-
-
Notifications
You must be signed in to change notification settings - Fork 8
/
main.mz
69 lines (61 loc) · 1.91 KB
/
main.mz
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
main() :=
let env := Cell("a", Int(2i32), Cell("x", Int(7u32), Nil()));
fetchCell(evalProgram(example(), env), "out");
// Computes "out = a^x" using a simple while-loop.
example() :=
Cons(Assign("out", Int(1i32)),
Cons(Assign("i", Var("x")),
Cons(While(GreaterThan(Var("i"), Int(0u32)),
Cons(Assign("out", Mul(Var("out"), Var("a"))),
Cons(Assign("i", Sub(Var("i"), Int(1u32))),
Nil()))),
Nil())));
evalProgram(program, env) := match program {
Nil() -> env,
Cons(stmt, rest) -> evalProgram(rest, evalStmt(stmt, env))
};
evalStmt(stmt, env) := match stmt {
Assign(x, t) -> updateCell(env, x, evalTerm(t, env)),
While(cond, repeat) -> match evalBoolean(cond, env) {
T() -> evalStmt(stmt, evalProgram(repeat, env)),
F() -> env
}
};
evalTerm(t, env) := match t {
Var(x) -> fetchCell(env, x),
Boolean(b) -> Boolean(b),
Int(n) -> Int(n),
Sub(t1, t2) ->
let result := -(evalInt(t1, env), evalInt(t2, env));
Int(result),
Mul(t1, t2) ->
let result := *(evalInt(t1, env), evalInt(t2, env));
Int(result),
GreaterThan(t1, t2) ->
let result := >(evalInt(t1, env), evalInt(t2, env));
Boolean(result)
};
evalBoolean(t, env) := match evalTerm(t, env) {
Boolean(b) -> b,
Int(_n) -> Panic("want `Boolean(b)`, got `Int(n)`")
};
evalInt(t, env) := match evalTerm(t, env) {
Int(n) -> n,
Boolean(_b) -> Panic("want `Int(n)`, got `Boolean(b)`")
};
fetchCell(env, x) := match env {
Nil() -> Panic(++("the variable is unbound: ", x)),
Cell(y, value, xs) -> match =(x, y) {
T() -> value,
F() -> fetchCell(xs, x)
}
};
updateCell(env, x, value) := match env {
Nil() -> Cell(x, value, Nil()),
Cell(y, value', xs) -> match =(x, y) {
T() -> Cell(x, value, xs),
F() ->
let xs := updateCell(xs, x, value);
Cell(y, value', xs)
}
};