Skip to content

Commit 100c396

Browse files
committed
Generate local and tgv variable assignment as OCaml array set.
1 parent e1ffac1 commit 100c396

1 file changed

Lines changed: 168 additions & 9 deletions

File tree

src/mlang/backend_compilers/bir_to_ocaml.ml

Lines changed: 168 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,177 @@
11
(* Backend OCaml *)
22

3+
let none_value = "m_undef"
4+
5+
let get_var_pos (var : Bir.variable) : int = var.Bir.offset
6+
7+
let generate_comp_op (op : Mast.comp_op) : string =
8+
match op with
9+
| Mast.Gt -> "m_greater_than"
10+
| Mast.Gte -> "m_greater_than_equal"
11+
| Mast.Lt -> "m_less_than"
12+
| Mast.Lte -> "m_less_than_equal"
13+
| Mast.Eq -> "m_equal"
14+
| Mast.Neq -> "m_not_equal"
15+
16+
let generate_binop (op : Mast.binop) : string =
17+
match op with
18+
| Mast.And -> "m_and"
19+
| Mast.Or -> "m_or"
20+
| Mast.Add -> "m_add"
21+
| Mast.Sub -> "m_subtract"
22+
| Mast.Mul -> "m_multiply"
23+
| Mast.Div -> "m_divide"
24+
25+
let generate_unop (op : Mast.unop) : string =
26+
match op with Mast.Not -> "mNot" | Mast.Minus -> "mNeg"
27+
28+
let rec generate_ocaml_expr (e : Bir.expression Pos.marked) :
29+
string * (Mir.LocalVariable.t * Bir.expression Pos.marked) list =
30+
match Pos.unmark e with
31+
| Comparison (op, e1, e2) ->
32+
let expr1, local1 = generate_ocaml_expr e1 in
33+
let expr2, local2 = generate_ocaml_expr e2 in
34+
( Format.asprintf "(%s %s %s)"
35+
(generate_comp_op (Pos.unmark op))
36+
expr1 expr2,
37+
local1 @ local2 )
38+
| Binop (op, e1, e2) ->
39+
let s1, local1 = generate_ocaml_expr e1 in
40+
let s2, local2 = generate_ocaml_expr e2 in
41+
( Format.asprintf "(%s %s %s)" (generate_binop (Pos.unmark op)) s1 s2,
42+
local1 @ local2 )
43+
| Unop (op, e) ->
44+
let expr, local = generate_ocaml_expr e in
45+
(Format.asprintf "(%s %s)" (generate_unop op) expr, local)
46+
| Index (_var, e) ->
47+
let _expr, local = generate_ocaml_expr e in
48+
("Index", local)
49+
| Conditional (e1, e2, e3) ->
50+
let se1, s1 = generate_ocaml_expr e1 in
51+
let se2, s2 = generate_ocaml_expr e2 in
52+
let se3, s3 = generate_ocaml_expr e3 in
53+
(Format.asprintf "(m_cond %s %s %s)" se1 se2 se3, s1 @ s2 @ s3)
54+
| FunctionCall (PresentFunc, [ arg ]) ->
55+
let _expr, local = generate_ocaml_expr arg in
56+
("PresentFunc", local)
57+
| FunctionCall (NullFunc, [ arg ]) ->
58+
let _expr, local = generate_ocaml_expr arg in
59+
("NullFunc", local)
60+
| FunctionCall (ArrFunc, [ arg ]) ->
61+
let _expr, local = generate_ocaml_expr arg in
62+
("ArrFunc", local)
63+
| FunctionCall (InfFunc, [ arg ]) ->
64+
let _expr, local = generate_ocaml_expr arg in
65+
("InfFunc", local)
66+
| FunctionCall (MaxFunc, [ e1; _e2 ]) ->
67+
let _s1, local1 = generate_ocaml_expr e1 in
68+
("MaxFunc", local1)
69+
| FunctionCall (MinFunc, [ e1; _e2 ]) ->
70+
let _s1, local1 = generate_ocaml_expr e1 in
71+
("MinFunc", local1)
72+
| FunctionCall (Multimax, [ e1; (Var _v2, _) ]) ->
73+
let _s1, local1 = generate_ocaml_expr e1 in
74+
("Multimax", local1)
75+
| FunctionCall _ -> assert false (* should not happen *)
76+
| Literal (Float f) -> (
77+
match f with
78+
| 0. -> (Format.asprintf "m_zero", [])
79+
| 1. -> (Format.asprintf "m_one", [])
80+
| _ ->
81+
(Format.asprintf "{undefined=false;value=%s}" (string_of_float f), [])
82+
)
83+
| Literal Undefined -> (Format.asprintf "%s" none_value, [])
84+
| Var var ->
85+
( Format.asprintf "(get tgv %d (*%s*))" (get_var_pos var)
86+
(Pos.unmark var.mir_var.name),
87+
[] )
88+
| LocalVar _lvar -> ("localvar", []) (*TODO*)
89+
| GenericTableIndex -> ("generic table index", []) (* TODO *)
90+
| Error -> assert false (* should not happen *)
91+
| LocalLet (lvar, e1, e2) ->
92+
let _, local1 = generate_ocaml_expr e1 in
93+
let se2, local2 = generate_ocaml_expr e2 in
94+
(Format.asprintf "%s" se2, local1 @ ((lvar, e1) :: local2))
95+
96+
let format_tgv_set (variable_expression : string) (oc : Format.formatter)
97+
(variable_position : int) : unit =
98+
Format.fprintf oc "Array.set tgv %d %s;@,"
99+
variable_position variable_expression
100+
101+
let format_local_defs (oc : Format.formatter)
102+
(defs : (Mir.LocalVariable.t * Bir.expression Pos.marked) list) : unit =
103+
Format.pp_print_list
104+
(fun fmt (lvar, expr) ->
105+
let se, _ = generate_ocaml_expr expr in
106+
Format.fprintf fmt
107+
"Array.set local_variables %d %s;@,"
108+
lvar.Mir.LocalVariable.id se)
109+
oc defs
110+
111+
let generate_var_def (variable : Bir.variable) (vdata : Bir.variable_data)
112+
(oc : Format.formatter) : unit =
113+
match vdata.var_definition with
114+
| SimpleVar e ->
115+
let tgv_expression, local_defs = generate_ocaml_expr e in
116+
Format.fprintf oc "%a(*%s*) %a" format_local_defs local_defs
117+
(Pos.unmark variable.mir_var.name)
118+
(format_tgv_set tgv_expression)
119+
(get_var_pos variable)
120+
| TableVar (_, IndexTable es) ->
121+
Format.fprintf oc "%a"
122+
(fun fmt ->
123+
Mir.IndexMap.iter (fun i v ->
124+
let tgv_expression, local_defs = generate_ocaml_expr v in
125+
Format.fprintf fmt "%a(*%s*) %a" format_local_defs local_defs
126+
(Pos.unmark variable.mir_var.name)
127+
(format_tgv_set tgv_expression)
128+
(get_var_pos variable |> ( + ) i)))
129+
es
130+
| TableVar (size, IndexGeneric e) ->
131+
let tgv_expression, local_defs = generate_ocaml_expr e in
132+
let list_pos =
133+
let rec integer_range first_item last_item =
134+
if first_item > last_item then []
135+
else first_item :: integer_range (first_item + 1) last_item
136+
in
137+
integer_range (get_var_pos variable) (get_var_pos variable + size)
138+
in
139+
let aux_print_list (list_pos : int list) (oc : Format.formatter)
140+
(tgv_expression : string) =
141+
List.iter (format_tgv_set tgv_expression oc) list_pos
142+
in
143+
Format.fprintf oc "%a(*Table %s*)@,%a" format_local_defs local_defs
144+
(Pos.unmark variable.mir_var.name)
145+
(aux_print_list list_pos) tgv_expression
146+
| InputVar -> assert false
147+
3148
let rec generate_stmts (program : Bir.program) (oc : Format.formatter)
4149
(stmts : Bir.stmt list) : unit =
5-
Format.pp_print_list (generate_stmt program) oc stmts
150+
Format.pp_print_list ~pp_sep:Format.pp_print_if_newline
151+
(generate_stmt program) oc stmts
6152

