149 lines
3.1 KiB
Common Lisp
149 lines
3.1 KiB
Common Lisp
(*
|
|
This file presents a fairly large example of Cool programming. The
|
|
class List defines the names of standard list operations ala Scheme:
|
|
car, cdr, cons, isNil, rev, sort, rcons (add an element to the end of
|
|
the list), and print_list. In the List class most of these functions
|
|
are just stubs that abort if ever called. The classes Nil and Cons
|
|
inherit from List and define the same operations, but now as
|
|
appropriate to the empty list (for the Nil class) and for cons cells (for
|
|
the Cons class).
|
|
|
|
The Main class puts all of this code through the following silly
|
|
test exercise:
|
|
|
|
1. prompt for a number N
|
|
2. generate a list of numbers 0..N-1
|
|
3. reverse the list
|
|
4. sort the list
|
|
5. print the sorted list
|
|
|
|
Because the sort used is a quadratic space insertion sort, sorting
|
|
moderately large lists will cause spim to run out of memory.
|
|
*)
|
|
|
|
Class List inherits IO {
|
|
(* Since abort() returns Object, we need something of
|
|
type Bool at the end of the block to satisfy the typechecker.
|
|
This code is unreachable, since abort() halts the program. *)
|
|
isNil() : Bool { { abort(); true; } };
|
|
|
|
cons(hd : Int) : Cons {
|
|
(let new_cell : Cons <- new Cons in
|
|
new_cell.init(hd,self)
|
|
)
|
|
};
|
|
|
|
(*
|
|
Since abort "returns" type Object, we have to add
|
|
an expression of type Int here to satisfy the typechecker.
|
|
This code is, of course, unreachable.
|
|
*)
|
|
car() : Int { { abort(); new Int; } };
|
|
|
|
cdr() : List { { abort(); new List; } };
|
|
|
|
rev() : List { cdr() };
|
|
|
|
sort() : List { cdr() };
|
|
|
|
insert(i : Int) : List { cdr() };
|
|
|
|
rcons(i : Int) : List { cdr() };
|
|
|
|
print_list() : Object { abort() };
|
|
};
|
|
|
|
Class Cons inherits List {
|
|
xcar : Int; -- We keep the car in cdr in attributes.
|
|
xcdr : List; -- Because methods and features must have different names,
|
|
-- we use xcar and xcdr for the attributes and reserve
|
|
-- cons and car for the features.
|
|
|
|
isNil() : Bool { false };
|
|
|
|
init(hd : Int, tl : List) : Cons {
|
|
{
|
|
xcar <- hd;
|
|
xcdr <- tl;
|
|
self;
|
|
}
|
|
};
|
|
|
|
car() : Int { xcar };
|
|
|
|
cdr() : List { xcdr };
|
|
|
|
rev() : List { (xcdr.rev()).rcons(xcar) };
|
|
|
|
sort() : List { (xcdr.sort()).insert(xcar) };
|
|
|
|
insert(i : Int) : List {
|
|
if i < xcar then
|
|
(new Cons).init(i,self)
|
|
else
|
|
(new Cons).init(xcar,xcdr.insert(i))
|
|
fi
|
|
};
|
|
|
|
|
|
rcons(i : Int) : List { (new Cons).init(xcar, xcdr.rcons(i)) };
|
|
|
|
print_list() : Object {
|
|
{
|
|
out_int(xcar);
|
|
out_string("\n");
|
|
xcdr.print_list();
|
|
}
|
|
};
|
|
};
|
|
|
|
Class Nil inherits List {
|
|
isNil() : Bool { true };
|
|
|
|
rev() : List { self };
|
|
|
|
sort() : List { self };
|
|
|
|
insert(i : Int) : List { rcons(i) };
|
|
|
|
rcons(i : Int) : List { (new Cons).init(i,self) };
|
|
|
|
print_list() : Object { true };
|
|
|
|
};
|
|
|
|
|
|
Class Main inherits IO {
|
|
|
|
l : List;
|
|
|
|
(* iota maps its integer argument n into the list 0..n-1 *)
|
|
iota(i : Int) : List {
|
|
{
|
|
l <- new Nil;
|
|
(let j : Int <- 0 in
|
|
while j < i
|
|
loop
|
|
{
|
|
l <- (new Cons).init(j,l);
|
|
j <- j + 1;
|
|
}
|
|
pool
|
|
);
|
|
l;
|
|
}
|
|
};
|
|
|
|
main() : Object {
|
|
{
|
|
out_string("How many numbers to sort?");
|
|
iota(in_int()).rev().sort().print_list();
|
|
}
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
|