1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
|
implement Generics;
include "sys.m";
include "draw.m";
include "bufio.m";
sys: Sys;
print: import sys;
bufio: Bufio;
Iobuf: import bufio;
Generics: module {
init: fn(nil: ref Draw->Context, nil: list of string);
};
# Polymorphic type
Rd: adt[T] {
t: ref Iobuf;
ws: fn(rd: self ref Rd[T]): int;
};
Num: adt {
pick {
String =>
s: string;
Int =>
d: int;
}
stringify: fn(v: self ref Num): string;
};
# Polymorphic and pick-tagged type
Word: adt[T] {
w: T;
pick {
String =>
s: string;
}
eq: fn(a, b: ref Word): int;
};
Integer: adt {
d: int;
};
Int: type ref Integer;
init(nil: ref Draw->Context, nil: list of string) {
sys = load Sys Sys->PATH;
bufio = load Bufio Bufio->PATH;
in := bufio->open("/fd/0", bufio->OREAD);
rd := ref Rd[ref Iobuf](in);
print("Type something: ");
c := rd.ws();
print("Broke on '%c'\n", c);
d := ref Num.Int(5);
s := ref Num.String("Five");
print("%s\n", d.stringify());
print("%s\n", s.stringify());
words: list of ref Word[Int].String;
smiley := "☺";
frowny := ":(";
sword := ref Word[Int].String(Int(9), smiley);
# Format is: Adt[Type].PickTag(fields...)
words = sword :: words;
words = ref Word[Int].String(Int(7), frowny) :: words;
if(ismember(sword, words))
print("Found %d!\n", sword.w.d);
exit;
}
# Skip white space
Rd[T].ws(rd: self ref Rd[T]): int {
while(isspace(c := rd.t.getb()))
{}
return c;
}
Word[T].eq(a, b: ref Word): int
{
return a.w == b.w; # This is a shallow comparison, don't rely on this
}
Num.stringify(v: self ref Num): string {
pick xv := v {
String =>
return xv.s;
Int =>
return string xv.d;
* =>
raise "type error";
}
}
# Matches whitespace characters
isspace(c: int): int {
return c == ' ' || c == '\r' || c == '\t' || c == '\n';
}
# Checks if x is a member of l
ismember[T](x: T, l: list of T): int
for {
T => eq: fn(a, b: T): int;
}
{
for(; l != nil; l = tl l)
if(T.eq(x, hd l))
return 1;
return 0;
}
# Pairs two lists of separate types(?)
pair[T1, T2](l1: list of T1, l2: list of T2): list of (T1, T2) {
if(l1 == nil && l2 == nil)
return nil;
return (hd l1, hd l2) :: pair(tl l1, tl l2);
}
# Reverse a list
rev[T](l: list of T): list of T {
r: list of T;
for(; l != nil; l = tl l)
r = hd l :: r;
return r;
}
|