-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathtutorial1-mlang.mc
170 lines (118 loc) · 4.36 KB
/
tutorial1-mlang.mc
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
-- Includes from the standard library
include "common.mc"
include "mexpr/info.mc"
include "string.mc"
-- Includes from the local directory
include "./lib/lambda.mc"
include "./tutorial1-mexpr.mc"
include "./ast.mc"
/-
The purpose of this tutorial is for you to familiarize yourself with MLang and
language fragments in particular.
This tutorial is divided into two tasks, with somewhat rising complexity. We
will re-use your solution to Task A later in the tutorial.
-/
-- Helpers to convert between floats and Exprs
let exprToFloat = use NumExprAst in
lam e. match e with NumExpr x in x.val.v
let floatToExpr = use NumExprAst in
lam f. NumExpr {info = NoInfo (), val = {v = f, i = NoInfo()}}
-- Language fragments implementing 'eval'
lang EvalBase = CalcBaseAst
sem eval : Map String Expr -> Expr -> Expr
end
lang NumExprEval = EvalBase + NumExprAst
sem eval env =
| e & NumExpr _ -> e
end
lang TermEval = EvalBase + AddExprAst + SubExprAst
sem eval env =
| AddExpr x ->
let l = exprToFloat (eval env x.left) in
let r = exprToFloat (eval env x.right) in
floatToExpr (addf l r)
| SubExpr x ->
let l = exprToFloat (eval env x.left) in
let r = exprToFloat (eval env x.right) in
floatToExpr (subf l r)
end
lang FactorEval = EvalBase + MulExprAst + DivExprAst
sem eval env =
| MulExpr x ->
let l = exprToFloat (eval env x.left) in
let r = exprToFloat (eval env x.right) in
floatToExpr (mulf l r)
| DivExpr x ->
let l = exprToFloat (eval env x.left) in
let r = exprToFloat (eval env x.right) in
floatToExpr (divf l r)
end
-- Language fragments implementing 'toString'
lang ToStringBase
sem toString : Expr -> String
end
lang NumToString = ToStringBase + NumExprAst
sem toString =
| NumExpr x -> float2string x.val.v
end
lang TermToString = ToStringBase + AddExprAst + SubExprAst
sem toString =
| AddExpr x -> join ["(", toString x.left, " + ", toString x.right, ")"]
| SubExpr x -> join ["(", toString x.left, " - ", toString x.right, ")"]
end
lang FactorToString = ToStringBase + MulExprAst + DivExprAst
sem toString =
| MulExpr x -> join ["(", toString x.left, " * ", toString x.right, ")"]
| DivExpr x -> join ["(", toString x.left, " / ", toString x.right, ")"]
end
-- Composed languages
lang Eval = TermEval + NumExprEval + FactorEval
end
lang ToString = NumToString + TermToString + FactorToString
end
lang Complete = Eval + ToString
end
/-
Task A ---------------------------------------------------------------------
Extend the language fragments `CalcAst` (in ast.mc), `Eval`, and
`ToString` with and AST node for sin(x). The sine function in mexpr
is called `sin`. You should name the new language fragment in ast.mc
`SinExprAst`, and the new constructor, `SinExpr` for the sake of the
rest of the tutorials.
-/
/-
Task B ---------------------------------------------------------------------
Extend the language fragments `CalcAst` (in ast.mc), `Eval`, and
`ToString` with and AST node for integer exponents based on your
implementation of `pow` from `tutorial1-mexpr.mc`. You should name the
new language fragment in ast.mc `PowExprAst`, and the new constructor
`PowExpr`, for the sake of the rest of the tutorials.
You will probably need to convert from floating point numbers to
integers which you can do with the functions `floorfi`, `ceilfi`, or
`roundfi`.
-/
/-
Task C (tutorial session 2) ------------------------------------------------
Add concrete syntax for your expressions using `ast.syn`. Replace
`include "ast.mc"` with `include "ast-gen.mc"` to use the generated
AST language fragments instead of the manually written ones, along
with a parsing function.
Next, use the (generated) function `parseCalcExn` to write your
expressions, instead of the helpers below. For example:
match parseCalcExn "example" "1.0 + 42.0 * sin 3.0"
with File {e = example} in
-/
mexpr
-- Test code
use Complete in
let emptyEnv = mapEmpty cmpString in
let add_ = lam l. lam r.
AddExpr{info = NoInfo (), left = l, right = r} in
let sub_ = lam l. lam r.
SubExpr{info = NoInfo (), left = l, right = r} in
let num_ = lam v.
NumExpr{info = NoInfo (), val = {v = v, i = NoInfo ()}} in
let example = add_ (num_ 2.0) (num_ 3.0) in
utest exprToFloat (eval emptyEnv example) with addf 2.0 3.0 in
printLn (toString (eval emptyEnv example));
printLn (toString example)