7-
and generate_stmt (_program : Bir.program) (oc : Format.formatter)
153+
and generate_stmt (program : Bir.program) (oc : Format.formatter)
8154
(stmt : Bir.stmt) : unit =
9-
Format.fprintf oc "%s"
10-
(match Pos.unmark stmt with
11-
| SAssign (variable, _variable_data) -> Pos.unmark variable.mir_var.name
12-
| SConditional (_expression, _tt, _ff) -> "Condition"
13-
| SVerif _condition_data -> "Verif"
14-
| SRuleCall _rule_id -> "Rule call"
15-
| SFunctionCall (function_name, _) -> function_name)
155+
match Pos.unmark stmt with
156+
| SAssign (variable, variable_data) ->
157+
generate_var_def variable variable_data oc
158+
| SConditional (_expression, tt, ff) ->
159+
let pos = Pos.get_position stmt in
160+
let fname =
161+
String.map
162+
(fun c -> if c = '.' then '_' else c)
163+
(Filename.basename (Pos.get_file pos))
164+
in
165+
let cond_name =
166+
Format.asprintf "cond_%s_%d_%d_%d_%d" fname (Pos.get_start_line pos)
167+
(Pos.get_start_column pos) (Pos.get_end_line pos)
168+
(Pos.get_end_column pos)
169+
in
170+
Format.fprintf oc "@[<v 1>Condition %s :@,true ->@,%a@,false ->@,%a@]"
171+
cond_name (generate_stmts program) tt (generate_stmts program) ff
172+
| SVerif _condition_data -> Format.fprintf oc "%s" "Verif"
173+
| SRuleCall _rule_id -> Format.fprintf oc "Rule %i call" _rule_id
174+
| SFunctionCall (function_name, _) -> Format.fprintf oc "%s" function_name
16175

17176
let generate_mpp_function (program : Bir.program) (oc : Format.formatter)
18177
(function_name : string) : unit =

0 commit comments

Comments
 (0)