2021-06-22 17:01:57 +03:00
|
|
|
(* This file is part of the Catala compiler, a specification language for tax
|
|
|
|
and social benefits computation rules. Copyright (C) 2021 Inria, contributor:
|
|
|
|
Denis Merigoux <denis.merigoux@inria.fr>
|
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
|
|
use this file except in compliance with the License. You may obtain a copy of
|
|
|
|
the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
|
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
|
|
License for the specific language governing permissions and limitations under
|
|
|
|
the License. *)
|
|
|
|
|
|
|
|
open Utils
|
2022-08-12 18:59:49 +03:00
|
|
|
open Shared_ast
|
2021-06-22 17:01:57 +03:00
|
|
|
module A = Ast
|
|
|
|
module L = Lcalc.Ast
|
|
|
|
module D = Dcalc.Ast
|
|
|
|
|
2022-07-28 11:36:36 +03:00
|
|
|
type 'm ctxt = {
|
2022-08-25 17:35:08 +03:00
|
|
|
func_dict : ('m L.naked_expr, A.TopLevelName.t) Var.Map.t;
|
2022-08-12 23:42:39 +03:00
|
|
|
decl_ctx : decl_ctx;
|
2022-08-25 17:35:08 +03:00
|
|
|
var_dict : ('m L.naked_expr, A.LocalName.t) Var.Map.t;
|
2021-06-24 15:52:51 +03:00
|
|
|
inside_definition_of : A.LocalName.t option;
|
2022-03-21 16:58:54 +03:00
|
|
|
context_name : string;
|
2021-06-22 17:01:57 +03:00
|
|
|
}
|
|
|
|
|
2021-06-23 18:47:34 +03:00
|
|
|
(* Expressions can spill out side effect, hence this function also returns a
|
|
|
|
list of statements to be prepended before the expression is evaluated *)
|
2022-08-25 18:29:00 +03:00
|
|
|
let rec translate_expr (ctxt : 'm ctxt) (expr : 'm L.expr) :
|
|
|
|
A.block * A.expr =
|
|
|
|
match Marked.unmark expr with
|
2022-08-12 23:42:39 +03:00
|
|
|
| EVar v ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let local_var =
|
2022-07-28 11:36:36 +03:00
|
|
|
try A.EVar (Var.Map.find v ctxt.var_dict)
|
|
|
|
with Not_found -> A.EFunc (Var.Map.find v ctxt.func_dict)
|
2021-06-23 18:47:34 +03:00
|
|
|
in
|
2022-08-25 18:29:00 +03:00
|
|
|
[], (local_var, Expr.pos expr)
|
2022-08-12 23:42:39 +03:00
|
|
|
| ETuple (args, Some s_name) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
let args_stmts, new_args =
|
|
|
|
List.fold_left
|
|
|
|
(fun (args_stmts, new_args) arg ->
|
|
|
|
let arg_stmts, new_arg = translate_expr ctxt arg in
|
|
|
|
arg_stmts @ args_stmts, new_arg :: new_args)
|
|
|
|
([], []) args
|
|
|
|
in
|
|
|
|
let new_args = List.rev new_args in
|
|
|
|
let args_stmts = List.rev args_stmts in
|
2022-08-25 18:29:00 +03:00
|
|
|
args_stmts, (A.EStruct (new_args, s_name), Expr.pos expr)
|
2022-08-16 11:04:01 +03:00
|
|
|
| ETuple (_, None) -> failwith "Non-struct tuples cannot be compiled to scalc"
|
2022-08-12 23:42:39 +03:00
|
|
|
| ETupleAccess (e1, num_field, Some s_name, _) ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let e1_stmts, new_e1 = translate_expr ctxt e1 in
|
|
|
|
let field_name =
|
2022-08-16 11:04:01 +03:00
|
|
|
fst (List.nth (StructMap.find s_name ctxt.decl_ctx.ctx_structs) num_field)
|
2021-06-23 18:47:34 +03:00
|
|
|
in
|
2022-08-25 18:29:00 +03:00
|
|
|
e1_stmts, (A.EStructFieldAccess (new_e1, field_name, s_name), Expr.pos expr)
|
2022-08-12 23:42:39 +03:00
|
|
|
| ETupleAccess (_, _, None, _) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
failwith "Non-struct tuples cannot be compiled to scalc"
|
2022-08-12 23:42:39 +03:00
|
|
|
| EInj (e1, num_cons, e_name, _) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
let e1_stmts, new_e1 = translate_expr ctxt e1 in
|
|
|
|
let cons_name =
|
2022-08-12 23:42:39 +03:00
|
|
|
fst (List.nth (EnumMap.find e_name ctxt.decl_ctx.ctx_enums) num_cons)
|
2021-06-24 15:52:51 +03:00
|
|
|
in
|
2022-08-25 18:29:00 +03:00
|
|
|
e1_stmts, (A.EInj (new_e1, cons_name, e_name), Expr.pos expr)
|
2022-08-12 23:42:39 +03:00
|
|
|
| EApp (f, args) ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let f_stmts, new_f = translate_expr ctxt f in
|
|
|
|
let args_stmts, new_args =
|
|
|
|
List.fold_left
|
|
|
|
(fun (args_stmts, new_args) arg ->
|
|
|
|
let arg_stmts, new_arg = translate_expr ctxt arg in
|
|
|
|
arg_stmts @ args_stmts, new_arg :: new_args)
|
|
|
|
([], []) args
|
|
|
|
in
|
|
|
|
let new_args = List.rev new_args in
|
2022-08-25 18:29:00 +03:00
|
|
|
f_stmts @ args_stmts, (A.EApp (new_f, new_args), Expr.pos expr)
|
2022-08-12 23:42:39 +03:00
|
|
|
| EArray args ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let args_stmts, new_args =
|
|
|
|
List.fold_left
|
|
|
|
(fun (args_stmts, new_args) arg ->
|
|
|
|
let arg_stmts, new_arg = translate_expr ctxt arg in
|
|
|
|
arg_stmts @ args_stmts, new_arg :: new_args)
|
|
|
|
([], []) args
|
|
|
|
in
|
|
|
|
let new_args = List.rev new_args in
|
2022-08-25 18:29:00 +03:00
|
|
|
args_stmts, (A.EArray new_args, Expr.pos expr)
|
|
|
|
| EOp op -> [], (A.EOp op, Expr.pos expr)
|
|
|
|
| ELit l -> [], (A.ELit l, Expr.pos expr)
|
2021-06-23 18:47:34 +03:00
|
|
|
| _ ->
|
2022-03-21 16:58:54 +03:00
|
|
|
let tmp_var =
|
|
|
|
A.LocalName.fresh
|
2022-04-04 19:12:19 +03:00
|
|
|
( (*This piece of logic is used to make the code more readable. TODO:
|
|
|
|
should be removed when
|
|
|
|
https://github.com/CatalaLang/catala/issues/240 is fixed. *)
|
2022-03-21 16:58:54 +03:00
|
|
|
(match ctxt.inside_definition_of with
|
|
|
|
| None -> ctxt.context_name
|
|
|
|
| Some v ->
|
2022-05-30 12:20:48 +03:00
|
|
|
let v = Marked.unmark (A.LocalName.get_info v) in
|
2022-03-21 16:58:54 +03:00
|
|
|
let tmp_rex = Re.Pcre.regexp "^temp_" in
|
2021-06-23 18:47:34 +03:00
|
|
|
if Re.Pcre.pmatch ~rex:tmp_rex v then v else "temp_" ^ v),
|
2022-08-25 18:29:00 +03:00
|
|
|
Expr.pos expr )
|
2022-05-04 18:40:55 +03:00
|
|
|
in
|
2022-03-21 16:58:54 +03:00
|
|
|
let ctxt =
|
2022-05-04 18:40:55 +03:00
|
|
|
{
|
2022-03-21 16:58:54 +03:00
|
|
|
ctxt with
|
|
|
|
inside_definition_of = Some tmp_var;
|
2022-05-30 12:20:48 +03:00
|
|
|
context_name = Marked.unmark (A.LocalName.get_info tmp_var);
|
2022-05-04 18:40:55 +03:00
|
|
|
}
|
|
|
|
in
|
2022-08-25 18:29:00 +03:00
|
|
|
let tmp_stmts = translate_statements ctxt expr in
|
|
|
|
( ( A.SLocalDecl ((tmp_var, Expr.pos expr), (TAny, Expr.pos expr)),
|
|
|
|
Expr.pos expr )
|
2021-06-23 18:47:34 +03:00
|
|
|
:: tmp_stmts,
|
2022-08-25 18:29:00 +03:00
|
|
|
(A.EVar tmp_var, Expr.pos expr) )
|
2021-06-22 19:16:47 +03:00
|
|
|
|
2022-08-25 17:35:08 +03:00
|
|
|
and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) :
|
2022-07-28 11:36:36 +03:00
|
|
|
A.block =
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark block_expr with
|
2022-08-12 23:42:39 +03:00
|
|
|
| EAssert e ->
|
2021-06-23 18:47:34 +03:00
|
|
|
(* Assertions are always encapsulated in a unit-typed let binding *)
|
|
|
|
let e_stmts, new_e = translate_expr ctxt e in
|
2022-08-12 23:42:39 +03:00
|
|
|
e_stmts @ [A.SAssert (Marked.unmark new_e), Expr.pos block_expr]
|
|
|
|
| EApp ((EAbs (binder, taus), binder_mark), args) ->
|
2021-06-22 19:16:47 +03:00
|
|
|
(* This defines multiple local variables at the time *)
|
2022-08-12 23:42:39 +03:00
|
|
|
let binder_pos = Expr.mark_pos binder_mark in
|
2021-06-22 19:16:47 +03:00
|
|
|
let vars, body = Bindlib.unmbind binder in
|
|
|
|
let vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) taus in
|
|
|
|
let ctxt =
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
var_dict =
|
|
|
|
List.fold_left
|
|
|
|
(fun var_dict (x, _) ->
|
2022-07-28 11:36:36 +03:00
|
|
|
Var.Map.add x
|
2021-06-24 15:52:51 +03:00
|
|
|
(A.LocalName.fresh (Bindlib.name_of x, binder_pos))
|
|
|
|
var_dict)
|
2021-06-22 19:16:47 +03:00
|
|
|
ctxt.var_dict vars_tau;
|
|
|
|
}
|
|
|
|
in
|
|
|
|
let local_decls =
|
|
|
|
List.map
|
|
|
|
(fun (x, tau) ->
|
2022-07-28 11:36:36 +03:00
|
|
|
( A.SLocalDecl ((Var.Map.find x ctxt.var_dict, binder_pos), tau),
|
2022-06-03 17:40:03 +03:00
|
|
|
binder_pos ))
|
2021-06-22 19:16:47 +03:00
|
|
|
vars_tau
|
|
|
|
in
|
|
|
|
let vars_args =
|
|
|
|
List.map2
|
2021-06-23 18:47:34 +03:00
|
|
|
(fun (x, tau) arg ->
|
2022-07-28 11:36:36 +03:00
|
|
|
(Var.Map.find x ctxt.var_dict, binder_pos), tau, arg)
|
2021-06-22 19:16:47 +03:00
|
|
|
vars_tau args
|
|
|
|
in
|
|
|
|
let def_blocks =
|
|
|
|
List.map
|
2021-06-23 18:47:34 +03:00
|
|
|
(fun (x, _tau, arg) ->
|
|
|
|
let ctxt =
|
2022-03-21 16:58:54 +03:00
|
|
|
{
|
|
|
|
ctxt with
|
2022-05-30 12:20:48 +03:00
|
|
|
inside_definition_of = Some (Marked.unmark x);
|
|
|
|
context_name =
|
|
|
|
Marked.unmark (A.LocalName.get_info (Marked.unmark x));
|
2022-03-21 16:58:54 +03:00
|
|
|
}
|
2021-06-23 18:47:34 +03:00
|
|
|
in
|
|
|
|
let arg_stmts, new_arg = translate_expr ctxt arg in
|
|
|
|
arg_stmts @ [A.SLocalDef (x, new_arg), binder_pos])
|
2021-06-22 19:16:47 +03:00
|
|
|
vars_args
|
|
|
|
in
|
2021-06-23 18:47:34 +03:00
|
|
|
let rest_of_block = translate_statements ctxt body in
|
|
|
|
local_decls @ List.flatten def_blocks @ rest_of_block
|
2022-08-12 23:42:39 +03:00
|
|
|
| EAbs (binder, taus) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
let vars, body = Bindlib.unmbind binder in
|
2022-08-12 23:42:39 +03:00
|
|
|
let binder_pos = Expr.pos block_expr in
|
2021-06-24 15:52:51 +03:00
|
|
|
let vars_tau = List.map2 (fun x tau -> x, tau) (Array.to_list vars) taus in
|
2021-06-24 18:50:08 +03:00
|
|
|
let closure_name =
|
|
|
|
match ctxt.inside_definition_of with
|
2022-08-12 23:42:39 +03:00
|
|
|
| None -> A.LocalName.fresh (ctxt.context_name, Expr.pos block_expr)
|
2021-06-24 18:50:08 +03:00
|
|
|
| Some x -> x
|
|
|
|
in
|
2021-06-24 15:52:51 +03:00
|
|
|
let ctxt =
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
var_dict =
|
|
|
|
List.fold_left
|
|
|
|
(fun var_dict (x, _) ->
|
2022-07-28 11:36:36 +03:00
|
|
|
Var.Map.add x
|
2021-06-24 15:52:51 +03:00
|
|
|
(A.LocalName.fresh (Bindlib.name_of x, binder_pos))
|
|
|
|
var_dict)
|
|
|
|
ctxt.var_dict vars_tau;
|
2021-06-24 18:50:08 +03:00
|
|
|
inside_definition_of = None;
|
2021-06-24 15:52:51 +03:00
|
|
|
}
|
|
|
|
in
|
|
|
|
let new_body = translate_statements ctxt body in
|
|
|
|
[
|
|
|
|
( A.SInnerFuncDef
|
|
|
|
( (closure_name, binder_pos),
|
|
|
|
{
|
|
|
|
func_params =
|
|
|
|
List.map
|
|
|
|
(fun (var, tau) ->
|
2022-07-28 11:36:36 +03:00
|
|
|
(Var.Map.find var ctxt.var_dict, binder_pos), tau)
|
2021-06-24 15:52:51 +03:00
|
|
|
vars_tau;
|
|
|
|
func_body = new_body;
|
|
|
|
} ),
|
|
|
|
binder_pos );
|
|
|
|
]
|
2022-08-12 23:42:39 +03:00
|
|
|
| EMatch (e1, args, e_name) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
let e1_stmts, new_e1 = translate_expr ctxt e1 in
|
|
|
|
let new_args =
|
|
|
|
List.fold_left
|
|
|
|
(fun new_args arg ->
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark arg with
|
2022-08-12 23:42:39 +03:00
|
|
|
| EAbs (binder, _) ->
|
2021-06-24 15:52:51 +03:00
|
|
|
let vars, body = Bindlib.unmbind binder in
|
|
|
|
assert (Array.length vars = 1);
|
|
|
|
let var = vars.(0) in
|
|
|
|
let scalc_var =
|
2022-08-12 23:42:39 +03:00
|
|
|
A.LocalName.fresh (Bindlib.name_of var, Expr.pos arg)
|
2021-06-24 15:52:51 +03:00
|
|
|
in
|
|
|
|
let ctxt =
|
2022-07-28 11:36:36 +03:00
|
|
|
{ ctxt with var_dict = Var.Map.add var scalc_var ctxt.var_dict }
|
2021-06-24 15:52:51 +03:00
|
|
|
in
|
|
|
|
let new_arg = translate_statements ctxt body in
|
|
|
|
(new_arg, scalc_var) :: new_args
|
|
|
|
| _ -> assert false
|
|
|
|
(* should not happen *))
|
|
|
|
[] args
|
|
|
|
in
|
|
|
|
let new_args = List.rev new_args in
|
2022-08-12 23:42:39 +03:00
|
|
|
e1_stmts @ [A.SSwitch (new_e1, e_name, new_args), Expr.pos block_expr]
|
|
|
|
| EIfThenElse (cond, e_true, e_false) ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let cond_stmts, s_cond = translate_expr ctxt cond in
|
|
|
|
let s_e_true = translate_statements ctxt e_true in
|
|
|
|
let s_e_false = translate_statements ctxt e_false in
|
2022-08-16 11:04:01 +03:00
|
|
|
cond_stmts
|
|
|
|
@ [A.SIfThenElse (s_cond, s_e_true, s_e_false), Expr.pos block_expr]
|
2022-08-12 23:42:39 +03:00
|
|
|
| ECatch (e_try, except, e_catch) ->
|
2021-06-23 18:47:34 +03:00
|
|
|
let s_e_try = translate_statements ctxt e_try in
|
|
|
|
let s_e_catch = translate_statements ctxt e_catch in
|
2022-08-12 23:42:39 +03:00
|
|
|
[A.STryExcept (s_e_try, except, s_e_catch), Expr.pos block_expr]
|
|
|
|
| ERaise except ->
|
2022-07-25 12:00:18 +03:00
|
|
|
(* Before raising the exception, we still give a dummy definition to the
|
|
|
|
current variable so that tools like mypy don't complain. *)
|
|
|
|
(match ctxt.inside_definition_of with
|
|
|
|
| None -> []
|
|
|
|
| Some x ->
|
|
|
|
[
|
|
|
|
( A.SLocalDef
|
2022-08-16 11:04:01 +03:00
|
|
|
( (x, Expr.pos block_expr),
|
|
|
|
(Ast.EVar Ast.dead_value, Expr.pos block_expr) ),
|
2022-08-12 23:42:39 +03:00
|
|
|
Expr.pos block_expr );
|
2022-07-25 12:00:18 +03:00
|
|
|
])
|
2022-08-12 23:42:39 +03:00
|
|
|
@ [A.SRaise except, Expr.pos block_expr]
|
2022-02-01 17:41:53 +03:00
|
|
|
| _ -> (
|
2021-06-23 18:47:34 +03:00
|
|
|
let e_stmts, new_e = translate_expr ctxt block_expr in
|
2021-06-24 15:52:51 +03:00
|
|
|
e_stmts
|
2022-02-01 17:41:53 +03:00
|
|
|
@
|
|
|
|
match e_stmts with
|
|
|
|
| (A.SRaise _, _) :: _ ->
|
|
|
|
(* if the last statement raises an exception, then we don't need to return
|
|
|
|
or to define the current variable since this code will be
|
|
|
|
unreachable *)
|
|
|
|
[]
|
|
|
|
| _ ->
|
|
|
|
[
|
|
|
|
( (match ctxt.inside_definition_of with
|
2022-05-30 12:20:48 +03:00
|
|
|
| None -> A.SReturn (Marked.unmark new_e)
|
|
|
|
| Some x -> A.SLocalDef (Marked.same_mark_as x new_e, new_e)),
|
2022-08-12 23:42:39 +03:00
|
|
|
Expr.pos block_expr );
|
2022-02-01 17:41:53 +03:00
|
|
|
])
|
2021-06-22 17:01:57 +03:00
|
|
|
|
2022-04-26 17:06:36 +03:00
|
|
|
let rec translate_scope_body_expr
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope_name : ScopeName.t)
|
|
|
|
(decl_ctx : decl_ctx)
|
2022-08-25 17:35:08 +03:00
|
|
|
(var_dict : ('m L.naked_expr, A.LocalName.t) Var.Map.t)
|
|
|
|
(func_dict : ('m L.naked_expr, A.TopLevelName.t) Var.Map.t)
|
|
|
|
(scope_expr : 'm L.naked_expr scope_body_expr) : A.block =
|
2022-04-26 17:06:36 +03:00
|
|
|
match scope_expr with
|
|
|
|
| Result e ->
|
|
|
|
let block, new_e =
|
|
|
|
translate_expr
|
2022-05-04 18:40:55 +03:00
|
|
|
{
|
2022-04-26 17:06:36 +03:00
|
|
|
decl_ctx;
|
|
|
|
func_dict;
|
|
|
|
var_dict;
|
|
|
|
inside_definition_of = None;
|
2022-08-12 23:42:39 +03:00
|
|
|
context_name = Marked.unmark (ScopeName.get_info scope_name);
|
2022-05-04 18:40:55 +03:00
|
|
|
}
|
|
|
|
e
|
|
|
|
in
|
2022-05-30 12:20:48 +03:00
|
|
|
block @ [A.SReturn (Marked.unmark new_e), Marked.get_mark new_e]
|
2022-04-26 17:06:36 +03:00
|
|
|
| ScopeLet scope_let ->
|
|
|
|
let let_var, scope_let_next = Bindlib.unbind scope_let.scope_let_next in
|
|
|
|
let let_var_id =
|
|
|
|
A.LocalName.fresh (Bindlib.name_of let_var, scope_let.scope_let_pos)
|
2022-05-04 18:40:55 +03:00
|
|
|
in
|
2022-07-28 11:36:36 +03:00
|
|
|
let new_var_dict = Var.Map.add let_var let_var_id var_dict in
|
2022-04-26 17:22:47 +03:00
|
|
|
(match scope_let.scope_let_kind with
|
2022-08-12 23:42:39 +03:00
|
|
|
| Assertion ->
|
2022-04-26 17:22:47 +03:00
|
|
|
translate_statements
|
2022-05-04 18:40:55 +03:00
|
|
|
{
|
2022-04-26 17:22:47 +03:00
|
|
|
decl_ctx;
|
|
|
|
func_dict;
|
|
|
|
var_dict;
|
|
|
|
inside_definition_of = Some let_var_id;
|
2022-08-12 23:42:39 +03:00
|
|
|
context_name = Marked.unmark (ScopeName.get_info scope_name);
|
2022-05-04 18:40:55 +03:00
|
|
|
}
|
2022-04-26 17:22:47 +03:00
|
|
|
scope_let.scope_let_expr
|
2022-05-04 18:40:55 +03:00
|
|
|
| _ ->
|
2022-04-26 17:22:47 +03:00
|
|
|
let let_expr_stmts, new_let_expr =
|
2022-04-26 17:06:36 +03:00
|
|
|
translate_expr
|
|
|
|
{
|
|
|
|
decl_ctx;
|
|
|
|
func_dict;
|
|
|
|
var_dict;
|
|
|
|
inside_definition_of = Some let_var_id;
|
2022-08-12 23:42:39 +03:00
|
|
|
context_name = Marked.unmark (ScopeName.get_info scope_name);
|
2022-04-26 17:06:36 +03:00
|
|
|
}
|
2022-04-26 17:22:47 +03:00
|
|
|
scope_let.scope_let_expr
|
2021-06-22 17:01:57 +03:00
|
|
|
in
|
2022-04-26 17:06:36 +03:00
|
|
|
let_expr_stmts
|
|
|
|
@ [
|
|
|
|
( A.SLocalDecl
|
|
|
|
((let_var_id, scope_let.scope_let_pos), scope_let.scope_let_typ),
|
2022-04-26 17:22:47 +03:00
|
|
|
scope_let.scope_let_pos );
|
|
|
|
( A.SLocalDef ((let_var_id, scope_let.scope_let_pos), new_let_expr),
|
|
|
|
scope_let.scope_let_pos );
|
|
|
|
])
|
2022-04-26 17:06:36 +03:00
|
|
|
@ translate_scope_body_expr scope_name decl_ctx new_var_dict func_dict
|
|
|
|
scope_let_next
|
2021-06-22 17:01:57 +03:00
|
|
|
|
2022-06-23 15:06:11 +03:00
|
|
|
let translate_program (p : 'm L.program) : A.program =
|
2021-06-22 17:01:57 +03:00
|
|
|
{
|
2022-08-12 23:42:39 +03:00
|
|
|
decl_ctx = p.decl_ctx;
|
2021-06-22 17:01:57 +03:00
|
|
|
scopes =
|
|
|
|
(let _, new_scopes =
|
2022-08-16 18:09:26 +03:00
|
|
|
Scope.fold_left
|
2022-04-26 17:06:36 +03:00
|
|
|
~f:(fun (func_dict, new_scopes) scope_def scope_var ->
|
|
|
|
let scope_input_var, scope_body_expr =
|
|
|
|
Bindlib.unbind scope_def.scope_body.scope_body_expr
|
2021-06-23 18:47:34 +03:00
|
|
|
in
|
2022-04-26 17:06:36 +03:00
|
|
|
let input_pos =
|
2022-08-12 23:42:39 +03:00
|
|
|
Marked.get_mark (ScopeName.get_info scope_def.scope_name)
|
2022-03-08 17:03:14 +03:00
|
|
|
in
|
2022-04-26 17:06:36 +03:00
|
|
|
let scope_input_var_id =
|
|
|
|
A.LocalName.fresh (Bindlib.name_of scope_input_var, input_pos)
|
|
|
|
in
|
|
|
|
let var_dict =
|
2022-07-28 11:36:36 +03:00
|
|
|
Var.Map.singleton scope_input_var scope_input_var_id
|
2022-04-26 17:06:36 +03:00
|
|
|
in
|
|
|
|
let new_scope_body =
|
2022-08-12 23:42:39 +03:00
|
|
|
translate_scope_body_expr scope_def.scope_name p.decl_ctx
|
2022-04-26 17:06:36 +03:00
|
|
|
var_dict func_dict scope_body_expr
|
|
|
|
in
|
|
|
|
let func_id =
|
|
|
|
A.TopLevelName.fresh (Bindlib.name_of scope_var, Pos.no_pos)
|
2022-02-14 19:01:34 +03:00
|
|
|
in
|
2022-07-28 11:36:36 +03:00
|
|
|
let func_dict = Var.Map.add scope_var func_id func_dict in
|
2021-06-24 15:52:51 +03:00
|
|
|
( func_dict,
|
2022-02-14 19:01:34 +03:00
|
|
|
{
|
2022-08-12 23:42:39 +03:00
|
|
|
Ast.scope_body_name = scope_def.scope_name;
|
2022-02-14 19:01:34 +03:00
|
|
|
Ast.scope_body_var = func_id;
|
|
|
|
scope_body_func =
|
|
|
|
{
|
2022-04-26 17:06:36 +03:00
|
|
|
A.func_params =
|
|
|
|
[
|
|
|
|
( (scope_input_var_id, input_pos),
|
2022-08-23 16:23:52 +03:00
|
|
|
( TStruct scope_def.scope_body.scope_body_input_struct,
|
2022-04-26 17:06:36 +03:00
|
|
|
input_pos ) );
|
|
|
|
];
|
2022-02-14 19:01:34 +03:00
|
|
|
A.func_body = new_scope_body;
|
|
|
|
};
|
|
|
|
}
|
2021-06-24 15:52:51 +03:00
|
|
|
:: new_scopes ))
|
2022-04-26 17:06:36 +03:00
|
|
|
~init:
|
|
|
|
( (if !Cli.avoid_exceptions_flag then
|
2022-07-28 11:36:36 +03:00
|
|
|
Var.Map.singleton L.handle_default_opt A.handle_default_opt
|
|
|
|
else Var.Map.singleton L.handle_default A.handle_default),
|
2022-04-26 17:06:36 +03:00
|
|
|
[] )
|
2022-08-12 23:42:39 +03:00
|
|
|
p.scopes
|
2021-06-22 17:01:57 +03:00
|
|
|
in
|
|
|
|
List.rev new_scopes);
|
|
|
|
}
|