520
|
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 |
}
|