{"id":13610343,"url":"https://github.com/jhallen/ivy-lang","last_synced_at":"2025-04-12T22:33:29.055Z","repository":{"id":147066562,"uuid":"50690122","full_name":"jhallen/ivy-lang","owner":"jhallen","description":"Ivy programming language","archived":false,"fork":false,"pushed_at":"2022-12-07T14:42:31.000Z","size":150,"stargazers_count":31,"open_issues_count":29,"forks_count":3,"subscribers_count":4,"default_branch":"master","last_synced_at":"2024-11-07T16:43:11.333Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jhallen.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2016-01-29T20:44:48.000Z","updated_at":"2024-01-12T18:07:08.000Z","dependencies_parsed_at":"2024-04-16T08:41:34.539Z","dependency_job_id":null,"html_url":"https://github.com/jhallen/ivy-lang","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhallen%2Fivy-lang","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhallen%2Fivy-lang/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhallen%2Fivy-lang/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jhallen%2Fivy-lang/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jhallen","download_url":"https://codeload.github.com/jhallen/ivy-lang/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248641865,"owners_count":21138282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T19:01:43.806Z","updated_at":"2025-04-12T22:33:28.777Z","avatar_url":"https://github.com/jhallen.png","language":"C","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"# Ivy\n\n- [Introduction](#Introduction)\n- [Invocation](#Invocation)\n- [Syntax](#Syntax)\n- [Variables](#Variables)\n- [Values](#Values)\n- [Expressions](#Expressions)\n- [Operators](#Operators)\n- [Functions](#Functions)\n- [Statements](#Statements)\n- [Intrinsic functions](#Intrinsics)\n- [Object Oriented Programming](#object-oriented-programming)\n\n## Introduction\n\nIvy is an extensible, dynamically typed, late binding language intended to\nbe used as an embedded command language.  It can also be used stand-alone:\nit can execute script files from the command line or presents a\nread-eval-print loop (REPL) to the user if no files are given.\n\nIvy's extensibility is based on the fact that statements are syntactically\nidentical to function calls.  Also blocks (surrounded by braces) may be used\nas function arguments.  Thus, new user-defined statements can be added just\nby defining functions.  Function arguments are packaged up as thunks and may\nhave their evaluation delayed and execution environment modified.  This\nallows user defined functions to do many of the things that traditional\nlanguage statements can do.\n\nA number of features make Ivy suitable as a command language.  Commands in\nIvy are just function calls, but with a convenient lightweight syntax. \nAlso, Ivy supports named arguments, default argument values and variadic\nfunctions.\n\nIvy source code is compiled to byte-code which is then interpreted.  Ivy's\ncompiler and interpreter are both event driven (meaning that they return to\nthe top level when more input is needed).  This allows Ivy to be easily\nembedded into other programs.\n\nIvy uses garbage collection for memory management.\n\nHere is some example code, to give you feel for Ivy.  Here is a recursive\nfunction to find the nth Fibonacci number:\n\n\tfn fib(n) {\n\t\tif n \u003c 2 {\n\t\t\treturn n\n\t\t} {\n\t\t\treturn fib(n - 1) + fib(n - 2)\n\t\t}\n\t}\n\nIt can be written more concisely as follows:\n\n\tfn fib(n) if(n \u003c 2, n, fib(n - 2) + fib(n - 1))\n\n\t-\u003eprint fib(30)\n\t832040\n\nA much more interesting non-recursive way to implement nth-Fibonacci is to\napply the Y-combinator to the almost-recursive definition of nth-Fibonacci. \nSee [The Y Combinator (Slight Return)](https://mvanier.livejournal.com/2897.html)\nfor an explanation (it will give you a headache if you've never seen this\nbefore). First, here is the strict version for non-lazy languages:\n\n\tfn Y(f) fn((x),x(x))(fn((x),f(fn((y),x(x)(y)))))\n\nHere is the almost-fibonacci:\n\n\tfn af(f) fn((n),if(n\u003c2,n,f(n-1)+f(n-2)))\n\nNow we create the nth-Fibonacci function:\n\n\t-\u003efib=Y(af)\n\t-\u003eprint fib(10)\n\t55\n\nIvy supports lazy evaluation of arguments, so we can also use the\nnormal-order Y-combinator:\n\n\tfn Y(f) {\n        \tfn inner(z) f(z(z))\n        \tinner(inner)\n\t}\n\nWe just have to indicate which arguments are to be evaluated lazily:\n\n\tfn af(\u0026f) fn((n),if(n\u003c2,n,(*f)(n-1)+(*f)(n-2)))\n\n\t-\u003efib=Y(af)\n\t-\u003eprint fib(10)\n\t55\n\nAs a final example, here is Donald Knuth's \"Man or Boy\" test for the ALGOL\n60 language:\n\n\tfn A(k, \u0026x1, \u0026x2, \u0026x3, \u0026x4, \u0026x5) {\n\t        fn B() {\n\t                k = k - 1\n\t                return A(k, B(), *x1, *x2, *x3, *x4)\n\t        }\n\t        if k \u003c= 0 {\n\t                return *x4 + *x5\n\t        } {\n\t                return B()\n\t        }\n\t}\n\n\t-\u003eprint A(10, 1, -1, -1, 1, 0)\n\t-67\n\nThis is a particularly clean implementation, almost as clean as the ALGOL 60\noriginal.  Languages that really support it have no need to adorn the\narguments in the call to A.  Take a look here for various versions of it:\n\n[https://rosettacode.org/wiki/Man_or_boy_test](https://rosettacode.org/wiki/Man_or_boy_test)\n\n\n## Invocation\n\n\tivy [-u] [-t] [-c] [filenames...]\n\n\t\tIf no filenames are given, ivy takes input from the keyboard\n\n\t\t-t  is a debugging aid which displays the parse tree as\n\t\t    commands are entered\n\n\t\t-u  is a debugging aid which unassembles the byte-code as\n\t\t    it's made\n\n\t\t-c  calculator mode.  prints the result of each command/\n\t\t    expression which is immediately executed\n\n\nFor example, here is \"hello world\" in Ivy interactive mode:\n\n\tivy\n\t-\u003eprint \"Hello, world\"\n\tHello, world\n\t-\u003e\n\nWhen calculator mode is used (-c option), the value of each command is\nprinted:\n\n\tivy -c\n\t-\u003e10;20\n\t10\n\t20\n\t-\u003e\n\n## Syntax\n\n### Comments\n\nIvy uses *#* to introduce comments.  Everything from an unquoted *#* to the\nend of the line is a comment.  *#* was chosen so that the very first line in\nan Ivy program can be *#!/usr/bin/ivy*, which makes the file into a script\nin UNIX.\n\n### Commands\n\nThere is a command format for function calls, where one or more commands\nare provided on a single logical line:\n\n\tcommand arg arg arg ; command arg arg arg ; ...\n\nNewlines are permitted within parenthesis, brackets and braces and in this\nway commands may span multiple physical lines.\n\nThe value of a list of commands is the value returned by the last command.\n\nArguments may be separated with whitespace or commas.  Arguments are\nexpressions.\n\nCommands are simple names or several names separated with periods (for\nmember selection).  If anything other than this is provided, the command and\nits arguments are treated as a list of expressions and they are sequentially\nevaluated (and the final value is the value of the last expression).\n\n\texpression expression expression ; command arg arg arg ; ...\n\nSometimes you may want to suppress the treatment of a simple name as a\ncommand (for example, to return a function).  To do this, enclose it within\nparenthesis:\n\n\t(name)\n\nNote that if you try to call a non-function value with zero arguments, the\nresult is the value itself.  This is relevant when you use Ivy\ninteractively (when invoked with the -c option):\n\n\t-\u003ea=10\n\t10\n\t-\u003ea\n\t10\n\n*a* alone on a line is treated as a command, and is called with zero\narguments, and returns itself.\n\n### Blocks\n\nCommands may appear at the top-level (non-enclosed) and within braces to\nmake a block.\n\n\t{ commands }\n\nThe entire block is treated as a single expression and may be used as an\nargument for a command.\n\nBlock structured statements such as *if* are just function calls but with\nblocks given as arguments.  The traditional *if...else if...else* statement\nlooks like this in Ivy:\n\n\tif a==1 {\n\t\tprint \"A is 1\"\n\t} a==2 {\n\t\tprint \"A is 2\"\n\t} a==3 {\n\t\tprint \"A is 3\"\n\t} {\n\t\tprint \"A is something else\"\n\t}\n\nIt is equivalent to calling *if* as a function like this:\n\n\tif(a==1, print(\"A is 1\"), a==2, print(\"A is 2\"), a==3, print(\"A is\n\t3\"), print(\"A is something else\"))\n\n### Lists\n\nA list of expressions is expected within parenthesis and brackets:\n\n\t(list)\t\t\tArgument list, parenthetical expression,\n\t\t\t\tor formal args for function definition.\n\n\t[list]\t\t\tAn object.\n\nA list is expected for function arguments and objects.  A list may also be\nprovided for simple parenthetical expressions.  In this case, the\nexpressions of the list are evaluated in turn from left to right, and the\nlast one provides the value of the parenthetical expression.\n\n\tfunc(2 3)\t\tCall func with two args: 2 and 3\n\n\t3*(2 3)\t\t\tResults in the value 9\n\nExpressions within a list can be separated with whitespace, commas or\nsemicolons.  These are all identical in this context:\n\n\tfunc(10 20 40)\t\tCall func with three args\n\tfunc(10,20;40)\t\tCall func with three args\n\tfunc(10;,20,,,40)\tCall func with three args\n\nNote that successive separators with nothing between them are ignored:\n\n\tfunc(1,2) is exactly the same as func(1,,,,2)\n\nNote however, that an empty set of parenthesis has meaning:\n\n\tfunc(() 20)\tCall func with two args: void and 20.\n\nSince whitespace may be used to separate expressions, ambiguities between\nsymbols which can be both infix and prefix operators result.  These\nambiguities are resolved by noting the typographical distance between the\nsymbol and its potential arguments.  The rule is that if the distance is\nbalanced, the operator is infix, otherwise it's prefix:\n\n\ta - b\t\t\tOne expression: subtract b from a\n\ta  -b\t\t\tTwo expressions: a and negated b\n\tf (7)\t\t\tTwo expressions: f and 7.\n\tf(7)\t\t\tOne expression: a call to f with arg 7\n\tf ( 7 )\t\t\tOne expression: a call to f with arg 7\n\tf  ( 7 )\t\tTwo expressions: f and 7.\n\nNote that tabs occur every 8 spaces for this purpose.\n\n## Variables\n\n### Scoping rules\n\nVariables set (assigned to) outside of functions are global variables.  They\nwill be visible in any function or scope.\n\nIf a variable is assigned to inside of a function and there is no global\nvariable of the same name, a local variable will be created within the\nfunction.\n\nThe *var* statement can be used to force the creation of local variables,\neven if there are global variables with the same name.\n\nFunctions have their own scope.  Local variables created within a function\nare only visible within the function.  Nested functions can see their\nparent's variables.  \n\nStatements and blocks do not have their own scope.  The only exception is\nthe *scope* statement.  Local variables created in its body will be visible\nonly within its body.\n\n### Assignment\n\nIvy supports nested multi-assignment via objects:\n\n\t[a,b,[x,y]] = [1,2,[9,10]]\n\nFunctions may return an object for multi-assignment:\n\n\tfn multi() [1 2 3]\n\n\t[a,b,c]=multi()\n\nIvy is unlike most languages in that it does not know that a variable will\nbe used as an L-value until very late (not until the assignment takes\nplace).  Therefore more things are legal L-values than you would expect. \nFor example, if a function returns a variable, it may be assigned to:\n\n\t-\u003ex=1\n\t-\u003efn rtnvar() x\n\t-\u003eprint x\n\t1\n\t-\u003ertnvar()=10\n\t-\u003eprint x\n\t10\n\nThis works for multi-assignment also:\n\n\t# Select a set of variables to assign to\n\tfn rtn(n) {\n\t\tif n==1 {\n\t\t\treturn [x,y,z]\n\t\t} {\n\t\t\treturn [i,j,k]\n\t}\n\t# Make sure they exist\n\tx=y=z=0\n\ti=j=l=0\n\t# Assign\n\trtn(1)=[1,2,3]\n\t# x, y and z have been assigned to.\n\nNote that the variables must already exist for this to work, otherwise they\nwill be created as local variables within the function.  They will still be\nassigned to, but it is probably not what you want.\n\n## Values\n\n### Objects\n\nObjects are catch-all data structures which may be indexed by number, symbol\nor string.  Objects indexed by number are similar to arrays.  Objects\nindexed by symbol are similar to structures.  Objects indexed by string are\nsimilar to hash tables.\n\nA mixture of index types may be used on the same object, but always\nrefer to different locations (symbol foo and string \"foo\" can have different\nvalues).\n\nAn automatic array is used for numbered indexing.  This array expands to\naccommodate whatever index is used.  If you store a value at index 0 and\nalso at index 999, then space for 1000 values will be allocated.\n\nWhen arrays are created all at once, the first item will be at index 0:\n\n\t-\u003eo=[10 20 30]\n\t-\u003eprint o[0]\n\t10\n\t-\u003eprint o[1]\n\t20\n\t-\u003eprint o[2]\n\t30\n\t-\u003e\n\nAuto-expanding hash tables are used for symbol and string indexing.  These\nhash tables expand to remain efficient as items are added to it.  Symbol\nindexing is faster than string indexing since, for symbols, the hash value\nis just the address of the symbol so the hash value does not have to be\nrecomputed or even looked up.\n\nObjects can be created either member by member:\n\n\to=[]\n\to.a=5\n\to.b=6\n\to(1)=7\n\to(\"foo\")=8\n\nor all at once:\n\n\to=[`a=5, `b=6, `1=7, `\"foo\"=8]\n\nObjects are assigned by reference.  This means that if you have an\nobject in one variable:\n\n\tx=[1 2 3]\n\nAnd you assign it to another:\n\n\ty=x\n\nAnd then change one of the members of x:\n\n\tx(0)=5\n\nThen the change will appear both in x and in y.\n\n### void\n\nThe special value *void* is returned when you attempt to look up an object\nmember, but it's missing.  *void* is equivalent to false or 0 when used with\n*if*.\n\nHere is an example:\n\n\t-\u003ea=[]\n\t-\u003eif a.b print(\"it exists\")\n\t-\u003ea.b=1\n\t-\u003eif a.b print(\"it exists\")\n\tit exists\n\t-\u003e\n\n### this\n\n*this* is a read-only symbol that returns the current activation record.  An\nactivation record is an Ivy object which is used to hold local variables.\n\n\t-\u003ea=10\n\t-\u003eb=20\n\t-\u003eprint this\n\t[ 1 at 0x0x1390498\n\t\t`a=10\n\t\t`mom=[ 0 at 0x0x13904e0 (globals) ]\n\t\t`b=20\n\t]\n\t-\u003eprint this.a\n\t10\n\t-\u003e\n\n### mom\n\n*mom* is an object member present in objects used as activation records.  It\nrefers to the object used as the next outer scope.  *mom* can be used to\naccess variables in the next outer scope:\n\n\t-\u003ex=10\n\t-\u003efn foo() {\n\t-\u003e\tvar x = 20\n\t-\u003e\tprint x\n\t-\u003e\tprint mom.x\n\t-\u003e}\n\t-\u003efoo\n\t20\n\t10\n\t-\u003e\n\n### Closures\n\nWhen functions are treated as data, they are always passed around as\nclosures.  A closure has the address of the code for the function and a\nreference to its environment- the object which was the activation record at\nthe time when the function was defined.  This object will become the next\nouter scope of the function (it's activation record's mom) when the function\nis called.\n\nThe environment part of a closure value can be replaced in various ways. \nThere is an operator to do this directly:\n\n\tmodified = original::new_environment\n\nAlso, when a closure is retrieved from an object with a member called *mom* via dot\nnotation, the object will replace the environment part of the closure:\n\n\t-\u003ex=10\n\t-\u003efn p() print(x)\n\t-\u003ea=[`mom=this, `x=20, `p=p]\n\t-\u003ep()\n\t10\n\t-\u003ea.p()\n\t20\n\nThis feature allows for object-oriented programming in Ivy.\n\n### Symbols\n\nThere are symbols:\n\n\t`hello\n\nSymbols can be tested for equality:\n\n\t`hello==`hello\t\t# True\n\t`hello==`goodbye\t# False\n\nThere is an interned string table for all symbols, so within Ivy, the check\nfor symbol equality is fast: symbols are identical if their addresses match.\n\nSymbols can be used as object indices.  Variables within a scope are\nindexed by symbols.  These are equivalent:\n\n\ta(`hello)=5\n\ta.hello=5\n\n### Integers\n\nIntegers may be entered in a variety of bases:\n\n\tx=0o127\t\t# Octal\n\tx=0x80\t\t# Hexadecimal\n\tx=0b11\t\t# Binary\n\tx=123\t\t# Decimal\n\nOctal, binary and hexadecimal digits may be interspersed with\nunderscores (_) for enhanced readability:\n\n\tx=0xADDED_FEE\n\nAlso the ASCII value of a character may be taken as an integer:\n\n\tx='A'\t\t# The value 65\n\nThe following \"escape sequences\" may also be used in place of a\ncharacter:\n\n\tx='\\n'\t\t# New-line\n\tx='\\r'\t\t# Return\n\tx='\\b'\t\t# Backspace\n\tx='\\t'\t\t# Tab\n\tx='\\a'\t\t# Alert (bell)\n\tx='\\e'\t\t# Escape\n\tx='\\f'\t\t# Form-feed\n\tx='\\^A'\t\t# Ctrl-A (works for ^@ to ^_ and ^?)\n\tx='\\010'\t# Octal for 8\n\tx='\\xFF'\t# Hexadecimal for 255\n\tx='\\\\'\t\t# \\\n\tx='\\q'\t\t# q (undefined characters return themselves)\n\n### Floating point numbers\n\n\tx=.125\n\tx=.125e3\n\tx=0.3\n\n### Strings\n\nString constants are enclosed in double-quotes:\n\n\tx=\"Hello there\"\n\nEscape sequences may also be used inside of strings.\n\n## Expressions\n\nAn expression is a single or dual operand operator with arguments, a\nconstant, a variable, a function definition, a block enclosed within braces,\na function call, an object or parenthetical expression.  Examples of each of\nthese cases follow:\n\n\t~expr\t\t\tSingle operand\n\n\texpr+expr\t\tDual operand\n\n\t25\t\t\tConstant\n\n\t(expressions)\t\tPrecedence\n\t{commands}\n\n\texpr(expr ...)\t\tFunction call\n\n\t[1 2 3 4]\t\tAn array object\n\n\t[`next=item `value=1]\tA structure object\n\n\t(fn (x,y) x*y)(3,5)\tCalling an anonymous function\n\n\n## Operators\n\nHere are the operators grouped from highest precedence to lowest:\n\n\t`\t\t\t\t# Named argument\n\n\t.\t\t\t\t# Member selection\n\n\t::\t\t\t\t# Modify environment part of closure\n\n\t( )\t\t\t\t# Function call\n\n\t\u0026 - ~ ! ++ -- *\t\t\t# Single operand\n\n\t\u003c\u003c \u003e\u003e\t\t\t\t# Shift group\n\n\t* / \u0026 %\t\t\t\t# Multiply group\n\n\t+ - | ^\t\t\t\t# Add group\n\n\t== \u003e \u003c \u003e= \u003c= !=\t\t\t# Comparison group\n\n\t\u0026\u0026\t\t\t\t# Logical and\n\n\t||\t\t\t\t# Logical or\n\n\t= \u003c\u003c= \u003e\u003e= *= /= %= += -= |= ^= .=\t# Pre-assignments\n\t: \u003c\u003c: \u003e\u003e: *: /: %: +: -: |: ^: .:\t# Post-assignments\n\n\t\\\t\t\t\t# Sequential evaluation: returns\n\t\t\t\t\t# result of right side.\n\n\t,\t\t\t\t# Expression separation\n\n\t;\t\t\t\t# Command separation\n\nA detailed description of each operator follows:\n\n### ` Symbol quoting\n\nThis operator can be used to prevent a symbol from being\nreplaced by its value.  Instead the symbol is used directly as the value. \nIt is also used to explicitly state the argument or member name in a\ncommand, function call or object.  For example:\n\n\topen `name=\"joe.c\",  `mode=\"r\"\n\tsquare(`x=5, `y=6)\n\t[`1=5 `0=7]\t\t\t# Array object\n\t[`x=10 `y=10]\t\t\t# Structure object\n\n### . Member selection\n\nThis operator is used to select a named member from an\nobject.  For example:\n\n\to=[`x=5, `y=10]\t\t# Create an object\n\tpr o.x\t\t\t# Print member x\n\tpr o.y\t\t\t# Print member y\n\tpr o(\"y\")\t\t# Same as above\n\n### :: Modify environment\n\nThis operator replaces the environment part of the closure\non the left side with the object on the right side.\n\n\tx = 2\n\tfn foo(n) { print x * n }\n\n\t# Call foo in its recorded environment-\n\t# in this case, the global variables\n\n\tfoo(7)\t\t\t# Prints 14\n\n\tmy_obj=[`mom=this, `x=3]\n\n\t# Call foo with my_obj as its environment\n\n\tfoo::my_obj(7)\t\t# Prints 21\n\n### ( ) Function call\n\nThis operator calls the function resulting from the\nexpression on the left with the arguments inside of the parenthesis.  This\noperator can also be used for object member selection and for string\ncharacter selection and substring operations.  Examples of each of these\nfollow:\n\n\tx.y(5)\t\t\t# Call function y in object x\n\n\tz(0)=1, z(1)=2\t\t# Set numbered members of an object\n\n\tz(\"foo\")=3, z(\"bar\")=4\t# Set string members of an object\n\n\tz(`foo)=3, z(`bar)=4\t# Set symbol members of an object\n\n\tpr \"Hello\"(0)\t\t# Prints 72\n\n\tpr \"Hello\"(1,3)\t\t# Prints \"el\" (selects substring\n\t\t\t\t# beginning with first index and\n\t\t\t\t# end before second).\n\n\n### - Negate\n\n### \u0026 Address of.\n\nThis operator converts its operand into a thunk (a zero\nargument nameless function thunk with no environment).  The thunk can\nbe called with () or *.\n\n### ~ Bit-wise one's complement\n\n### ! Logical not\n\n### ++ Pre or post increment\n\nPre or post increment depending on whether it precedes or follows\na variable\n\n### -- Pre or post decrement\n\n### * Indirection\n\nThis prefix operator is used to call a zero argument\nfunction or thunk.\n\n\tfn set(\u0026a b) {\n\t\t*a=b\n\t}\n\n\tx=3\n\tset x 10\t# Set x to 10\n\tprint x\t\t# Prints 10\n\n### \u003c\u003c Bit-wise shift left\n\n### \u003e\u003e Bit-wise shift right\n\n### * Multiply\n\n### / Divide\n\n### \u0026 Bit-wise AND\n\n### % Modulus (Remainder)\n\n### + Add or concatenate\n\nIn addition to adding integers, this operator concatenates\nstrings if strings are passed to it.  For example:\n\n\tprint \"Hello\"+\" There\" \t# Prints \"Hello There\"\n\n\"+\" will also append an element on the right into an\narray object on the left:\n\n\ta=[1 2 3]\n\ta+=4\t\t\t# a now is [ 1 2 3 4 ]\n\n\tprint []+1+2+3+4\t# same as print [1 2 3 4]\n\tprint []+1+2+3+[4 5]\t# same as print [1 2 3 [4 5]]\n\n### - Subtract\n\n### | Bit-wise or\n\nIf objects are given as arguments to OR, OR unions the\nobjects together into a single object.  If the objects have\nnumerically referenced members, OR will append the array on the\nright to the array on the left.  For example:\n\n\ta=[1 2 3]\n\tb=[4 5 6]\n\ta|=b\t\t\t# a now is [1 2 3 4 5 6]\n\n### ^ Bit-wise Exclusive OR\n\n### == Equal\n\nReturns 1 (true) if arguments are equal or 0 (false) if arguments are not\nequal.  Can be used for strings, numbers, symbols and objects.  For objects,\n\"==\" tests if the two arguments are the same object, not if the two\narguments have equivalent objects.\n\n### \u003e Greater than\n\n### \u003e= Greater than or equal to\n\n### \u003c  Less than\n\n### \u003c= Less than or equal to\n\n### != Not equal to\n\n### \u0026\u0026 Logical and\n\nThe right argument is only evaluated if the left argument is\ntrue (non-zero).\n\n### || Logical or\n\nThe right argument is evaluated only if the left argument is\nfalse (zero).\n\n### = Pre-assignment\n\nThe right side is evaluated and the result is stored in the variable\nspecified on the left side.  The right side's result is also returned.\n\n### : Post-assignment\n\nThe right side is evaluated and the result is stored in the\nvariable specified on the left side.  The left side's original value\nis returned.\n\n### X= Pre-assignment group\n\nThese translate directly into: \"left = left X right\"\n\n### X: Post-assignment group\n\nThese translate directly into: \"left : left X right\"\n\nNotes on assignment groups:\n\n\t.=\ttranslates into \"left = left . right\" and is\n\t\tuseful for traversing linked lists.  For example:\n\n\t\tfor list=void\\ x=0, x!=10, ++x {\t# Build list\n\t\t  list=[`next=list, `value=x]\n\t\t}\n\n\t\t(note, this builds the list in reverse\n\t\torder.  9,8,7...)\n\t\t\t\t\n\t\tfor a=list, a, a.=next {\t# Print list  (second\n\t\t\t\t\t\t# expr evals for 0)\n\t\t\tprint a.value\n\t\t}\n\n\tx+:1\tIs the same as x++\n\tx+=1\tIs the same as ++x\n\n\n\":\" is useful for shifting the value of variables around.  In this example,\na gets b, b gets c, and c gets 5:\n\n\ta:b:c:5\n\n\":\" is also useful for swapping the values of variables.  In this example, a\ngets swapped with b:\n\n\ta:b:a\n\n### \\ Sequential evaluation\n\nThe left and then the right argument are evaluated and the\nresult of the right argument is returned.\n\n### , Argument separator\n\nWhen this is used in statements which require only a single\nexpression, it has the same effect as \\\n\n\n## Functions\n\n### Function declaration syntax:\n\nCommand format named function declarations:\n\n\tfn name(args) expr\n\n\tfn name(args) {\n\t       \tbody\n\t}\n\nExpression format named function declarations:\n\n\tfn(name, (args), body-expr)\n\nCommand format anonymous function:\n\n\t{ fn (args) body-expr }\n\nExpression format anonymous function:\n\n\tfn((args), body-expr)\n\nThese are all equivalent:\n\n\tfn square(x) x*x\n\n\tfn square (x) {\n\t\tx*x\n\t}\n\n\tsquare = { fn (x) x*x }\n\n\tsquare = fn((x), x*x)\n\nThe last forms define so-called \"Lambda\" (anonymous) functions.  You\ncan call anonymous functions without assigning them:\n\n\tx=fn((x),x*x)(6)\t# x gets assigned 36\n\nYou can also define named functions right in the middle of an expression,\nand immediately call them:\n\n\ty=fn(square,(x),x*x)(5)\t# y gets assigned 25\n\tprint square(6)\t\t# Prints 36\n\n### Argument lists\n\nYou may specify zero or more formal arguments.  Each argument must be\nprovided during a function call, or an error occurs.\n\n\tfn mm(x,y) x*y\n\n\tmm(1)      --\u003e \"Error: Missing arguments\"\n\n\tmm(1,2,3)  --\u003e \"Error: Too many arguments\"\n\n\tmm(3,4)    --\u003e returns 12.\n\nHowever, default values may be specified.  If an argument with a\ndefault value is missing, no error occurs and the default value is used\ninstead:\n\n\tfn mm(x=5,y=6) x*y\n\n\tmm()       --\u003e x=5,y=6 --\u003e 30\n\n\tmm(6)      --\u003e x=6,y=6 --\u003e 36\n\n\tmm(6,2)    --\u003e x=6,y=2 --\u003e 12\n\nExpressions may be used for the default values.  The expressions are\nevaluated when the function is called (not when defined).  The evaluation\nhappens in the body of the function (where the expression may declare local\nvariables).  The order is left to right, and expressions on the right may\nuse arguments to their left.\n\n\tfn zz(x=5,y={ var q=5; x }) x*y+q\n\n\tq=10\n\n\tzz()      --\u003e x=5,q=5,y=5  --\u003e 25\n\n\tzz(3)     --\u003e x=3,q=5,y=3  --\u003e 14\n\n\tzz(3, 3)  --\u003e x=3,q=10,y=3 --\u003e 19\n\nArguments may be passed by name.  When an argument is passed by name, a\nlocal variable of that name is injected into the function's body.  Variables\nmay be created which are not in the formal argument list.  Named and\nunnamed arguments may be mixed in the same function call.  The named\narguments have no effect on how the unnamed arguments are processed: the\nunnamed arguments are matched up left-to-right with the formal argument list\nas if there were no provided named arguments.  This means that an unnamed\nargument may overwrite a named argument if it occurs after the named\nargument, or vice-versa.  If there were fewer unnamed arguments than in the\nformal argument list, and the missing ones were declared with default\nvalues, and they were not provided with a named argument, then the default\nvalue is used.  If arguments without default values are missing, and they\nwere not provided by a named argument, an error occurs.\n\n\tfn zz(x,y,z=10) x+y+z+e\n\n\tzz(`e=1,`y=2,3) --\u003e x=3, y=2, z=10, e=1 --\u003e 16\n\nExtra unnamed arguments may be collected into an object with your choice of\nname with the following syntax:\n\n\tfn zz(x,extras...) {\n\t\tprint \"x = \", x\n\t\tforindex z extras {\n\t\t\tprint \"extras(\", z, \") = \", extras(z)\n\t\t}\n\t}\n\n\tzz(5,6,7,8) --\u003e prints\n\n\tx = 5\n\textras(0) = 6\n\textras(1) = 7\n\textras(2) = 8\n\n### Function execution\n\nWhen the body of a function gets control, its activation record (the\nobject used for the function's local variables) gets several variables:\n\n\n\n\tthis\tThe function's activation record itself as an object\n\n\t\tprint this\tPrints all local variables\n\n*this* is not a variable, it's a special symbol that is replaced by the\nactivation record object.\n\n\tmom\tThe next outer lexical scope.\n\nMom is a normal variable.  If you assign it, the next outer lexical scope is\nchanged to the specified object.\n\nFunctions may be assigned to variables and passed to other functions.  For\nexample you can define a function *apply* which applies a function to an\nargument:\n\n\tfn apply(x y) {\n\t\treturn x(y)\n\t}\n\n\tfn square(x) {\n\t\treturn x*x\n\t}\n\n\tprint apply(square,5)\t# Prints 25\n\n\nFunctions can return other named or unnamed functions.  (Remember to enclose\nthe function name in parenthesis to suppress command interpretation, or use\nreturn).  For example:\n\n\tfn square(x) {\n\t\treturn x*x\n\t}\n\n\tfn foo() {\n\t\treturn square\n\t}\n\n\tprint foo()(4)\t\t# Prints 16\n\n\tfn bar() {\n\t\t(fn((x),x*x))\t# Return lambda function\n\t}\n\n\tprint bar()(4)\t\t# Prints 16\n\nFunctions can be declared inside of other functions.  This is\nespecially useful for manipulating the argument lists of pre-existing\nfunctions.  Suppose you had an averaging function:\n\n\tfn avg(func from to) {\n\t\tvar x, accu = 0\n\t\tfor x = from, x != to, ++x {\n\t\t\taccu += func(x)\n\t\t}\n\t\treturn accu / (to - from)\n\t}\n\nAnd suppose that you have another function which takes two arguments which\nyou'd like its average, but with one argument set to a constant:\n\n\tfn add(a b) {\n\t\treturn a+b\n\t}\n\nYou could do this by using a function which creates a function\nwhich calls add, but with one argument set to a constant:\n\n\tfn curry(y) {\n\t\treturn fn((x), add(x,y))\n\t}\n\n\tNow 'avg' can be used on 'add':\n\n\tprint avg(curry(20),0,10) # Prints 24\n\n### Delayed evaluation of arguments\n\nArguments may be prefixed with ampersands to prevent them from being\nimmediately evaluated.  The marked argument is packaged up as a \"thunk\"- a\nzero argument function with the environment set as the calling function's\nactivation record.  The function may call the thunk whenever it wants,\neither by using the normal function call syntax or by using the indirection\noperator, '*'.\n\nFor example, here is a function which sets a specified variable to\na value:\n\n\tfn set(\u0026x,y) { *x = y }\n\n\tset q 10\n\n\tprint q\t--\u003e prints 10\n\n## Statements\n\n### If statement\n\n\tif test-expr-1 {\n\t\texpr-1\n\t} test-expr-2 {\n\t\texpr-2\n\t} test-expr-3 {\n\t\texpr-3\n\t} {\n\t\totherwise-expr\n\t}\n\n\tif(test-expr-1,expr-1,test-expr-2,expr-2,...,otherwise-expr)\n\n### Foreach statement\n\n\tforeach name expr block\n\n\tforeach `label name expr block\n\nSets the variable *name* to each element in the object resulting from *expr*\nand executes the *block*.\n\n*foreach* may optionally be labeled for matching with the argument to\n*break* and *continue*\n\n\t-\u003eforeach a [1 2 3] print(a)\n\t1\n\t2\n\t3\n\t-\u003e\n\n### Forindex statement\n\n\tforindex name expr block\n\n\tforindex `label name expr block\n\nSets the variable *name* to each valid index into the object resulting from\n*expr* and executes the block.\n\n*forindex* may optionally be labeled for matching with the argument to\n*break* and *continue*\n\n\t-\u003eforindex a [10 20 30] print(a)\n\t0\n\t1\n\t2\n\t-\u003e\n\n### Loop statement\n\n\tloop block\n\tloop `label block\n\nThe block gets repeatedly executed until a 'break' or 'until' statement\nwithin the block terminates the loop.\n\n*loop* may optionally be labeled for matching with the argument to *break*\nand *continue*.\n\n### While statement\n\n\twhile expr block\n\n\twhile `label expr block\n\nThe block is repeatedly executed if the expression is true.\n\n*while* may optionally be labeled for matching with the argument to *break*\nand *continue*.\n\n### For statement\n\n\tfor init, test, incr block\n\n\tfor `label init, test, incr block\n\nThis is a shorthand for the following while statement:\n\n\tinit\n\twhile test {\n\t\tblock\n\t\tincr\n\t}\n\nThus,\n\n*init* is usually used as an index variable initializer\n\n*test* is the loop test\n\n*incr* is the index variable incrementer\n\n*for* may optionally be labeled for matching with the argument to *break*\nand *continue*\n\n### Return statement\n\n\treturn\n\n\treturn expr\n\n*return* exits the function it is executed in with the given return value or\nwith *void* if no value is given.\n\n### Break statement\n\n\tbreak\n\n\tbreak LABEL\n\n*break* jumps out of the innermost or labeled loop\n\n### Continue statement\n\n\tcontinue\n\n\tcontinue LABEL\n\n*continue* jumps to the beginning of the innermost or labeled loop.\n\n### Until statement\n\n\tuntil expr\n\n*until* exits the loop it's in if *expr* is true.\n\n### Var statement\n\n\tvar a, b, c\n\nDeclare local variables.  The variables may also have initializers:\n\n\tvar a=10, b=20\n\n\tfn raise(a) {\n\t\tvar x\n\t\tfor x=1, a, x\u003c\u003c=1\\ --a\n\t\treturn x\n\t}\n\n### Scope statement\n\n\tscope expr expr ...\n\nThe expressions are evaluated in their own scope.  If they create local\nvariables, they will not show up in the outer scope.  The value of the last\nexpression is returned.\n\n## Intrinsics\n\nHere are functions that are always built-in.\n\n### loadfile\n\n\ta = loadfile(\"name\")\n\nExecute an Ivy source file within an empty global variable scope.  The\nexecuted code will only see Ivy's built-in functions.  The final value is\nreturned.\n\n### len\n\n\tlen(a)\n\nReturns the length of string 'a' or number of elements in\narray 'a'\n\n### print\n\n\tprint(...)\n\nPrints the arguments\n\n### printf\n\n\tprintf(...)\n\nC printf\n\n\tprintf \"%d\\n\", 17\n\n### get\n\n\ta=get()\n\nGet a line of input as a string.  Returns void if there is\nno more input.\n\n\t# Add line numbers to input\n\tn=1\n\twhile a=get() {\n\t\tprint n++, \" \", a\n\t}\n\n### atoi\n\n\tx=atoi(\"2\")\n\nConverts a string to a number\n\n### itoa\n\n\ts=itoa(20)\n\nConvert a number to a string\n\n### clear\n\n\tclear(...)\n\nFrees the values of the listed variables and sets the\nvariables to VOID.\n\n### dup\n\n\tb=dup(a)\n\nMake a duplicate of an array/object\n\n### match\n\n\tmatch(string,pattern,result-variables...)\n\nRegular expression pattern matching\n\nReturn true if string matches pattern (which must be a\nregular expression string).\n\nIf there is a match, each spanned area is stored in the\ncorresponding result variable:\n\n\tmatch \"fooAbar\" \".*A.*\" a b\n\n\t\ta now has \"foo\" and b has \"bar\".\n\nIt is ok to supply fewer result variables than there are\nspanning areas.\n\n\tThe regular expression string may be made of:\n\n                    .      matches any character.\n                    *      matches zero or more of the previous character\n                           (generates a result string).\n                    +      matches one or more of the previous character\n                           (generates a result string).\n                    [...]  matches one character in the list ...\n                           ranges may be specified with the list, such\n                           as 0-9, a-z, etc.\n                    x      other characters match themselves only.\n\nNote that the entire string must be spanned for a match to\noccur:  It is as if the pattern always begins with ^ and\nends with $.\n\n## Math functions\n\nThe following functions from the standard C library are provided:\n\n\tsin() cos() tan() asin() acos() atan() atan2()\n\tsinh() cosh() tanh() asinh() acosh() atanh()\n\texp() log() log10() pow() hypot() sqrt()\n\tfloor() ceil() int() abs() min() max() erf() erfc()\n\tj0() j1() jn() y0() y1() yn()\n\n## Object-Oriented Programming\n\nBesides being available for use by the programmer, Ivy's objects are used\ninternally for activation records.  This means that a function's local\nvariables are implemented as object members.\n\nThe only difference between regular objects and objects used for activation\nrecords is the presence of a member called *`mom*.  This member refers to\nthe next outer scoping level.  Ivy uses lexical scoping, so the chain of\nnext outer levels include (for the case of nested functions) the parent\nfunction's (*not* the calling function's) activation record, then the global\nvariables (when modules are loaded, they each get their own object for\nglobal variables), then finally the object containing Ivy's built-in\nfunctions, such as *print*.  During symbol lookup, the chain of moms is\nsearched for the symbol.\n\nWhen functions are passed around, they always come in closures.  A closure\ncontains a pointer to the function's code and a pointer to the environment\nwhere it was defined, which is the activation record in effect at that time. \nThe environment is the object that becomes the function's activation\nrecord's mom when the function is called.\n\nWith this understanding, we can proceed towards implementing object-oriented\nprogramming in Ivy.  There are two ways to do it: the direct method and the\nclosure method.  They are equivalent, and will be shown side by side.\n\nFirst we need to define a class to hold member functions and static\nvariables (variables shared by all instances of the class).  In the direct\nmethod, we just create an object, but with *`mom* set to the current\nactivation record, in this case the one containing the global variables:\n\n\tMy_class=[`mom=this]\n\nThe special symbol *this* always refers to the object being used as the\ncurrent activation record.\n\nWe can add a member function by assigning a lambda (nameless) function to a\nmember name (*show* in this case):\n\n\tMy_class.show = fn((), {\n\t\tprint x\n\t})\n\nOr we can do this same thing by using dot notation in the function\ndeclaration:\n\n\tfn My_class.show() {\n\t\tprint x\n\t}\n\t\n\tfn My_class.increment() {\n\t\tx = x + 1\n\t}\n\nOr we could even have included them when we created the object in the first\nplace:\n\n\tMy_class = [\n\t\t`mom = this\n\t\n\t\t`show = fn((), {\n\t\t\tprint x\n\t\t})\n\t\n\t\t`increment = fn((), {\n\t\t\tx = x + 1\n\t\t})\n\t]\n\nIn the closure method, we write a function which returns its activation\nrecord.  This will be used as the class.  Any nested functions will become\nmember functions:\n\n\tfn create_My_class() {\n\t\n\t\tfn show() {\n\t\t\tprint x\n\t\t}\n\t\n\t\treturn this\n\t}\n\n\tMy_class = create_My_class()\n\nThe closure method has the advantage of not requiring you to explicitly set\n*mom*, in case that bothers you.  *My_class.mom* will still exist, however. \nIt was set in the activation record when then function was invoked.\n\nWe can add more member functions after the class has been created (by either\nmethod: assigning lambda functions to member names or by declaring named\nfunctions with the dot notation):\n\n\tfn My_class.increment() {\n\t\tx = x + 1\n\t}\n\nNotice that member functions refer to instance variables as in C++ or Java. \nThere is no need to prefix each instance variable with *self* or *this* as\nin most languages with prototype based object systems.  On the other hand,\ncalls to sibling member functions should use dot notation:\n\n\tfn My_class.inc_and_show() {\n\t\tthis.increment()\n\t\tthis.show()\n\t}\n\nWe need a constructor to create class instances.  This constructor\nshould be a class member.  For the direct method, we write this:\n\n\tfn My_class.instance(i=[]) {\n\t\ti.x = 10\n\t\ti.mom = My_class\n\t\treturn i\n\t}\n\nNotice that an empty object is provided as the default value for *i*.  If\nthe *i* argument is missing, this default empty object will become the\ninstance.  If the argument is provided, then the caller provided object is\nused for the instance.  We will use this capability later for derived\nclasses, where we want to allow the derived class constructor to call the\nbase class constructor.\n\nNext, we create an instance variable x and set it to a default value 10.\n\nFinally, we set the mom of the instance to the class so that if we call\nmember functions on the instance, the ones defined in the class will be\nfound.\n\nFor the closure method, the instance creation function is a nested function\nof *create_My_class* which returns its activation record as the instance. \nWe separate out a construction function from the instance allocator so that\nit may be later called by derived class constructors:\n\n\tfn create_My_class() {\n\n\t\tfn construct(i) {\n\t\t\ti.x = 10\n\t\t}\n\n\t\tfn instance() {\n\t\t\tconstruct(this)\n\t\t\treturn this\n\t\t}\n\n\t\tfn show() {\n\t\t\tprint x\n\t\t}\n\n\t\tfn increment() {\n\t\t\tx = x + 1\n\t\t}\n\n\t\treturn this\n\t}\n\nNow we create some instances of the class:\n\n\tinstance_1 = My_class.instance()\n\tinstance_2 = My_class.instance()\n\nThe instances are now ready and we can call their member functions:\n\n\tinstance_1.show()   --\u003e prints 10\n\tinstance_1.increment()\n\tinstance_1.show()   --\u003e prints 11\n\tinstance_2.show()   --\u003e prints 10\n\nBut, the member functions are not in the instance objects, and even then you\nwould expect the called function's activation record's mom to be the class,\nnot the instance.  So what is going on?\n\nThe member functions are found because we explicitly set *i.mom* to\n*My_class* in the constructor with the direct method or it was implicitly\nset this way in the closure method.  In either case, the symbol lookup\nfollows the mom chain as usual.  It finds the closure for *show* or\n*increment* with the recorded environment being the class object.\n\nBut the class object is not used for the member function's environment (and\nhere we come to the heart of Ivy's object system).  This is because the . \noperator replaces the environment part of the closure retrieved from the\nsymbol on its right side (*show* or *increment*) with the object it\nbegan the symbol search in on its left side (*instance_1*), but only if\nthat object contains a mom.\n\n[If the object did not contain a mom, then the environment replacement does\nnot happen.  Instead the recorded environment is used.  This allows you to\nuse non-class objects as simple containers for other object's member\nfunctions:\n\n\tz=[]\n\tz.show = instance_1.show\n\tz.show()  --\u003e prints 11\n\nThe environment replacement is happening in the *instance_1.show* part of\nthe assignment above, so *instance_1* is the mom for *show*'s activation\nrecord.  Since *z* does not have a mom, *z* is not used as the\nenvironment when we finally call show in *z.show()*.]\n\nThe bottom line is that a function does not know that it is a member\nfunction and certainly not which instance to operate on until it has been\naccessed via the dot notation.  A non-obivious consequence of this is that\nmember functions must use dot notation when calling sibling member\nfunctions, even though the dot notation is not required to find them.\n\nFor example, we could have a function which increments and shows.  We might\ntry writing it like this:\n\n\tfn My_class.inc_and_show() {\n\t\tincrement()\n\t\tshow()\n\t}\n\nBut it will not work.  The increment will look up *x* starting in the\nenvironment where it was defined.  This is either in the global environment\nfor the direct method or in the class object for the closure method.  Either\nway, it's not accessing the *x* in the instance.\n\nThe correct way to write this function is as follows:\n\n\tfn My_class.inc_and_show() {\n\t\tmom.increment()\n\t\tmom.show()\n\t}\n\n*Mom* will refer to the instance object when inc_and_show is called.  In\nthis case, you could replace *mom* with *this*.  But it is better to use\n*mom*, since the member function should not be modifying the activation\nrecord of *inc_and_show* itself.\n\n### Inheritance\n\nWe can create a new class based on an existing class like this:\n\n\tDerivedClass = [ `mom = MyClass ]\n\nSince *DerivedClass*'s mom is set to *MyClass*, symbol lookup for member\nfunctions will find ones defined in *MyClass* if they are not directly\nprovided in *DerivedClass*.\n\nIt will need a new instance constructor:\n\n\tfn DerivedClass.construct(i=[]) {\n\t\ti = MyClass.construct(i)\n\t\ti.y = 20\n\t\ti.mom = DerivedClass\n\t\treturn i\n\t}\n\nNotice how we are calling the base class's constructor, but then elaborating\nthe instance by adding a new instance variable *y*.  Naturally the instance's\nmom is replaced (it had been set to *MyClass* by *MyClass*'s constructor) so\nthat it is set to *DerivedClass*.\n\nAnd we will override one of the member functions:\n\n\tfn DerivedClass.show() {\n\t\tprint \"Derived\"\n\t\tprint x\n\t\tprint y\n\t}\n\nUsing the closure method, we provide a new class creation function and then\ncall it:\n\n\tfn MyClass.create_DerivedClass() {\n\n\t\tfn construct(i) {\n\t\t\tmom.mom.construct(i)\n\t\t\ti.y = 20\n\t\t}\n\n\t\tfn show() {\n\t\t\tprint \"Derived\"\n\t\t\tprint x\n\t\t\tprint y\n\t\t}\n\n\t\treturn this\n\t}\n\n\tDerivedClass = MyClass.create_DerivedClass()\n\n*create_DerivedClass* is defined as a member of *MyClass* so that when\nit's called, *create_DerivedClass*'s activation record's mom ends up being\n*MyClass*.\n\nAn alternative way of defining *create_DerivedClass* which does not\ninvolve modifying *MyClass* at all is as follows:\n\n\tfn create_DerivedClass() {\n\n\t\tmom = MyClass\n\n\t\tfn construct(i) {\n\t\t\tmom.mom.construct(i)\n\t\t\ti.y = 20\n\t\t}\n\n\t\tfn show() {\n\t\t\tprint \"Derived\"\n\t\t\tprint x\n\t\t\tprint y\n\t\t}\n\n\t\treturn this\n\t}\n\n\tDerivedClass = create_DerivedClass()\n\nNotice that we replaced *create_DerivedClass*'s activation record's mom\nduring execution to connect it with its base class.  Since Ivy is a late\nbinding language, this is perfectly legal to do.\n\nIn either case, the new construction function adds a new instance variable,\n*y*, as in the direct method.  It also calls the base class constructor. \nNotice that we follow mom twice to find it.  Remember that the construction\nfunction will have its own activation record when it's called, so one \"mom.\"\nis needed to traverse to *DerivedClass*.  The second \"mom.\" traversed back\nto *My_class*, which has the construct function we want to call.\n\nNotice that we do not provide a new instance allocation function.  The one\nin *My_class* does the right thing, so there is no need to replace it.  It\nwill find *DerivedClass*'s *construct* function.\n\nNow we can create an instance of the derived class:\n\n\tderived_instance_1 = DerivedClass.instance()\n\n\tderived_instance_1.show()  --\u003e Prints:\n\n\tDerived\n\t10\n\t20\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhallen%2Fivy-lang","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjhallen%2Fivy-lang","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjhallen%2Fivy-lang/lists"}