-
Notifications
You must be signed in to change notification settings - Fork 0
/
ast.ml
165 lines (148 loc) · 4.83 KB
/
ast.ml
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
type bop = Add | Sub | Mul | Div | Mod | Equal | Neq | Less | Leq | Greater | Geq | And | Or
type uop = Not
type id = string
type typ =
| Int
| Bool
| Float
| Char
| String
| ListT of typ
| Void
| EmptyList
| RecordType of id
| FunkType of typ list * typ
and opt = Opt of typ * id
type expr =
| Noexpr
| IntLit of int
| BoolLit of bool
| FloatLit of float
| CharLit of char
| StrLit of string
| Id of string (* figure this out *)
| Binop of expr * bop * expr
| Unop of uop * expr
| Assign of string * expr
| RecordCreate of id * expr list
| RecordAccess of expr * id
| MutateRecord of (expr * id) * expr
| ListLit of expr list
| ListAccess of expr * expr
| MutateList of (expr * expr) * expr
| Call of id * expr list
| CallRecord of (expr * id) * expr list
| CallList of (expr * expr) * expr list
type vdecl =
| Declare of typ * id
| Initialize of typ * id * expr
type stmt =
| Block of stmt list
| Expr of expr
| Vdecl of vdecl
| If of expr * stmt * stmt
| For of id * expr * stmt
| While of expr * stmt
| RecordDef of id * opt list
| Return of expr
| Continue
| Break
type fdecl = {
rtyp: typ;
fname: id;
formals: opt list;
body: stmt list;
}
type top_level =
| Stmt of stmt
| Fdecl of fdecl
type program = top_level list
let rec string_of_typ = function
Int -> "int"
| Bool -> "bool"
| Float -> "float"
| String -> "string"
| Char -> "char"
| Void -> "void"
| EmptyList -> "EmptyList"
| RecordType(t) -> "record " ^ t
| ListT(t) -> "[" ^ (string_of_typ t) ^ "]"
| FunkType(types, return_typ) ->
string_of_typ return_typ ^ "(" ^ String.concat ", " (List.map string_of_typ types) ^ ")"
and string_of_opt = function
| Opt(t, id) -> string_of_typ t ^ " " ^ id
and string_of_opt_list l = String.concat ", " (List.map string_of_opt l)
let string_of_bop = function
Add -> "+"
| Sub -> "-"
| Mul -> "*"
| Div -> "/"
| Mod -> "%"
| Equal -> "=="
| Neq -> "!="
| Less -> "<"
| Leq -> "<="
| Greater -> ">"
| Geq -> ">="
| And -> "and"
| Or -> "or"
let string_of_uop = function
Not -> "not"
let rec string_of_expr = function
IntLit(l) -> string_of_int l
| BoolLit(true) -> "true"
| BoolLit(false) -> "false"
| Id(s) -> s
| Binop(e1, o, e2) ->
string_of_expr e1 ^ " " ^ string_of_bop o ^ " " ^ string_of_expr e2
| Unop(o, e) -> string_of_uop o ^ " " ^ string_of_expr e
| Assign(v, e) -> v ^ " = " ^ string_of_expr e
| Noexpr -> ""
| FloatLit(l) -> string_of_float l
| CharLit(l) -> "'" ^ Char.escaped l ^ "'"
| StrLit(l) -> "\"" ^ String.escaped l ^ "\""
| RecordCreate(rec_name, actuals) ->
rec_name ^ " { " ^ String.concat ", " (List.map string_of_expr actuals) ^ " }"
| RecordAccess(r, field) -> string_of_expr r ^ "." ^ field
| MutateRecord((r, field), e) -> string_of_expr r ^ "." ^ field ^ " = " ^ string_of_expr e
| ListLit(l) -> "[" ^ String.concat ", " (List.map string_of_expr l) ^ "]"
| ListAccess(lst, ind) -> string_of_expr lst ^ "[" ^ string_of_expr ind ^ "]"
| MutateList((lst, ind), e) -> string_of_expr lst ^ "[" ^ string_of_expr ind ^ "] = " ^ string_of_expr e
| Call(f, actuals) -> f ^ "(" ^ String.concat ", " (List.map string_of_expr actuals) ^ ")"
| CallRecord((r, field), actuals) ->
string_of_expr r ^ "." ^ field ^
"(" ^ String.concat ", " (List.map string_of_expr actuals) ^ ")"
| CallList((lst, ind), actuals) ->
string_of_expr lst ^ "[" ^ string_of_expr ind ^ "]" ^
"(" ^ String.concat ", " (List.map string_of_expr actuals) ^ ")"
let string_of_vdecl = function
| Declare(t, id) -> string_of_typ t ^ " " ^ id ^ ";"
| Initialize(t, id, expr) -> string_of_typ t ^ " " ^ id ^ " = " ^ string_of_expr expr ^ ";"
let rec string_of_stmt = function
Block(stmts) ->
"{\n" ^ String.concat "" (List.map string_of_stmt stmts) ^ "}\n"
| Expr(expr) -> string_of_expr expr ^ ";";
| Vdecl(decl) -> string_of_vdecl decl
| If(e, s1, s2) -> "if (" ^ string_of_expr e ^ ")\n" ^
string_of_stmt s1 ^ "else\n" ^ string_of_stmt s2
| For(i, iter, stmt) -> "for (" ^ i ^ " in " ^ string_of_expr iter ^ ") " ^ string_of_stmt stmt
| While(e, s) -> "while (" ^ string_of_expr e ^ ") " ^ string_of_stmt s
| RecordDef(rec_name, formals) ->
"record " ^ rec_name ^ " {\n " ^ String.concat ",\n " (List.map string_of_opt formals) ^ "\n};"
| Return(e) -> "return " ^ string_of_expr e ^ ";"
| Continue -> "continue;"
| Break -> "break;"
let string_of_fdecl f =
string_of_typ f.rtyp ^ " " ^
f.fname ^ "(" ^
string_of_opt_list f.formals ^ ") {\n " ^
String.concat "\n " (List.map string_of_stmt f.body)
^ "\n}"
let string_of_program decls =
let stringify = function
| Stmt(t) -> string_of_stmt t
| Fdecl(t) -> string_of_fdecl t
in
"\n\nParsed program: \n\n" ^
String.concat "\n\n" (List.map stringify decls) ^
"\n"