Skip to content

Commit a3e0b18

Browse files
author
Jeff Wendling
committed
change to ocaml and do crud transforms
1 parent 918d10b commit a3e0b18

6 files changed

+515
-316
lines changed

src/ir/ir_xform.re

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ module FieldHash = Hashes.FieldHash;
88

99
type t = Transform.t;
1010

11-
let transform_defs = Transform.xform_defs;
11+
let transform_defs = Transform.xform_defs;

src/ir/ir_xform_transform.ml

+378
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
open Core
2+
open Crud_ast
3+
open Ir_xform_hashes
4+
5+
include Ir_xform_types
6+
7+
let check_duplicate_strings strings =
8+
let seen = StringHash.create () in
9+
List.iter strings ~f:(
10+
fun { Annotate.node = node; loc } ->
11+
match StringHash.find seen node with
12+
| Some prev_loc -> raise @@ Ir_error.Exn (Duplicate ("value", prev_loc, loc))
13+
| None -> StringHash.set seen node loc
14+
)
15+
16+
let rec find_and_xform_field defs t model field =
17+
match Ir_xform_defs.find_field defs (!model).Model.name field with
18+
| Field field -> xform_field defs t model field
19+
| Rel rel -> xform_rel defs t model rel
20+
21+
and find_and_xform_model defs t model =
22+
xform_model defs t (Ir_xform_defs.find_model defs model)
23+
24+
and xform_model defs t model =
25+
let { Syntax.Model.name = { node = name }; entries } = model in
26+
27+
let model = lazy begin
28+
let entries_set = Ir_xform_dupes.create "model entry" in
29+
let fields_set = Ir_xform_dupes.create "field" in
30+
31+
let model = ref
32+
{ Model.name = name
33+
; fields = StringHash.create ()
34+
; table = None
35+
; key = []
36+
; unique = []
37+
; index = []
38+
; cruds = []
39+
} in
40+
StringHash.set t.models name model;
41+
42+
List.iter entries ~f:(
43+
fun { Annotate.loc; node } ->
44+
match node with
45+
| Syntax.Model.Table table ->
46+
Ir_xform_dupes.check entries_set "table" loc;
47+
model := { !model with table = Some table.node }
48+
49+
| Key key ->
50+
Ir_xform_dupes.check entries_set "key" loc;
51+
check_duplicate_strings key;
52+
let fields = List.map key (find_and_xform_field defs t model) in
53+
model := { !model with key = fields }
54+
55+
| Unique unique ->
56+
check_duplicate_strings unique;
57+
let fields = List.map unique (find_and_xform_field defs t model) in
58+
model := { !model with unique = fields :: !model.unique }
59+
60+
| Index index ->
61+
check_duplicate_strings index;
62+
let fields = List.map index (find_and_xform_field defs t model) in
63+
model := { !model with index = fields :: !model.index }
64+
65+
| Field ({ name = { node = field_name } } as field) ->
66+
Ir_xform_dupes.check fields_set field_name loc;
67+
let field = xform_field defs t model field in
68+
StringHash.set !model.fields field_name field
69+
70+
| Rel ({ name = { node = rel_name } } as rel) ->
71+
Ir_xform_dupes.check fields_set rel_name loc;
72+
let rel = xform_rel defs t model rel in
73+
StringHash.set !model.fields rel_name rel
74+
);
75+
76+
model
77+
end in
78+
79+
match StringHash.find t.models name with
80+
| Some model -> model
81+
| None -> force model
82+
83+
and xform_field defs t parent field =
84+
let { Syntax.Field.name = { node = name }; type_ = { node = type_ }; attrs } = field in
85+
86+
let field = lazy begin
87+
let entries_set = Ir_xform_dupes.create "field attribute" in
88+
89+
let field_ = ref
90+
{ Field.parent = parent
91+
; name
92+
; type_
93+
; column = None
94+
; nullable = false
95+
; updatable = false
96+
; autoinsert = false
97+
; autoupdate = false
98+
; length = None
99+
} in
100+
let field = ref @@ Model.Field !field_ in
101+
FieldHash.set t.fields (!parent.name, name) field;
102+
103+
List.iter attrs ~f:(
104+
fun { Annotate.loc; node } ->
105+
begin match node with
106+
| Syntax.Field.Column { node = col } ->
107+
Ir_xform_dupes.check entries_set "column" loc;
108+
field_ := { !field_ with column = Some col }
109+
110+
| Nullable ->
111+
Ir_xform_dupes.check entries_set "nullable" loc;
112+
field_ := { !field_ with nullable = true }
113+
114+
| Updatable ->
115+
Ir_xform_dupes.check entries_set "updatable" loc;
116+
field_ := { !field_ with updatable = true }
117+
118+
| Autoinsert ->
119+
Ir_xform_dupes.check entries_set "autoinsert" loc;
120+
field_ := { !field_ with autoinsert = true }
121+
122+
| Autoupdate ->
123+
Ir_xform_dupes.check entries_set "autoupdate" loc;
124+
field_ := { !field_ with autoupdate = true }
125+
126+
| Length { node = length; loc } ->
127+
Ir_xform_dupes.check entries_set "length" loc;
128+
match Int.of_string length with
129+
| length -> field_ := { !field_ with length = Some length }
130+
| exception _ -> raise @@ Ir_error.Exn (Invalid loc)
131+
end;
132+
133+
field := Field !field_;
134+
);
135+
136+
field
137+
end in
138+
139+
match FieldHash.find t.fields (!parent.name, name) with
140+
| Some field -> field
141+
| None -> force field
142+
143+
and xform_rel defs t parent rel =
144+
let { Syntax.Rel.name = { node = name }; model; field; kind = { node = kind }; attrs } = rel in
145+
146+
let rel = lazy begin
147+
let entries_set = Ir_xform_dupes.create "relation attribute" in
148+
let model = find_and_xform_model defs t model in
149+
let field = find_and_xform_field defs t model field in
150+
151+
let rel_ = ref
152+
{ Rel.parent = parent
153+
; name
154+
; model
155+
; field
156+
; kind
157+
; column = None
158+
; nullable = false
159+
; updatable = false
160+
} in
161+
let rel = ref @@ Model.Rel !rel_ in
162+
FieldHash.set t.fields (!parent.name, name) rel;
163+
164+
List.iter attrs ~f:(
165+
fun { Annotate.loc; node } ->
166+
begin match node with
167+
| Syntax.Rel.Column { node = col } ->
168+
Ir_xform_dupes.check entries_set "column" loc;
169+
rel_ := { !rel_ with column = Some col }
170+
171+
| Nullable ->
172+
(Ir_xform_dupes.check entries_set "nullable" loc;
173+
rel_ := { !rel_ with nullable = true })
174+
175+
| Updatable ->
176+
(Ir_xform_dupes.check entries_set "updatable" loc;
177+
rel_ := { !rel_ with updatable = true })
178+
end;
179+
180+
rel := Rel !rel_;
181+
);
182+
183+
rel
184+
end in
185+
186+
match FieldHash.find t.fields (!parent.name, name) with
187+
| Some rel -> rel
188+
| None -> force rel
189+
190+
and xform_crud defs t crud =
191+
let { Syntax.Crud.model; entries } = crud in
192+
let model = find_and_xform_model defs t model in
193+
194+
let crud = lazy begin
195+
let crud = ref
196+
{ Crud.model
197+
; entries = []
198+
} in
199+
StringHash.set t.cruds !model.name crud;
200+
201+
List.iter entries ~f:(
202+
fun { Annotate.loc; node } ->
203+
match node with
204+
| Syntax.Crud.Create create ->
205+
let create = xform_create defs t crud create in
206+
crud := { !crud with entries = create :: !crud.entries }
207+
208+
| Read read ->
209+
let read = xform_read defs t crud read in
210+
crud := { !crud with entries = read :: !crud.entries }
211+
212+
| Update update ->
213+
let update = xform_update defs t crud update in
214+
crud := { !crud with entries = update :: !crud.entries }
215+
216+
| Delete delete ->
217+
let delete = xform_delete defs t crud delete in
218+
crud := { !crud with entries = delete :: !crud.entries }
219+
);
220+
221+
crud
222+
end in
223+
224+
match StringHash.find t.cruds !model.name with
225+
| Some crud -> crud
226+
| None -> force crud
227+
228+
and xform_query defs t model = function
229+
| Syntax.Query.Term term -> xform_query_term defs t model term
230+
231+
| And { left_query = { node = left_query }; right_query = { node = right_query } } ->
232+
Query.And { b_left = xform_query defs t model left_query
233+
; b_right = xform_query defs t model right_query
234+
}
235+
236+
| Or { left_query = { node = left_query }; right_query = { node = right_query } } ->
237+
Query.Or { b_left = xform_query defs t model left_query
238+
; b_right = xform_query defs t model right_query
239+
}
240+
241+
and xform_query_term defs t model term =
242+
let { Syntax.Query.left_val = { node = left_val }
243+
; op = { node = op }
244+
; right_val = { node = right_val }
245+
} = term in
246+
let left_val = xform_query_value defs t model left_val in
247+
let right_val = xform_query_value defs t model right_val in
248+
Query.Term { t_left = left_val
249+
; t_op = op
250+
; t_right = right_val
251+
}
252+
253+
and xform_query_value defs t model = function
254+
| Syntax.Query.Placeholder ->
255+
Query.Placeholder
256+
257+
| Literal { node = literal } ->
258+
Literal literal
259+
260+
| Call ({ node = fn }, { node = value }) ->
261+
Call (fn, xform_query_value defs t model value)
262+
263+
| Field field ->
264+
let field = find_and_xform_field defs t model field in
265+
Field field
266+
267+
| Join (model, { node = query }, field) ->
268+
let model = find_and_xform_model defs t model in
269+
let field = find_and_xform_field defs t model field in
270+
Join (model, xform_query defs t model query, field)
271+
272+
and xform_create defs t parent create =
273+
let { Syntax.Create.attrs } = create in
274+
let attrs_set = Ir_xform_dupes.create "attribute" in
275+
276+
let create = ref { Create.parent
277+
; raw = false
278+
; suffix = None
279+
} in
280+
281+
List.iter attrs ~f:(
282+
fun { Annotate.loc; node } ->
283+
match node with
284+
| Syntax.Create.Raw ->
285+
Ir_xform_dupes.check attrs_set "raw" loc;
286+
create := { !create with raw = true }
287+
288+
| Suffix { node = suffix } ->
289+
Ir_xform_dupes.check attrs_set "suffix" loc;
290+
create := { !create with suffix = Some suffix }
291+
);
292+
293+
Crud.Create !create
294+
295+
and xform_read defs t parent read =
296+
let { Syntax.Read.kind = { node = kind }; query; attrs } = read in
297+
let attrs_set = Ir_xform_dupes.create "attribute" in
298+
let query = Option.map query ~f:(
299+
fun query -> xform_query defs t !parent.model query.node
300+
) in
301+
302+
let read = ref { Read.parent
303+
; kind
304+
; query
305+
; suffix = None
306+
; order_by = None
307+
} in
308+
309+
List.iter attrs ~f:(
310+
fun { Annotate.loc; node } ->
311+
match node with
312+
| Syntax.Read.Suffix { node = suffix } ->
313+
Ir_xform_dupes.check attrs_set "suffix" loc;
314+
read := { !read with suffix = Some suffix }
315+
316+
| OrderBy direction ->
317+
Ir_xform_dupes.check attrs_set "orderby" loc;
318+
read := { !read with order_by = Some direction }
319+
);
320+
321+
Crud.Read !read
322+
323+
and xform_update defs t parent update =
324+
let { Syntax.Update.attrs; query = { node = query } } = update in
325+
let attrs_set = Ir_xform_dupes.create "attribute" in
326+
let query = xform_query defs t !parent.model query in
327+
328+
let update = ref { Update.parent
329+
; query
330+
; suffix = None
331+
} in
332+
333+
List.iter attrs ~f:(
334+
fun { Annotate.loc; node } ->
335+
match node with
336+
| Syntax.Update.Suffix { node = suffix } ->
337+
Ir_xform_dupes.check attrs_set "suffix" loc;
338+
update := { !update with suffix = Some suffix }
339+
);
340+
341+
Crud.Update !update
342+
343+
and xform_delete defs t parent delete =
344+
let { Syntax.Delete.attrs; query = { node = query } } = delete in
345+
let attrs_set = Ir_xform_dupes.create "attribute" in
346+
let query = xform_query defs t !parent.model query in
347+
348+
let delete = ref { Delete.parent
349+
; query
350+
; suffix = None
351+
} in
352+
353+
List.iter attrs ~f:(
354+
fun { Annotate.loc; node } ->
355+
match node with
356+
| Syntax.Delete.Suffix { node = suffix } ->
357+
Ir_xform_dupes.check attrs_set "suffix" loc;
358+
delete := { !delete with suffix = Some suffix }
359+
);
360+
361+
Crud.Delete !delete
362+
363+
364+
let xform_def defs t { Annotate.node = def } =
365+
match def with
366+
| Syntax.Model model -> ignore @@ xform_model defs t model
367+
| Syntax.Crud crud -> ignore @@ xform_crud defs t crud
368+
369+
let xform_defs defs =
370+
let t =
371+
{ models = StringHash.create ()
372+
; fields = FieldHash.create ()
373+
; cruds = StringHash.create ()
374+
} in
375+
376+
match List.iter defs ~f:(xform_def (Ir_xform_defs.create defs) t) with
377+
| () -> Ok t
378+
| exception Ir_error.Exn err -> Error err

0 commit comments

Comments
 (0)