|
1 abstract class Exp |
|
2 abstract class Stmt |
|
3 |
|
4 case class Plus(e1: Exp, e2: Exp) extends Exp |
|
5 case class Times(e1: Exp, e2: Exp) extends Exp |
|
6 case class Equ(e1: Exp, e2: Exp) extends Exp |
|
7 case class Num(n: Int) extends Exp |
|
8 case class Var(x: String) extends Exp |
|
9 |
|
10 case class Label(l: String) extends Stmt |
|
11 case class Assign(x: String, e: Exp) extends Stmt |
|
12 case class Goto(l: String) extends Stmt |
|
13 case class Jmp(e: Exp, l: String) extends Stmt |
|
14 |
|
15 type Stmts = List[Stmt] |
|
16 type Env = Map[String, Int] |
|
17 type Snips = Map[String, Stmts] |
|
18 |
|
19 def preproc(sts: Stmts) : Snips = sts match { |
|
20 case Nil => Map() |
|
21 case Label(l)::rest => preproc(rest) + (l -> rest) |
|
22 case _::rest => preproc(rest) |
|
23 } |
|
24 |
|
25 def Prog(sts: Stmt*) = preproc(Label("")::sts.toList) |
|
26 |
|
27 def eval_exp(e: Exp, env: Env) : Int = e match { |
|
28 case Var(x) => env(x) |
|
29 case Num(n) => n |
|
30 case Plus(e1, e2) => eval_exp(e1, env) + eval_exp(e2, env) |
|
31 case Times(e1, e2) => eval_exp(e1, env) * eval_exp(e2, env) |
|
32 case Equ(e1, e2) => |
|
33 if (eval_exp(e1, env) == eval_exp(e2, env)) 1 else 0 |
|
34 } |
|
35 |
|
36 def eval(sn: Snips) : Env = { |
|
37 def eval_stmts(sts: Stmts, env: Env): Env = sts match { |
|
38 case Nil => env |
|
39 case Label(l)::rest => eval_stmts(rest, env) |
|
40 case Assign(x, e)::rest => |
|
41 eval_stmts(rest, env + (x -> eval_exp(e, env))) |
|
42 case Goto(l)::rest => eval_stmts(sn(l), env) |
|
43 case Jmp(b, l)::rest => |
|
44 if (eval_exp(b, env) == 1) eval_stmts(sn(l), env) |
|
45 else eval_stmts(rest, env) |
|
46 } |
|
47 eval_stmts(sn(""), Map()) |
|
48 } |