// // // -$@:@ @@ // @ -@ @ @ // $: @@@@@ $@$: $@+@ @ @@@ // -$@$ @ -@ $+ -@ @ *$ // *$ @ -$@$@ @ @$$ // @ @ $* @ @ @$$ // @+ -$ @: :$ @- *@ $* -$ @ -$ // @:@$- :@@$- -$$-@@ $@$- @@ @@@- // // // // type Stack { Stack push(Any x); pop(); void foreach(Any -> void); } class ListStackC(List list) : Stack impl Stack { Stack push(Any x) { return new ListStackC(list = new ConsList(car = x, cdr = list)); } pop() { return (new ListStackC(list = list.rest()), list.first()); } void foreach(Any -> void f) { list.foreach(f); } export Stack : push, pop, foreach; } Stack emptyStack() { return new ListStackC(list = new MTList()); } // // //@@@@@: @@ @@ -$@:@ @@ // @ :@ @ @ @ -@ @ @ // @ -$ $@$ @@ @@ @@:@@: $@:@ -@@$ $@:@ $: @@@@@ $@$: $@+@ @ @@@ // @@@$ $- -$ @ @ @+ :@ $* *@ $ -$ $* *@ -$@$ @ -@ $+ -@ @ *$ // @ :$ @ @ @ @ @ @ @ @ @@@@@ @ @ *$ @ -$@$@ @ @$$ // @ @ @ @ @ @ @ @ @ @ $ @ @ @ @ $* @ @ @$$ // @ :@ $- -$ @: +@ @ @ $* *@ +: $* *@ @+ -$ @: :$ @- *@ $* -$ @ -$ //@@@@@: $@$ :@$-@@@@@ @@@ $@:@@ $@@+ $@:@@ @:@$- :@@$- -$$-@@ $@$- @@ @@@- // // // // type BoundedStack <: Stack { BoundedStack push(Any x); pop(); bool isFull(); int spaceRemaining(); } // space = number of pushes possible on this stack class BoundedStackC(Stack stack, int space) : BoundedStack impl BoundedStack { bool isFull() { return space < 1; } int spaceRemaining() { return space; } BoundedStack push(Any x) { if(isFull()) { error("Stack is full"); } else { return new BoundedStackC(stack = stack.push(x), space = space - 1); }; } pop() { (Stack s, Any obj) = stack.pop(); return (new BoundedStackC(stack = s, space = space + 1), obj); } void foreach(Any -> void f) { stack.foreach(f); } export BoundedStack : push, pop, isFull, spaceRemaining, foreach; } BoundedStack emptyBoundedStack(int n) { return new BoundedStackC(stack = emptyStack(), space = n); } // // // +@@@* // @ @ // @ @@:@@: @@@@@ -@@$ $@-@@ -@@$ @@-$+ // @ @+ :@ @ $ -$ $* :@ $ -$ @$ : // @ @ @ @ @@@@@ @ @ @@@@@ @ // @ @ @ @ $ @ @ $ @ // @ @ @ @: :$ +: $* :@ +: @ // -@@@: @@@ @@@ :@@$- $@@+ $@:@ $@@+ @@@@@ // -$ // -@@$ // // struct IntegerC(int value) : Integer { } // // // @@@ @ // @ @ // @ -@@ :@@+@ @@@@@ // @ @ @$ -@ @ // @ @ :@@$- @ // @ @ @ *@ @ // @ @ @ @ :@ @: :$ // @@@@@ @@@@@ $+@@: :@@$- // // // // type List { List addToFront(Any); List addToEnd(Any); Any first(); Any atIndex(int); Any last(); List rest(); List drop(int); List take(int); List appendToEnd(List); List appendToFront(List); List reverse(); int length(); bool empty(); List map(Any -> Any); Any foldl( -> Any, Any); Any foldr( -> Any, Any); List filter(Any -> bool); void foreach(Any -> void); } class MTList() : List impl List { List add(Any elt) { return new ConsList(car = elt, cdr = (this : List)); } Any no_elts(int n) { error("The empty list has no elements!"); } Any no_elt() { error("The empty list has no elements!"); } List rest() { error("Cannot get the rest of the empty list!"); } List drop(int n) { if n == 0 { this : List; } else { error("Attempt to drop elements from an empty list!"); }; } List take(int n) { if n == 0 { this : List; } else { error("Attempt to take elements from an empty list!"); }; } List ret_other(List l) { return l; } List reverse() { return (this : List); } int length() { return 0; } bool empty() { return true; } List map(Any -> Any f) { return (this : List); } Any fold( -> Any f, Any i) { return i; } List filter(Any -> bool f) { return (this : List); } void foreach(Any -> void f) { return(); } export List : add as addToFront, add as addToEnd, no_elt as first, no_elts as atIndex, no_elt as last, rest, drop, take, reverse, ret_other as appendToEnd, ret_other as appendToFront, length, empty, map, fold as foldl, fold as foldr, filter, foreach; } // Since init slots get translated to init fields by need, we can put // car and cdr here, and then use them appropriately inside the methods // which will make them fields. class ConsList(Any car, List cdr) : List impl List { Any first() { return car; } Any atIndex(int n) { if n == 0 { car; } else { cdr.atIndex(n - 1); }; } Any last() { if cdr.empty() { car; } else { cdr.last(); }; } List rest() { return cdr; } List drop(int n) { if n == 0 { this : List; } else { cdr.drop(n - 1); }; } List take(int n) { if n == 0 { new MTList(); } else { new ConsList(car = car, cdr = cdr.take(n - 1)); }; } List addToFront(Any x) { return new ConsList(car = x, cdr = (this : List)); } List addToEnd(Any x) { return new ConsList(car = car, cdr = cdr.addToEnd(x)); } List appendToFront(List other) { if other.empty() { this : List; } else { new ConsList(car = other.first(), cdr = other.drop(1)); }; } List appendToEnd(List other) { return new ConsList(car = car, cdr = cdr.appendToEnd(other)); } List reverse() { return cdr.reverse().addToEnd(car); } int length() { return 1 + cdr.length(); } bool empty() { return false; } List map(Any -> Any f) { return new ConsList(car = f(car), cdr = cdr.map(f)); } Any foldl( -> Any f, Any i) { return f(car, cdr.foldl(f, i)); } Any foldr( -> Any f, Any i) { return cdr.foldr(f, f(car, i)); } List filter(Any -> bool f) { if f(car) { new ConsList(car = car, cdr = cdr.filter(f)); } else { cdr.filter(f); }; } void foreach(Any -> void f) { f(car); cdr.foreach(f); } export List : addToFront, addToEnd, first, atIndex, last, reverse, rest, drop, take, appendToEnd, appendToFront, length, empty, map, foldl, foldr, filter, foreach; } // // //@@@@@@ @@ // @ @ @ // @ @ @@ @@ $@$: @@+-$: @@:@$- @ -@@$ :@@+@ // @@@ $ -$- -@ @+@$@ @: -$ @ $ -$ @$ -@ // @ @ $$- -$@$@ @ @ @ @ @ @ @@@@@ :@@$- // @ -$$ $* @ @ @ @ @ @ @ $ *@ // @ @ -$- $ @- *@ @ @ @ @: -$ @ +: @ :@ //@@@@@@ @@ @@ -$$-@@@@@@@@@ @-@$ @@@@@ $@@+ $+@@: // @ // @@@ // // // Stack empty = emptyBoundedStack(5); // Stack s1 = empty.push(new IntegerC(value = 5)); // Stack s2 = s1.push(new IntegerC(value = 3)); // Stack s3 = s2.push(new IntegerC(value = 10)); // Stack s4 = s3.push(new IntegerC(value = 20)); // Stack s5 = s4.push(new IntegerC(value = 40)); // use foreach + don't care(about binding) syntax // _ = s5.foreach(void fun(Any x) { // cond { // x isa Integer => printLine(intToString((x : Integer).value)); // else printLine("Unknown type of value"); // }; // }); // Now try adding something to s5! // Stack s6 = s5.push(new IntegerC(value = 50));