-
Notifications
You must be signed in to change notification settings - Fork 1
/
parse.mc
122 lines (112 loc) · 3.58 KB
/
parse.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
include "result.mc"
include "error.mc"
include "./ast_gen.mc"
include "./ast.mc"
include "./pprint.mc"
include "./error-print.mc"
lang DAEParseAnalysis = DAEAst + DAEParsePrettyPrint
type Res a = Result ErrorSection ErrorSection a
sem daeParse : String -> String -> Res DAEProg
sem daeParse filename =| prog ->
switch parseDAEParse filename prog
case Right prog then result.ok prog
case Left errs then
foldl1
result.withAnnotations
(map
(lam e. result.err { errorDefault with msg = e.1, info = e.0 })
errs)
end
sem daeParseExn : String -> String -> DAEProg
sem daeParseExn filename =| prog ->
switch result.consume (daeParse filename prog)
case (ws, Right prog) then
(if not (null ws) then errorWarn (errorMsg ws {single = "", multi = ""})
else ());
prog
case (ws, Left errs) then
(if not (null ws) then errorWarn (errorMsg ws {single = "", multi = ""})
else ());
errorDie (errorMsg errs {single = "", multi = ""})
end
sem daeProgWellFormed : all a. DAEProg -> Res DAEProg
sem daeProgWellFormed =
| prog & ProgDAEProg r ->
result.withAnnotations
(result.withAnnotations
(foldl daeVarWellFormed (setEmpty nameCmp, result.ok ()) r.vars).1
(result.mapM daeInitWellFormed r.ieqns))
(foldl1 result.withAnnotations
[
smapM_DAEProg_DAETop daeTopWellFormed prog,
smapM_DAEProg_DAEEqn
(smapM_DAEEqn_DAEExpr daeExprAllowPrimWellFormed) prog
])
sem daeVarWellFormed : all a. (Set Name, Res ()) -> DAEVar -> (Set Name, Res ())
sem daeVarWellFormed acc =
| vars & VarsDAEVar r ->
foldl
(lam acc. lam name.
match acc with (names, res) in
let newres =
if setMem name.v names then
result.err {
errorDefault with
msg = strJoin "\n" [
"Duplicate dependent variable declaration:",
daeVarToString vars
],
info = name.i
}
else result.ok ()
in
(setInsert name.v names, result.withAnnotations res newres))
acc
r.names
sem daeTopWellFormed : all a. DAETop -> Res DAETop
sem daeTopWellFormed =
| top -> smapM_DAETop_DAEExpr daeExprWellFormed top
sem daeInitWellFormed : all a. DAEEqn -> Res DAEEqn
sem daeInitWellFormed =
| eqn & EqnDAEEqn r ->
switch (r.left, r.right)
case
((VarDAEExpr _, _) | (_, VarDAEExpr _))
| ((PrimDAEExpr _, _) | (_, PrimDAEExpr _))
then result.ok eqn
case _ then result.err {
errorDefault with
msg = strJoin "\n" [
"Non-explicit initial equation:", daeEqnToString eqn
],
info = r.info
}
end
sem daeExprWellFormed : all a. DAEExpr -> Res DAEExpr
sem daeExprWellFormed =
| expr & PrimDAEExpr r ->
result.err {
errorDefault with
msg = strJoin "\n" ["Invalid use of \':", daeExprToString expr],
info = r.info
}
| expr -> smapM_DAEExpr_DAEExpr daeExprWellFormed expr
sem daeExprAllowPrimWellFormed : all a. DAEExpr -> Res DAEExpr
sem daeExprAllowPrimWellFormed =
| expr & PrimDAEExpr r ->
recursive let recur = lam expr.
switch expr
case VarDAEExpr _ then true
case PrimDAEExpr r then recur r.left
case _ then false
end
in
if recur r.left then result.ok expr
else
result.err {
errorDefault with
msg = strJoin "\n" ["Invalid use of \':", daeExprToString expr],
info = r.info
}
| expr -> smapM_DAEExpr_DAEExpr daeExprAllowPrimWellFormed expr
end