// nil is the undefined object // integers, floats, strings are as usual // # is a symbol literal print(nil, " ", 42, " ", 3.14, " string ", #Symbol, " newline \n"); // the prototypical object types used in the implementation have global names // e.g., Object is the prototypical object at the root of the delegation hierarchy print("Object => ", Object, "\n"); // this prints as print("Lambda => ", Lambda, "\n"); // this prints as print("Closure => ", Closure, "\n"); // this prints as // create a new object instance by asking an existing one to be the delegate for a new instance // e.g., to create a new object that delegates to the prototype Object... o = Object.new(); print("o = Object.new() => ", o, "\n"); // this prints as <> because the number of <> surrounding the name tells you // how many levels of delegation were needed before the __name__ property was found // arguments can be positional and/or key:value pairs // for the new() method, the arguments become the properties of the newly created object o = Object.new(foo: 42, bar: 666); print("o = Object.new(foo:42, bar: 666) => ", o, "\n", full: 1); print("o.foo => ", o.foo, "\n"); // to create a new type make a prototype with a __name__ that delegates to another prototype Point = Object.new(__name__: #Point); // objects can be created from the new prototype because it delegates to the Object prototype, // in other words the new prototype 'inherits' Object.new() // objects created from the new prototype will inherit its __name__ property print("Point.new() => ", Point.new(), "\n"); print("Point.new(x: 3, y: 4) => ", Point.new(x: 3, y: 4), "\n", full: 1); // anonymous functions are written: "(parameters...) { statements... }" // all statements return values // the last statement in a block provides a return value for the entire function double = (x) { x+x }; print("twice 21 is ", double(21), "\n"); // use the keyword argument "full:x" (where x is non-nil) to make the print primitive // recursively print the entire contents of any objects it encounters print("double => ", double, "\n", full:1); // anonymous functions installed as properties of a prototype become methods // for all objects that delegate to the prototype Point.magnitude() { sqrt(self.x * self.x + self.y * self.y) } m = Point.new(x: 3, y: 4).magnitude(); print("Point.new(x:3, y:4).magnitude() => ", m, "\n"); // functions close over their dynamic environment when created // (yes, I know, something needs to be done about all the nasty semicolons) makeCounter(n) { n = n - 1; // make the counter return n the first time it is called () { print(__env__(), "\n", full:1); n = n + 1 } // the counter is an anonymous function, closing over n, that increments n } counter = makeCounter(40); print(counter(), "\n"); print(counter(), "\n"); print(counter(), "\n"); print(counter(), "\n"); test(x) { print(x, " "); if (x) print("yes\n") else print("no\n") } test(nil); test(1); test("hello"); nfib(n) { if (n < 2) 1 else nfib(n-1) + nfib(n-2) + 1 } print(nfib(5), "\n"); print(nfib(15), "\n"); assert(x) { if (!(eval(x))) { print("\nassertion failed: ", codeString(x), "\n"); exit(1); } } assert.fixed = #t; // do not evaluate arguments (x will be an AST suitable for eval()) refute(x) { if (eval(x)) { print("\nrefutation failed: ", codeString(x), "\n"); exit(1); } } refute.fixed = #t; refute; assert(1 == 1); refute(1 == 0); assert(0 < 1); refute(1 < 1); refute(2 < 1); assert(0 <= 1); assert(1 <= 1); refute(2 <= 1); refute(0 >= 1); assert(1 >= 1); assert(2 >= 1); refute(0 > 1); refute(1 > 1); assert(2 > 1); refute(0 == 1); assert(1 == 1); refute(2 == 1); assert(0 != 1); refute(1 != 1); assert(2 != 1); assert(16 << 0 == 16); assert(16 << 1 == 32); assert(16 << 2 == 64); assert(16 << 3 == 128); assert(16 >> 0 == 16); assert(16 >> 1 == 8); assert(16 >> 2 == 4); assert(16 >> 3 == 2); print(0b101010, " "); print(052, " "); print(42, " "); print(0x2a, "\n"); bin__(n, b, w) { if (n >= 2 || w > 1) bin__(truncate(n / 2), b, w - 1); print(n % 2); } assert((0b1110 | 0b0111) == 0b1111); assert((0b1110 ^ 0b0111) == 0b1001); assert((0b1110 & 0b0111) == 0b0110); nt = 0; nf = 0; t() { nt = nt + 1; #t } f() { nf = nf + 1; nil } refute(f() || f()); assert(nt == 0); assert(nf == 2); assert(f() || t()); assert(nt == 1); assert(nf == 3); assert(t() || f()); assert(nt == 2); assert(nf == 3); assert(t() || t()); assert(nt == 3); assert(nf == 3); refute(f() && f()); assert(nt == 3); assert(nf == 4); refute(f() && t()); assert(nt == 3); assert(nf == 5); refute(t() && f()); assert(nt == 4); assert(nf == 6); assert(t() && t()); assert(nt == 6); assert(nf == 6); 1 || ({ print("fail\n"); exit(1) }); nil && ({ print("fail\n"); exit(1) }); nil || print("ok\n"); 1 && print("ok\n"); print(eval(42), "\n"); MyType = Object.new(__name__: #MyType); print("----\n"); MyType.__eval__(self) { print("MyType.__eval__() invoked\n"); 42; } myType = MyType.new(); print(eval(myType), "\n"); Object.print() { print(self) } Object.println() { self.print(); print("\n") } (){}.println(); x = 42; print("====\n"); (42).println(); "hello".println(); nil.println(); nil.__delegate__.println(); nil.__delegate__.__delegate__.println(); nil.__delegate__.__delegate__.__delegate__.println(); Object.dump() { print("["); keys = self.keys(); for (key in keys) print("KEY: ", key, "\n"); print("]\n"); } p = Point.new(x: 3, y: 4); p.dump(); #Symbol.println(); #Symbol.__delegate__.println(); #Symbol.__delegate__.__delegate__.println(); #Symbol.__delegate__.__delegate__.__delegate__.println(); print("POINT ", Point, "\n"); p = [x:5, y:12]; print("P ", p, "\n"); p[#__delegate__] = Point; print("P ", p, "\n"); q = [__delegate__:Point, x:5, y:12]; print("Q ", q, "\n"); print("P.mag ", p.magnitude(), "\n"); o = [bar:666, 1, [2, 3, 6*7], foo:42]; print(o, "\n", full:1); o.dump(); print(len("Hello"), "\n"); print(len(#Goodbye), "\n"); print(len([]), "\n"); print(len([1]), "\n"); print(len([1, 2]), "\n"); printelts(x) { n = len(x); print(n, "\n"); i = 0; while (i < n) { print(i, ": ", x[i], "\n"); i = i + 1; } x; } f() { printelts(__env__()); } f(); f("a"); f("a", "b"); f("a", "b", "c"); printelts("hello, world"); s = "hello, world\n"; print(s); s[1] = 97; print(s); s[4] = ord("y"); print(s); s[8] = ord("i"); print(s); print("READ = ", readfile("test2.txt")); Object.subtype(name) { self.new(__name__: name) } Stream = Object.subtype(#Stream); newStream(string) { self = Stream.new( content: string, position: 0, limit: len(string) ); print(self.position, " ", self.limit, " ", !self.atEnd(), "\n"); self; } Stream.atEnd() { self.position >= self.limit } Stream.peek() { !self.atEnd() && self.content[self.position] } Stream.next() { !self.atEnd() && { c = self.content[self.position]; self.position = self.position + 1; c; } } s = newStream(readfile("test2.txt")); print(s, "\n"); while (!s.atEnd()) print(chr(s.peek()), " ", s.next(), " "); print("\n"); x = (`6*7;); print(x, "\n", full:1); print(x.__eval__(), "\n", full:1); print(eval(x), "\n"); print(codeString(x), "\n"); Symbol.macros.test = (x, y) { print("MACRO EVAL test with ", x, " and ", y, "\n"); `{print("REPLACEMENT ", @x, "\n"); @y } }; print("MACRO table ", Symbol.macros, "\n", full:1); print("define testfun\n"); testfun() { test(1, 2); test("three", "four"); } print("call testfun\n"); testfun(); for (i from 0 to 10) print(i, " "); print("\n"); for (i from 10 to 0) print(i, " "); print("\n"); for (i in 10) print(i, " "); print("\n"); for (i in "ABCDE") print(i, " "); print("\n"); for (i in [1, "two", 3, "four"]) print(i, " "); print("\n"); factorial(n) { if (n < 2) "1" else n * factorial(n-1) } factorial(5);