| 1 | component interpreterExercise |
|---|
| 2 | export Executable |
|---|
| 3 | |
|---|
| 4 | trait Ast comprises { Expr, Type } |
|---|
| 5 | getter asString(): String |
|---|
| 6 | end |
|---|
| 7 | |
|---|
| 8 | (* expressions *) |
|---|
| 9 | (* e ::= s |
|---|
| 10 | | n |
|---|
| 11 | | n + n |
|---|
| 12 | | n - n |
|---|
| 13 | *) |
|---|
| 14 | trait Expr extends Ast comprises { Val, BinOpApp } excludes Type end |
|---|
| 15 | |
|---|
| 16 | trait Val extends Expr comprises { Str, Num } |
|---|
| 17 | getter asValue(): Object |
|---|
| 18 | end |
|---|
| 19 | |
|---|
| 20 | object Str(string: String) extends Val |
|---|
| 21 | getter asString() = string |
|---|
| 22 | getter asValue() = string |
|---|
| 23 | end |
|---|
| 24 | |
|---|
| 25 | (* Define an object Num. |
|---|
| 26 | * Take some hints from the object Str. |
|---|
| 27 | *) |
|---|
| 28 | |
|---|
| 29 | trait BinOpApp extends Expr comprises { Plus, Minus } |
|---|
| 30 | abstract getter left(): Expr |
|---|
| 31 | abstract getter op(): String |
|---|
| 32 | abstract getter right(): Expr |
|---|
| 33 | getter asString() = self.left.asString self.op self.right.asString |
|---|
| 34 | end |
|---|
| 35 | |
|---|
| 36 | (* Define objects Plus and Minus. |
|---|
| 37 | * Note that they have two parameters. |
|---|
| 38 | *) |
|---|
| 39 | |
|---|
| 40 | (* types *) |
|---|
| 41 | (* t ::= StringType |
|---|
| 42 | | IntegerType |
|---|
| 43 | *) |
|---|
| 44 | trait Type extends Ast comprises { StringType, IntegerType } excludes Expr end |
|---|
| 45 | object StringType extends Type end |
|---|
| 46 | object IntegerType extends Type end |
|---|
| 47 | |
|---|
| 48 | (* Define an evaluator as overloaded function declarations. *) |
|---|
| 49 | eval(e: Expr): Object = |
|---|
| 50 | fail("You still need to implement an eval function.") |
|---|
| 51 | |
|---|
| 52 | (* Define a type checker as overloaded function declarations. *) |
|---|
| 53 | typecheck(e: Expr): Type = |
|---|
| 54 | fail("You still need to implement a typecheck function.") |
|---|
| 55 | |
|---|
| 56 | (********************************************************************************** |
|---|
| 57 | * TESTS |
|---|
| 58 | **********************************************************************************) |
|---|
| 59 | |
|---|
| 60 | run(): () = do |
|---|
| 61 | eight = Plus(Num(3), Num(5)) |
|---|
| 62 | hello = Str("Hello") |
|---|
| 63 | wrong = Minus(eight, hello) |
|---|
| 64 | |
|---|
| 65 | assert(eight.asString, "3+5") |
|---|
| 66 | assert(hello.asString, "Hello") |
|---|
| 67 | assert(wrong.asString, "3+5-Hello") |
|---|
| 68 | println("Your objects appear to work.") |
|---|
| 69 | |
|---|
| 70 | (* test: eval *) |
|---|
| 71 | assert(eval(eight), 8) |
|---|
| 72 | assert(eval(hello), "Hello") |
|---|
| 73 | println("Your eval appears to work.") |
|---|
| 74 | |
|---|
| 75 | (* test: typecheck *) |
|---|
| 76 | assert(typecheck(eight), IntegerType) |
|---|
| 77 | assert(typecheck(hello), StringType) |
|---|
| 78 | try |
|---|
| 79 | typecheck(wrong) |
|---|
| 80 | catch x |
|---|
| 81 | FailCalled => () |
|---|
| 82 | end |
|---|
| 83 | println("Your typecheck appears to work.") |
|---|
| 84 | end |
|---|
| 85 | |
|---|
| 86 | end |
|---|