
of a supertype and subtype, where the subtype was not yet added to the tenv. Had to hack to get around that one. Also little problems like the fact that list can be captured by the user program, so we can't use that -- used list* (with a null at the end) and null (for empty lists) instead. Since the power was down and I couldn't get the earlier stuff committed, I have even more changes. Bug-fixes, mostly, though now top-level functions that are defined consecutively are mutually recursive as they should be. svn: r300
323 lines
8.7 KiB
Plaintext
323 lines
8.7 KiB
Plaintext
//
|
|
//
|
|
// -$@:@ @@
|
|
// @ -@ @ @
|
|
// $: @@@@@ $@$: $@+@ @ @@@
|
|
// -$@$ @ -@ $+ -@ @ *$
|
|
// *$ @ -$@$@ @ @$$
|
|
// @ @ $* @ @ @$$
|
|
// @+ -$ @: :$ @- *@ $* -$ @ -$
|
|
// @:@$- :@@$- -$$-@@ $@$- @@ @@@-
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
type Stack {
|
|
Stack push(Any x);
|
|
<Stack, Any> pop();
|
|
}
|
|
|
|
class ListStackC(List list) : Stack impl Stack {
|
|
|
|
Stack push(Any x) {
|
|
return new ListStackC(list = new ConsList(car = x, cdr = list));
|
|
}
|
|
|
|
<Stack, Any> pop() {
|
|
return (new ListStackC(list = list.rest()), list.first());
|
|
}
|
|
|
|
export Stack : push, pop;
|
|
}
|
|
|
|
Stack emptyStack() {
|
|
return new ListStackC(list = new MTList());
|
|
}
|
|
|
|
//
|
|
//
|
|
//@@@@@: @@ @@ -$@:@ @@
|
|
// @ :@ @ @ @ -@ @ @
|
|
// @ -$ $@$ @@ @@ @@:@@: $@:@ -@@$ $@:@ $: @@@@@ $@$: $@+@ @ @@@
|
|
// @@@$ $- -$ @ @ @+ :@ $* *@ $ -$ $* *@ -$@$ @ -@ $+ -@ @ *$
|
|
// @ :$ @ @ @ @ @ @ @ @ @@@@@ @ @ *$ @ -$@$@ @ @$$
|
|
// @ @ @ @ @ @ @ @ @ @ $ @ @ @ @ $* @ @ @$$
|
|
// @ :@ $- -$ @: +@ @ @ $* *@ +: $* *@ @+ -$ @: :$ @- *@ $* -$ @ -$
|
|
//@@@@@: $@$ :@$-@@@@@ @@@ $@:@@ $@@+ $@:@@ @:@$- :@@$- -$$-@@ $@$- @@ @@@-
|
|
//
|
|
//
|
|
//
|
|
//
|
|
|
|
type BoundedStack <: Stack {
|
|
BoundedStack push(Any x);
|
|
<BoundedStack, Any> 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);
|
|
};
|
|
}
|
|
|
|
<BoundedStack, Any> pop() {
|
|
(Stack s, Any obj) = stack.pop();
|
|
return (new BoundedStackC(stack = s, space = space + 1), obj);
|
|
}
|
|
|
|
export BoundedStack : push, pop, isFull, spaceRemaining;
|
|
}
|
|
|
|
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, Any);
|
|
Any foldr(<Any, Any> -> Any, Any);
|
|
List filter(Any -> bool);
|
|
|
|
}
|
|
|
|
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, Any> -> Any f, Any i) { return i; }
|
|
|
|
List filter(Any -> bool f) { return (this : List); }
|
|
|
|
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;
|
|
}
|
|
|
|
// 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, Any> -> Any f, Any i) {
|
|
return f(car, cdr.foldl(f, i));
|
|
}
|
|
|
|
Any foldr(<Any, Any> -> 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);
|
|
};
|
|
}
|
|
|
|
export List : addToFront, addToEnd, first, atIndex, last, reverse,
|
|
rest, drop, take, appendToEnd, appendToFront, length, empty,
|
|
map, foldl, foldr, filter;
|
|
}
|
|
|
|
|
|
//
|
|
//
|
|
//@@@@@@ @@
|
|
// @ @ @
|
|
// @ @ @@ @@ $@$: @@+-$: @@:@$- @ -@@$ :@@+@
|
|
// @@@ $ -$- -@ @+@$@ @: -$ @ $ -$ @$ -@
|
|
// @ @ $$- -$@$@ @ @ @ @ @ @ @@@@@ :@@$-
|
|
// @ -$$ $* @ @ @ @ @ @ @ $ *@
|
|
// @ @ -$- $ @- *@ @ @ @ @: -$ @ +: @ :@
|
|
//@@@@@@ @@ @@ -$$-@@@@@@@@@ @-@$ @@@@@ $@@+ $+@@:
|
|
// @
|
|
// @@@
|
|
//
|
|
//
|
|
|
|
|
|
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));
|
|
|
|
// Now try adding something to s5!
|
|
|
|
Stack s6 = s5.push(new IntegerC(value = 50)); |