|
1 | 1 | (* Backend OCaml *) |
2 | 2 |
|
| 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 | + |
3 | 148 | let rec generate_stmts (program : Bir.program) (oc : Format.formatter) |
4 | 149 | (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 |
6 | 152 |
|
7 | | -and generate_stmt (_program : Bir.program) (oc : Format.formatter) |
| 153 | +and generate_stmt (program : Bir.program) (oc : Format.formatter) |
8 | 154 | (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 |
16 | 175 |
|
17 | 176 | let generate_mpp_function (program : Bir.program) (oc : Format.formatter) |
18 | 177 | (function_name : string) : unit = |
|
0 commit comments