|
@ -0,0 +1,329 @@ |
|
|
|
|
|
// 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"); |
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
makeForm(assert); |
|
|
|
|
|
|
|
|
|
|
|
refute(x) { |
|
|
|
|
|
if (eval(x)) { |
|
|
|
|
|
print("\nrefutation failed: ", codeString(x), "\n"); |
|
|
|
|
|
exit(1); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
makeForm(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); |