// nil is the undefined object
|
|
// integers, floats, strings are as usual
|
|
// #<identifier> 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 <Object>
|
|
print("Lambda => ", Lambda, "\n"); // this prints as <Lambda>
|
|
print("Closure => ", Closure, "\n"); // this prints as <Closure>
|
|
|
|
// 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 <<Object>> 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");
|
|
|
|
print(Object, full:1, "\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");
|
|
|
|
i = 40;
|
|
|
|
assert(i++ == 40); assert(i == 41);
|
|
assert(i-- == 41); assert(i == 40);
|
|
assert(++i == 41); assert(i == 41);
|
|
assert(--i == 40); assert(i == 40);
|
|
|
|
assert((i *= 2) == 80); assert(i == 80);
|
|
assert((i /= 2) == 40); assert(i == 40);
|
|
|
|
assert((i %= 7) == 5); assert(i == 5);
|
|
assert((i <<= 4) == 80); assert(i == 80);
|
|
assert((i >>= 3) == 10); assert(i == 10);
|
|
|
|
i = 0;
|
|
|
|
assert((i |= 7) == 7); assert(i == 7);
|
|
assert((i |= 14) == 15); assert(i == 15);
|
|
assert((i ^= 6) == 9); assert(i == 9);
|
|
assert((i ^= 6) == 15); assert(i == 15);
|
|
assert((i &= 14) == 14); assert(i == 14);
|
|
assert((i &= 7) == 6); assert(i == 6);
|
|
|
|
i = [1, 2, 3];
|
|
|
|
assert(codeString(i) == "[1, 2, 3]");
|
|
|
|
assert(++i[1] == 3); assert(codeString(i) == "[1, 3, 3]");
|
|
assert(--i[2] == 2); assert(codeString(i) == "[1, 3, 2]");
|
|
assert(i[0]++ == 1); assert(codeString(i) == "[2, 3, 2]");
|
|
assert(i[2]-- == 2); assert(codeString(i) == "[2, 3, 1]");
|
|
|
|
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.allKeys().sorted();
|
|
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();
|
|
|
|
// used-defined AST nodes are evaluated the same way as built-in types
|
|
|
|
MakeSeven = Object.subtype(#MakeSeven);
|
|
|
|
MakeSeven.__eval__(exp, env) {
|
|
print("MakeSeven.__eval__ invoked\n");
|
|
7;
|
|
}
|
|
|
|
myNode = MakeSeven.new();
|
|
|
|
ast = (`6 * @myNode;); // user-defined node in AST
|
|
|
|
print("AST eval => ", eval(ast), "\n");
|
|
|
|
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);
|