-
Notifications
You must be signed in to change notification settings - Fork 2
/
implementation.ml
229 lines (219 loc) · 5.88 KB
/
implementation.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
open Back
open Builtin
open Emit
open Error
open Front
open Global
open Instruction
open Lambda
open Printer
open Syntax
open Type
open Typing
let stage = ref 4
let verbose = ref false
let typing_impl_expr loc e =
push_level();
let ty = typing_expr [] e in
pop_level();
if should_generate e then
gen_type ty;
ty
let submit_variant ty_res cs =
let n = List.length cs in
let rec go i acc = function
| [] -> List.rev acc
| (name,arg)::xs ->
match arg with
| None ->
let constr =
{ qualid=Lident name
; info={ cs_res=ty_res
; cs_arg=type_unit
; cs_tag=Constr_tag_regular(n,i)
; cs_kind=Constr_constant
}
}
in
add_global_constr constr;
go (i+1) (constr::acc) xs
| Some arg ->
let ty_arg = type_of_type_expression true arg in
(* TODO kind *)
let constr =
{ qualid=Lident name
; info={ cs_res=ty_res
; cs_arg=ty_arg
; cs_tag=Constr_tag_regular(n,i)
; cs_kind=Constr_regular
}
}
in
add_global_constr constr;
go (i+1) (constr::acc) xs
in
let cds = go 0 [] cs in
pop_level();
gen_type ty_res;
List.iter (fun cd -> gen_type cd.info.cs_arg) cds;
Variant_type cds
let typing_impl_typedef loc decl : (typ * type_components) list =
let submit (name,args,def) =
let ty_constr =
{ qualid=Lident name
; info={ ty_stamp=new_type_stamp(); ty_abbr=Tnotabbrev }
} in
let ty_desc =
{ qualid=Lident name
; info={ ty_constr=ty_constr; ty_arity=List.length args;
ty_desc=Abstract_type }
} in
add_global_type ty_desc;
ty_desc,args,def
in
let submit_abbrev ty_constr ty_params body =
let ty = type_of_type_expression true body in
pop_level();
gen_type ty;
List.iter gen_type ty_params;
ty_constr.info.ty_abbr <- Tabbrev(ty_params, ty);
Abbrev_type(ty_params, ty)
in
let define (ty_desc,args,def) =
push_level();
let ty_args =
try
bind_te_vars args
with Failure "bind_te_vars" ->
duplicate_param_in_type_decl_err loc
in
let ty_res =
{ typ_desc=Tconstr(ty_desc.info.ty_constr, ty_args)
; typ_level=notgeneric
} in
let ty_comp =
match def with
| Ptd_abstract ->
pop_level();
Abstract_type
| Ptd_variant cs ->
(* pop_level() included *)
submit_variant ty_res cs
| Ptd_alias te ->
(* pop_level() included *)
submit_abbrev ty_desc.info.ty_constr ty_args te
in
ty_desc.info.ty_desc <- ty_comp;
ty_res, ty_comp
in
let decl = List.map submit decl in
let r = List.map define decl in
List.iter (fun (ty_desc,_,_) ->
check_recursive_abbrev ty_desc.info.ty_constr
) decl;
r
let typing_impl_excdef loc (name,arg) : constr_desc global =
let cd =
begin match arg with
| None ->
let id = Lident name in
{ qualid=id
; info={ cs_res=type_exn
; cs_arg=type_unit
; cs_tag=Constr_tag_extensible(id,new_type_stamp())
; cs_kind=Constr_constant
}
}
| Some arg ->
let id = Lident name in
let ty_arg = type_of_type_expression true arg in
{ qualid=id
; info={ cs_res=type_exn
; cs_arg=ty_arg
; cs_tag=Constr_tag_extensible(id,new_type_stamp())
; cs_kind=Constr_regular
}
}
end
in
add_global_constr cd;
cd
let typing_impl_letdef loc isrec pes =
push_level();
let tys = List.map (fun _ -> new_type_var()) pes in
let env = typing_pat_list [] (List.map fst pes) tys in
let submit () =
List.iter (fun (name,ty) ->
add_global_value
{ qualid=Lident name
; info={ v_typ=ty; v_prim=Not_prim }
}) env in
if isrec then
submit();
List.iter2 (fun (_,e) ty ->
typing_expect [] e ty
) pes tys;
pop_level();
let gens = List.map (fun (_,e) -> should_generate e) pes in
(*List.iter (dump_typ 0) tys;*)
List.iter2 (fun gen ty ->
if gen then (
(*print_endline "+ gen";*)
gen_type ty
)
else (
(*print_endline "+ restrict";*)
value_restrict ty
)
) gens tys;
(*List.iter (dump_typ 0) tys;*)
if not isrec then
submit();
env
let process_lambda oc lambda =
if !stage = 2 then
dump_lambda 0 lambda
else if !stage >= 3 then (
let init, fcts as code = compile_lambda lambda in
if !stage = 3 then (
print_endline "Initialization";
dump_zinc init;
print_endline "";
print_endline "Code for functions";
dump_zinc fcts;
print_endline ""
) else
emit_phrase oc code
)
let compile_impl oc impl =
let loc = impl.im_loc in
reset_te_vars();
match impl.im_desc with
| Pimpl_expr e ->
let ty = typing_impl_expr loc e in
if !verbose then
print_impl_expr ty;
if !stage >= 2 then
process_lambda oc @@ translate_expr e
| Pimpl_typedef decl ->
let ty_decl = typing_impl_typedef loc decl in
if !verbose then
print_impl_typedef ty_decl
| Pimpl_letdef(isrec,binds) ->
let env = typing_impl_letdef loc isrec binds in
if !verbose then
print_impl_letdef env;
if !stage >= 2 then
process_lambda oc @@ translate_letdef impl.im_loc isrec binds
| Pimpl_excdef decl ->
let cd = typing_impl_excdef loc decl in
if !verbose then
print_impl_excdef cd
let compile_implementation objfile impls =
let oc = if !stage >= 4 then open_out_bin objfile else stdout in
if !stage >= 4 then
start_emit_phrase oc;
List.iter (compile_impl oc) impls;
if !stage >= 4 then
end_emit_phrase oc;
close_out oc