Uniform naming of conversion modules across compilation passes

This commit is contained in:
Louis Gesbert 2022-11-07 13:50:28 +01:00
parent 6ecca5c664
commit 47799ea24f
25 changed files with 702 additions and 619 deletions

View File

@ -1,7 +1,15 @@
(library (library
(name dcalc) (name dcalc)
(public_name catala.dcalc) (public_name catala.dcalc)
(libraries bindlib unionFind utils re ubase catala.runtime_ocaml shared_ast) (libraries
bindlib
unionFind
utils
re
ubase
catala.runtime_ocaml
shared_ast
scopelang)
(preprocess (preprocess
(pps visitors.ppx))) (pps visitors.ppx)))

View File

@ -20,19 +20,18 @@ open Shared_ast
type scope_var_ctx = { type scope_var_ctx = {
scope_var_name : ScopeVar.t; scope_var_name : ScopeVar.t;
scope_var_typ : naked_typ; scope_var_typ : naked_typ;
scope_var_io : Ast.io; scope_var_io : Desugared.Ast.io;
} }
type 'm scope_sig_ctx = { type 'm scope_sig_ctx = {
scope_sig_local_vars : scope_var_ctx list; (** List of scope variables *) scope_sig_local_vars : scope_var_ctx list; (** List of scope variables *)
scope_sig_scope_var : 'm Dcalc.Ast.expr Var.t; scope_sig_scope_var : 'm Ast.expr Var.t; (** Var representing the scope *)
(** Var representing the scope *) scope_sig_input_var : 'm Ast.expr Var.t;
scope_sig_input_var : 'm Dcalc.Ast.expr Var.t;
(** Var representing the scope input inside the scope func *) (** Var representing the scope input inside the scope func *)
scope_sig_input_struct : StructName.t; (** Scope input *) scope_sig_input_struct : StructName.t; (** Scope input *)
scope_sig_output_struct : StructName.t; (** Scope output *) scope_sig_output_struct : StructName.t; (** Scope output *)
scope_sig_in_fields : scope_sig_in_fields :
(StructFieldName.t * Ast.io_input Marked.pos) ScopeVarMap.t; (StructFieldName.t * Desugared.Ast.io_input Marked.pos) ScopeVarMap.t;
(** Mapping between the input scope variables and the input struct fields. *) (** Mapping between the input scope variables and the input struct fields. *)
scope_sig_out_fields : StructFieldName.t ScopeVarMap.t; scope_sig_out_fields : StructFieldName.t ScopeVarMap.t;
(** Mapping between the output scope variables and the output struct (** Mapping between the output scope variables and the output struct
@ -47,10 +46,11 @@ type 'm ctx = {
enums : enum_ctx; enums : enum_ctx;
scope_name : ScopeName.t; scope_name : ScopeName.t;
scopes_parameters : 'm scope_sigs_ctx; scopes_parameters : 'm scope_sigs_ctx;
scope_vars : ('m Dcalc.Ast.expr Var.t * naked_typ * Ast.io) ScopeVarMap.t; scope_vars : ('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVarMap.t;
subscope_vars : subscope_vars :
('m Dcalc.Ast.expr Var.t * naked_typ * Ast.io) ScopeVarMap.t SubScopeMap.t; ('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVarMap.t
local_vars : ('m Ast.expr, 'm Dcalc.Ast.expr Var.t) Var.Map.t; SubScopeMap.t;
local_vars : ('m Scopelang.Ast.expr, 'm Ast.expr Var.t) Var.Map.t;
} }
let empty_ctx let empty_ctx
@ -99,9 +99,9 @@ let merge_defaults caller callee =
body body
let tag_with_log_entry let tag_with_log_entry
(e : 'm Dcalc.Ast.expr boxed) (e : 'm Ast.expr boxed)
(l : log_entry) (l : log_entry)
(markings : Utils.Uid.MarkedString.info list) : 'm Dcalc.Ast.expr boxed = (markings : Utils.Uid.MarkedString.info list) : 'm Ast.expr boxed =
let m = mark_tany (Marked.get_mark e) (Expr.pos e) in let m = mark_tany (Marked.get_mark e) (Expr.pos e) in
Expr.eapp (Expr.eop (Unop (Log (l, markings))) m) [e] m Expr.eapp (Expr.eop (Unop (Log (l, markings))) m) [e] m
@ -112,10 +112,10 @@ let tag_with_log_entry
NOTE: the choice of the exception that will be triggered and show in the NOTE: the choice of the exception that will be triggered and show in the
trace is arbitrary (but deterministic). *) trace is arbitrary (but deterministic). *)
let collapse_similar_outcomes (type m) (excepts : m Ast.expr list) : let collapse_similar_outcomes (type m) (excepts : m Scopelang.Ast.expr list) :
m Ast.expr list = m Scopelang.Ast.expr list =
let module ExprMap = Map.Make (struct let module ExprMap = Map.Make (struct
type t = m Ast.expr type t = m Scopelang.Ast.expr
let compare = Expr.compare let compare = Expr.compare
end) in end) in
@ -156,12 +156,13 @@ let thunk_scope_arg io_in e =
let silent_var = Var.make "_" in let silent_var = Var.make "_" in
let pos = Marked.get_mark io_in in let pos = Marked.get_mark io_in in
match Marked.unmark io_in with match Marked.unmark io_in with
| Ast.NoInput -> invalid_arg "thunk_scope_arg" | Desugared.Ast.NoInput -> invalid_arg "thunk_scope_arg"
| Ast.OnlyInput -> Expr.eerroronempty e (Marked.get_mark e) | Desugared.Ast.OnlyInput -> Expr.eerroronempty e (Marked.get_mark e)
| Ast.Reentrant -> Expr.make_abs [| silent_var |] e [TLit TUnit, pos] pos | Desugared.Ast.Reentrant ->
Expr.make_abs [| silent_var |] e [TLit TUnit, pos] pos
let rec translate_expr (ctx : 'm ctx) (e : 'm Ast.expr) : let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
'm Dcalc.Ast.expr boxed = 'm Ast.expr boxed =
let m = Marked.get_mark e in let m = Marked.get_mark e in
match Marked.unmark e with match Marked.unmark e with
| EVar v -> Expr.evar (Var.Map.find v ctx.local_vars) m | EVar v -> Expr.evar (Var.Map.find v ctx.local_vars) m
@ -215,7 +216,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Ast.expr) :
(fun var_name str_field expr -> (fun var_name str_field expr ->
let expr = let expr =
match str_field, expr with match str_field, expr with
| Some (_, (Ast.Reentrant, _)), None -> | Some (_, (Desugared.Ast.Reentrant, _)), None ->
Some (Expr.unbox (Expr.elit LEmptyError (mark_tany m pos))) Some (Expr.unbox (Expr.elit LEmptyError (mark_tany m pos)))
| _ -> expr | _ -> expr
in in
@ -372,10 +373,10 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Ast.expr) :
come later in the chain of let-bindings. *) come later in the chain of let-bindings. *)
let translate_rule let translate_rule
(ctx : 'm ctx) (ctx : 'm ctx)
(rule : 'm Ast.rule) (rule : 'm Scopelang.Ast.rule)
((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) : ((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) :
('m Dcalc.Ast.expr scope_body_expr Bindlib.box -> ('m Ast.expr scope_body_expr Bindlib.box ->
'm Dcalc.Ast.expr scope_body_expr Bindlib.box) 'm Ast.expr scope_body_expr Bindlib.box)
* 'm ctx = * 'm ctx =
match rule with match rule with
| Definition ((ScopelangScopeVar a, var_def_pos), tau, a_io, e) -> | Definition ((ScopelangScopeVar a, var_def_pos), tau, a_io, e) ->
@ -436,7 +437,9 @@ let translate_rule
(VarDef (Marked.unmark tau)) (VarDef (Marked.unmark tau))
[sigma_name, pos_sigma; a_name] [sigma_name, pos_sigma; a_name]
in in
let thunked_or_nonempty_new_e = thunk_scope_arg a_io.Ast.io_input new_e in let thunked_or_nonempty_new_e =
thunk_scope_arg a_io.Desugared.Ast.io_input new_e
in
( (fun next -> ( (fun next ->
Bindlib.box_apply2 Bindlib.box_apply2
(fun next thunked_or_nonempty_new_e -> (fun next thunked_or_nonempty_new_e ->
@ -478,14 +481,15 @@ let translate_rule
let all_subscope_input_vars = let all_subscope_input_vars =
List.filter List.filter
(fun var_ctx -> (fun var_ctx ->
match Marked.unmark var_ctx.scope_var_io.Ast.io_input with match Marked.unmark var_ctx.scope_var_io.Desugared.Ast.io_input with
| NoInput -> false | NoInput -> false
| _ -> true) | _ -> true)
all_subscope_vars all_subscope_vars
in in
let all_subscope_output_vars = let all_subscope_output_vars =
List.filter List.filter
(fun var_ctx -> Marked.unmark var_ctx.scope_var_io.Ast.io_output) (fun var_ctx ->
Marked.unmark var_ctx.scope_var_io.Desugared.Ast.io_output)
all_subscope_vars all_subscope_vars
in in
let scope_dcalc_var = subscope_sig.scope_sig_scope_var in let scope_dcalc_var = subscope_sig.scope_sig_scope_var in
@ -639,11 +643,11 @@ let translate_rule
let translate_rules let translate_rules
(ctx : 'm ctx) (ctx : 'm ctx)
(rules : 'm Ast.rule list) (rules : 'm Scopelang.Ast.rule list)
((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) ((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info)
(mark : 'm mark) (mark : 'm mark)
(scope_sig : 'm scope_sig_ctx) : (scope_sig : 'm scope_sig_ctx) :
'm Dcalc.Ast.expr scope_body_expr Bindlib.box * 'm ctx = 'm Ast.expr scope_body_expr Bindlib.box * 'm ctx =
let scope_lets, new_ctx = let scope_lets, new_ctx =
List.fold_left List.fold_left
(fun (scope_lets, ctx) rule -> (fun (scope_lets, ctx) rule ->
@ -658,7 +662,7 @@ let translate_rules
Expr.estruct scope_sig.scope_sig_output_struct Expr.estruct scope_sig.scope_sig_output_struct
(ScopeVarMap.fold (ScopeVarMap.fold
(fun var (dcalc_var, _, io) acc -> (fun var (dcalc_var, _, io) acc ->
if Marked.unmark io.Ast.io_output then if Marked.unmark io.Desugared.Ast.io_output then
let field = ScopeVarMap.find var scope_sig.scope_sig_out_fields in let field = ScopeVarMap.find var scope_sig.scope_sig_out_fields in
StructFieldMap.add field StructFieldMap.add field
(Expr.make_var dcalc_var (mark_tany mark pos_sigma)) (Expr.make_var dcalc_var (mark_tany mark pos_sigma))
@ -678,8 +682,8 @@ let translate_scope_decl
(enum_ctx : enum_ctx) (enum_ctx : enum_ctx)
(sctx : 'm scope_sigs_ctx) (sctx : 'm scope_sigs_ctx)
(scope_name : ScopeName.t) (scope_name : ScopeName.t)
(sigma : 'm Ast.scope_decl) : (sigma : 'm Scopelang.Ast.scope_decl) :
'm Dcalc.Ast.expr scope_body Bindlib.box * struct_ctx = 'm Ast.expr scope_body Bindlib.box * struct_ctx =
let sigma_info = ScopeName.get_info sigma.scope_decl_name in let sigma_info = ScopeName.get_info sigma.scope_decl_name in
let scope_sig = ScopeMap.find sigma.scope_decl_name sctx in let scope_sig = ScopeMap.find sigma.scope_decl_name sctx in
let scope_variables = scope_sig.scope_sig_local_vars in let scope_variables = scope_sig.scope_sig_local_vars in
@ -786,17 +790,20 @@ let translate_scope_decl
(input_destructurings rules_with_return_expr)), (input_destructurings rules_with_return_expr)),
new_struct_ctx ) new_struct_ctx )
let translate_program (prgm : 'm Ast.program) : 'm Dcalc.Ast.program = let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
let scope_dependencies = Dependency.build_program_dep_graph prgm in let scope_dependencies = Scopelang.Dependency.build_program_dep_graph prgm in
Dependency.check_for_cycle_in_scope scope_dependencies; Scopelang.Dependency.check_for_cycle_in_scope scope_dependencies;
let scope_ordering = Dependency.get_scope_ordering scope_dependencies in let scope_ordering =
Scopelang.Dependency.get_scope_ordering scope_dependencies
in
let decl_ctx = prgm.program_ctx in let decl_ctx = prgm.program_ctx in
let sctx : 'm scope_sigs_ctx = let sctx : 'm scope_sigs_ctx =
ScopeMap.mapi ScopeMap.mapi
(fun scope_name scope -> (fun scope_name scope ->
let scope_dvar = let scope_dvar =
Var.make Var.make
(Marked.unmark (ScopeName.get_info scope.Ast.scope_decl_name)) (Marked.unmark
(ScopeName.get_info scope.Scopelang.Ast.scope_decl_name))
in in
let scope_return = ScopeMap.find scope_name decl_ctx.ctx_scopes in let scope_return = ScopeMap.find scope_name decl_ctx.ctx_scopes in
let scope_input_var = let scope_input_var =
@ -811,14 +818,14 @@ let translate_program (prgm : 'm Ast.program) : 'm Dcalc.Ast.program =
let scope_sig_in_fields = let scope_sig_in_fields =
ScopeVarMap.filter_map ScopeVarMap.filter_map
(fun dvar (_, vis) -> (fun dvar (_, vis) ->
match Marked.unmark vis.Ast.io_input with match Marked.unmark vis.Desugared.Ast.io_input with
| NoInput -> None | NoInput -> None
| OnlyInput | Reentrant -> | OnlyInput | Reentrant ->
let info = ScopeVar.get_info dvar in let info = ScopeVar.get_info dvar in
let s = Marked.unmark info ^ "_in" in let s = Marked.unmark info ^ "_in" in
Some Some
( StructFieldName.fresh (s, Marked.get_mark info), ( StructFieldName.fresh (s, Marked.get_mark info),
vis.Ast.io_input )) vis.Desugared.Ast.io_input ))
scope.scope_sig scope.scope_sig
in in
{ {

View File

@ -16,4 +16,4 @@
(** Scope language to default calculus translator *) (** Scope language to default calculus translator *)
val translate_program : 'm Ast.program -> 'm Dcalc.Ast.program val translate_program : 'm Scopelang.Ast.program -> 'm Ast.program

View File

@ -21,20 +21,6 @@ open Shared_ast
(** {1 Names, Maps and Keys} *) (** {1 Names, Maps and Keys} *)
module IdentMap : Map.S with type key = String.t = Map.Make (String)
module RuleName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module RuleMap : Map.S with type key = RuleName.t = Map.Make (RuleName)
module RuleSet : Set.S with type elt = RuleName.t = Set.Make (RuleName)
module LabelName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module LabelMap : Map.S with type key = LabelName.t = Map.Make (LabelName)
module LabelSet : Set.S with type elt = LabelName.t = Set.Make (LabelName)
(** Inside a scope, a definition can refer either to a scope def, or a subscope (** Inside a scope, a definition can refer either to a scope def, or a subscope
def *) def *)
module ScopeDef = struct module ScopeDef = struct
@ -103,6 +89,9 @@ module ExprMap = Map.Make (struct
let compare = Expr.compare let compare = Expr.compare
end) end)
type io_input = NoInput | OnlyInput | Reentrant
type io = { io_output : bool Marked.pos; io_input : io_input Marked.pos }
type exception_situation = type exception_situation =
| BaseCase | BaseCase
| ExceptionToLabel of LabelName.t Marked.pos | ExceptionToLabel of LabelName.t Marked.pos
@ -192,7 +181,7 @@ type scope_def = {
scope_def_rules : rule RuleMap.t; scope_def_rules : rule RuleMap.t;
scope_def_typ : typ; scope_def_typ : typ;
scope_def_is_condition : bool; scope_def_is_condition : bool;
scope_def_io : Scopelang.Ast.io; scope_def_io : io;
} }
type var_or_states = WholeVar | States of StateName.t list type var_or_states = WholeVar | States of StateName.t list

View File

@ -19,16 +19,6 @@
open Utils open Utils
open Shared_ast open Shared_ast
(** {1 Names, Maps and Keys} *)
module IdentMap : Map.S with type key = String.t
module RuleName : Uid.Id with type info = Uid.MarkedString.info
module RuleMap : Map.S with type key = RuleName.t
module RuleSet : Set.S with type elt = RuleName.t
module LabelName : Uid.Id with type info = Uid.MarkedString.info
module LabelMap : Map.S with type key = LabelName.t
module LabelSet : Set.S with type elt = LabelName.t
(** Inside a scope, a definition can refer either to a scope def, or a subscope (** Inside a scope, a definition can refer either to a scope def, or a subscope
def *) def *)
module ScopeDef : sig module ScopeDef : sig
@ -88,11 +78,32 @@ type meta_assertion =
| FixedBy of reference_typ Marked.pos | FixedBy of reference_typ Marked.pos
| VariesWith of unit * variation_typ Marked.pos option | VariesWith of unit * variation_typ Marked.pos option
(** This type characterizes the three levels of visibility for a given scope
variable with regards to the scope's input and possible redefinitions inside
the scope.. *)
type io_input =
| NoInput
(** For an internal variable defined only in the scope, and does not
appear in the input. *)
| OnlyInput
(** For variables that should not be redefined in the scope, because they
appear in the input. *)
| Reentrant
(** For variables defined in the scope that can also be redefined by the
caller as they appear in the input. *)
type io = {
io_output : bool Marked.pos;
(** [true] is present in the output of the scope. *)
io_input : io_input Marked.pos;
}
(** Characterization of the input/output status of a scope variable. *)
type scope_def = { type scope_def = {
scope_def_rules : rule RuleMap.t; scope_def_rules : rule RuleMap.t;
scope_def_typ : typ; scope_def_typ : typ;
scope_def_is_condition : bool; scope_def_is_condition : bool;
scope_def_io : Scopelang.Ast.io; scope_def_io : io;
} }
type var_or_states = WholeVar | States of StateName.t list type var_or_states = WholeVar | States of StateName.t list

View File

@ -229,10 +229,10 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t =
(** {2 Graph declaration} *) (** {2 Graph declaration} *)
module ExceptionVertex = struct module ExceptionVertex = struct
include Ast.RuleSet include RuleSet
let hash (x : t) : int = let hash (x : t) : int =
Ast.RuleSet.fold (fun r acc -> Int.logxor (Ast.RuleName.hash r) acc) x 0 RuleSet.fold (fun r acc -> Int.logxor (RuleName.hash r) acc) x 0
let equal x y = compare x y = 0 let equal x y = compare x y = 0
end end
@ -257,13 +257,13 @@ module ExceptionsSCC = Graph.Components.Make (ExceptionsDependencies)
(** {2 Graph computations} *) (** {2 Graph computations} *)
type exception_edge = { type exception_edge = {
label_from : Ast.LabelName.t; label_from : LabelName.t;
label_to : Ast.LabelName.t; label_to : LabelName.t;
edge_positions : Pos.t list; edge_positions : Pos.t list;
} }
let build_exceptions_graph let build_exceptions_graph
(def : Ast.rule Ast.RuleMap.t) (def : Ast.rule RuleMap.t)
(def_info : Ast.ScopeDef.t) : ExceptionsDependencies.t = (def_info : Ast.ScopeDef.t) : ExceptionsDependencies.t =
(* First we partition the definitions into groups bearing the same label. To (* First we partition the definitions into groups bearing the same label. To
handle the rules that were not labeled by the user, we create implicit handle the rules that were not labeled by the user, we create implicit
@ -271,63 +271,57 @@ let build_exceptions_graph
(* All the rules of the form [definition x ...] are base case with no explicit (* All the rules of the form [definition x ...] are base case with no explicit
label, so they should share this implicit label. *) label, so they should share this implicit label. *)
let base_case_implicit_label = let base_case_implicit_label = LabelName.fresh ("base_case", Pos.no_pos) in
Ast.LabelName.fresh ("base_case", Pos.no_pos)
in
(* When declaring [exception definition x ...], it means there is a unique (* When declaring [exception definition x ...], it means there is a unique
rule [R] to which this can be an exception to. So we give a unique label to rule [R] to which this can be an exception to. So we give a unique label to
all the rules that are implicitly exceptions to rule [R]. *) all the rules that are implicitly exceptions to rule [R]. *)
let exception_to_rule_implicit_labels : Ast.LabelName.t Ast.RuleMap.t = let exception_to_rule_implicit_labels : LabelName.t RuleMap.t =
Ast.RuleMap.fold RuleMap.fold
(fun _ rule_from exception_to_rule_implicit_labels -> (fun _ rule_from exception_to_rule_implicit_labels ->
match rule_from.Ast.rule_exception with match rule_from.Ast.rule_exception with
| Ast.ExceptionToRule (rule_to, _) -> ( | Ast.ExceptionToRule (rule_to, _) -> (
match match RuleMap.find_opt rule_to exception_to_rule_implicit_labels with
Ast.RuleMap.find_opt rule_to exception_to_rule_implicit_labels
with
| Some _ -> | Some _ ->
(* we already created the label *) exception_to_rule_implicit_labels (* we already created the label *) exception_to_rule_implicit_labels
| None -> | None ->
Ast.RuleMap.add rule_to RuleMap.add rule_to
(Ast.LabelName.fresh (LabelName.fresh
( "exception_to_" ( "exception_to_" ^ Marked.unmark (RuleName.get_info rule_to),
^ Marked.unmark (Ast.RuleName.get_info rule_to),
Pos.no_pos )) Pos.no_pos ))
exception_to_rule_implicit_labels) exception_to_rule_implicit_labels)
| _ -> exception_to_rule_implicit_labels) | _ -> exception_to_rule_implicit_labels)
def Ast.RuleMap.empty def RuleMap.empty
in in
(* When declaring [exception foo_l definition x ...], the rule is exception to (* When declaring [exception foo_l definition x ...], the rule is exception to
all the rules sharing label [foo_l]. So we give a unique label to all the all the rules sharing label [foo_l]. So we give a unique label to all the
rules that are implicitly exceptions to rule [foo_l]. *) rules that are implicitly exceptions to rule [foo_l]. *)
let exception_to_label_implicit_labels : Ast.LabelName.t Ast.LabelMap.t = let exception_to_label_implicit_labels : LabelName.t LabelMap.t =
Ast.RuleMap.fold RuleMap.fold
(fun _ rule_from (fun _ rule_from
(exception_to_label_implicit_labels : Ast.LabelName.t Ast.LabelMap.t) -> (exception_to_label_implicit_labels : LabelName.t LabelMap.t) ->
match rule_from.Ast.rule_exception with match rule_from.Ast.rule_exception with
| Ast.ExceptionToLabel (label_to, _) -> ( | Ast.ExceptionToLabel (label_to, _) -> (
match match
Ast.LabelMap.find_opt label_to exception_to_label_implicit_labels LabelMap.find_opt label_to exception_to_label_implicit_labels
with with
| Some _ -> | Some _ ->
(* we already created the label *) (* we already created the label *)
exception_to_label_implicit_labels exception_to_label_implicit_labels
| None -> | None ->
Ast.LabelMap.add label_to LabelMap.add label_to
(Ast.LabelName.fresh (LabelName.fresh
( "exception_to_" ( "exception_to_" ^ Marked.unmark (LabelName.get_info label_to),
^ Marked.unmark (Ast.LabelName.get_info label_to),
Pos.no_pos )) Pos.no_pos ))
exception_to_label_implicit_labels) exception_to_label_implicit_labels)
| _ -> exception_to_label_implicit_labels) | _ -> exception_to_label_implicit_labels)
def Ast.LabelMap.empty def LabelMap.empty
in in
(* Now we have all the labels necessary to partition our rules into sets, each (* Now we have all the labels necessary to partition our rules into sets, each
one corresponding to a label relating to the structure of the exception one corresponding to a label relating to the structure of the exception
DAG. *) DAG. *)
let label_to_rule_sets = let label_to_rule_sets =
Ast.RuleMap.fold RuleMap.fold
(fun rule_name rule rule_sets -> (fun rule_name rule rule_sets ->
let label_of_rule = let label_of_rule =
match rule.Ast.rule_label with match rule.Ast.rule_label with
@ -336,23 +330,23 @@ let build_exceptions_graph
match rule.Ast.rule_exception with match rule.Ast.rule_exception with
| BaseCase -> base_case_implicit_label | BaseCase -> base_case_implicit_label
| ExceptionToRule (r, _) -> | ExceptionToRule (r, _) ->
Ast.RuleMap.find r exception_to_rule_implicit_labels RuleMap.find r exception_to_rule_implicit_labels
| ExceptionToLabel (l', _) -> | ExceptionToLabel (l', _) ->
Ast.LabelMap.find l' exception_to_label_implicit_labels) LabelMap.find l' exception_to_label_implicit_labels)
in in
Ast.LabelMap.update label_of_rule LabelMap.update label_of_rule
(fun rule_set -> (fun rule_set ->
match rule_set with match rule_set with
| None -> Some (Ast.RuleSet.singleton rule_name) | None -> Some (RuleSet.singleton rule_name)
| Some rule_set -> Some (Ast.RuleSet.add rule_name rule_set)) | Some rule_set -> Some (RuleSet.add rule_name rule_set))
rule_sets) rule_sets)
def Ast.LabelMap.empty def LabelMap.empty
in in
let find_label_of_rule (r : Ast.RuleName.t) : Ast.LabelName.t = let find_label_of_rule (r : RuleName.t) : LabelName.t =
fst fst
(Ast.LabelMap.choose (LabelMap.choose
(Ast.LabelMap.filter (LabelMap.filter
(fun _ rule_set -> Ast.RuleSet.mem r rule_set) (fun _ rule_set -> RuleSet.mem r rule_set)
label_to_rule_sets)) label_to_rule_sets))
in in
(* Next, we collect the exception edges between those groups of rules referred (* Next, we collect the exception edges between those groups of rules referred
@ -360,7 +354,7 @@ let build_exceptions_graph
edges as they are declared at each rule but should be the same for all the edges as they are declared at each rule but should be the same for all the
rules of the same group. *) rules of the same group. *)
let exception_edges : exception_edge list = let exception_edges : exception_edge list =
Ast.RuleMap.fold RuleMap.fold
(fun rule_name rule exception_edges -> (fun rule_name rule exception_edges ->
let label_from = find_label_of_rule rule_name in let label_from = find_label_of_rule rule_name in
let label_to_and_pos = let label_to_and_pos =
@ -374,16 +368,16 @@ let build_exceptions_graph
| Some (label_to, edge_pos) -> ( | Some (label_to, edge_pos) -> (
let other_edges_originating_from_same_label = let other_edges_originating_from_same_label =
List.filter List.filter
(fun edge -> Ast.LabelName.compare edge.label_from label_from = 0) (fun edge -> LabelName.compare edge.label_from label_from = 0)
exception_edges exception_edges
in in
(* We check the consistency*) (* We check the consistency*)
if Ast.LabelName.compare label_from label_to = 0 then if LabelName.compare label_from label_to = 0 then
Errors.raise_spanned_error edge_pos Errors.raise_spanned_error edge_pos
"Cannot define rule as an exception to itself"; "Cannot define rule as an exception to itself";
List.iter List.iter
(fun edge -> (fun edge ->
if Ast.LabelName.compare edge.label_to label_to <> 0 then if LabelName.compare edge.label_to label_to <> 0 then
Errors.raise_multispanned_error Errors.raise_multispanned_error
(( Some (( Some
"This declaration contradicts another exception \ "This declaration contradicts another exception \
@ -401,8 +395,8 @@ let build_exceptions_graph
let existing_edge = let existing_edge =
List.find_opt List.find_opt
(fun edge -> (fun edge ->
Ast.LabelName.compare edge.label_from label_from = 0 LabelName.compare edge.label_from label_from = 0
&& Ast.LabelName.compare edge.label_to label_to = 0) && LabelName.compare edge.label_to label_to = 0)
exception_edges exception_edges
in in
match existing_edge with match existing_edge with
@ -420,7 +414,7 @@ let build_exceptions_graph
in in
(* We've got the vertices and the edges, let's build the graph! *) (* We've got the vertices and the edges, let's build the graph! *)
let g = let g =
Ast.LabelMap.fold LabelMap.fold
(fun _label rule_set g -> ExceptionsDependencies.add_vertex g rule_set) (fun _label rule_set g -> ExceptionsDependencies.add_vertex g rule_set)
label_to_rule_sets ExceptionsDependencies.empty label_to_rule_sets ExceptionsDependencies.empty
in in
@ -429,11 +423,9 @@ let build_exceptions_graph
List.fold_left List.fold_left
(fun g edge -> (fun g edge ->
let rule_group_from = let rule_group_from =
Ast.LabelMap.find edge.label_from label_to_rule_sets LabelMap.find edge.label_from label_to_rule_sets
in
let rule_group_to =
Ast.LabelMap.find edge.label_to label_to_rule_sets
in in
let rule_group_to = LabelMap.find edge.label_to label_to_rule_sets in
let edge = let edge =
ExceptionsDependencies.E.create rule_group_from edge.edge_positions ExceptionsDependencies.E.create rule_group_from edge.edge_positions
rule_group_to rule_group_to
@ -453,11 +445,10 @@ let check_for_exception_cycle (g : ExceptionsDependencies.t) : unit =
let spans = let spans =
List.flatten List.flatten
(List.map (List.map
(fun (vs : Ast.RuleSet.t) -> (fun (vs : RuleSet.t) ->
let v = Ast.RuleSet.choose vs in let v = RuleSet.choose vs in
let var_str, var_info = let var_str, var_info =
( Format.asprintf "%a" Ast.RuleName.format_t v, Format.asprintf "%a" RuleName.format_t v, RuleName.get_info v
Ast.RuleName.get_info v )
in in
let succs = ExceptionsDependencies.succ_e g vs in let succs = ExceptionsDependencies.succ_e g vs in
let _, edge_pos, _ = let _, edge_pos, _ =

View File

@ -18,6 +18,7 @@
OCamlgraph} *) OCamlgraph} *)
open Utils open Utils
open Shared_ast
(** {1 Scope variables dependency graph} *) (** {1 Scope variables dependency graph} *)
@ -71,9 +72,9 @@ val build_scope_dependencies : Ast.scope -> ScopeDependencies.t
module EdgeExceptions : Graph.Sig.ORDERED_TYPE_DFT with type t = Pos.t list module EdgeExceptions : Graph.Sig.ORDERED_TYPE_DFT with type t = Pos.t list
module ExceptionsDependencies : module ExceptionsDependencies :
Graph.Sig.P with type V.t = Ast.RuleSet.t and type E.label = EdgeExceptions.t Graph.Sig.P with type V.t = RuleSet.t and type E.label = EdgeExceptions.t
val build_exceptions_graph : val build_exceptions_graph :
Ast.rule Ast.RuleMap.t -> Ast.ScopeDef.t -> ExceptionsDependencies.t Ast.rule RuleMap.t -> Ast.ScopeDef.t -> ExceptionsDependencies.t
val check_for_exception_cycle : ExceptionsDependencies.t -> unit val check_for_exception_cycle : ExceptionsDependencies.t -> unit

View File

@ -1,7 +1,7 @@
(library (library
(name desugared) (name desugared)
(public_name catala.desugared) (public_name catala.desugared)
(libraries utils dcalc scopelang ocamlgraph)) (libraries ocamlgraph utils shared_ast surface))
(documentation (documentation
(package catala) (package catala)

View File

@ -16,7 +16,7 @@
the License. *) the License. *)
open Utils open Utils
module SurfacePrint = Print module SurfacePrint = Surface.Print
open Shared_ast open Shared_ast
module Runtime = Runtime_ocaml.Runtime module Runtime = Runtime_ocaml.Runtime
@ -27,7 +27,7 @@ module Runtime = Runtime_ocaml.Runtime
(** {1 Translating expressions} *) (** {1 Translating expressions} *)
let translate_op_kind (k : Ast.op_kind) : op_kind = let translate_op_kind (k : Surface.Ast.op_kind) : op_kind =
match k with match k with
| KInt -> KInt | KInt -> KInt
| KDec -> KRat | KDec -> KRat
@ -35,7 +35,7 @@ let translate_op_kind (k : Ast.op_kind) : op_kind =
| KDate -> KDate | KDate -> KDate
| KDuration -> KDuration | KDuration -> KDuration
let translate_binop (op : Ast.binop) : binop = let translate_binop (op : Surface.Ast.binop) : binop =
match op with match op with
| And -> And | And -> And
| Or -> Or | Or -> Or
@ -52,7 +52,7 @@ let translate_binop (op : Ast.binop) : binop =
| Neq -> Neq | Neq -> Neq
| Concat -> Concat | Concat -> Concat
let translate_unop (op : Ast.unop) : unop = let translate_unop (op : Surface.Ast.unop) : unop =
match op with Not -> Not | Minus l -> Minus (translate_op_kind l) match op with Not -> Not | Minus l -> Minus (translate_op_kind l)
let disambiguate_constructor let disambiguate_constructor
@ -68,7 +68,7 @@ let disambiguate_constructor
in in
let possible_c_uids = let possible_c_uids =
try try
Desugared.Ast.IdentMap.find Name_resolution.IdentMap.find
(Marked.unmark constructor) (Marked.unmark constructor)
ctxt.constructor_idmap ctxt.constructor_idmap
with Not_found -> with Not_found ->
@ -111,16 +111,16 @@ let disambiguate_constructor
disambiguate the scope and subscopes variables than occur in the expression *) disambiguate the scope and subscopes variables than occur in the expression *)
let rec translate_expr let rec translate_expr
(scope : ScopeName.t) (scope : ScopeName.t)
(inside_definition_of : Desugared.Ast.ScopeDef.t Marked.pos option) (inside_definition_of : Ast.ScopeDef.t Marked.pos option)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(expr : Ast.expression Marked.pos) : Desugared.Ast.expr boxed = (expr : Surface.Ast.expression Marked.pos) : Ast.expr boxed =
let scope_ctxt = ScopeMap.find scope ctxt.scopes in let scope_ctxt = ScopeMap.find scope ctxt.scopes in
let rec_helper = translate_expr scope inside_definition_of ctxt in let rec_helper = translate_expr scope inside_definition_of ctxt in
let pos = Marked.get_mark expr in let pos = Marked.get_mark expr in
let emark = Untyped { pos } in let emark = Untyped { pos } in
match Marked.unmark expr with match Marked.unmark expr with
| Binop | Binop
( (Ast.And, _pos_op), ( (Surface.Ast.And, _pos_op),
( TestMatchCase (e1_sub, ((constructors, Some binding), pos_pattern)), ( TestMatchCase (e1_sub, ((constructors, Some binding), pos_pattern)),
_pos_e1 ), _pos_e1 ),
e2 ) -> e2 ) ->
@ -204,9 +204,9 @@ let rec translate_expr
| Ident x -> ( | Ident x -> (
(* first we check whether this is a local var, then we resort to scope-wide (* first we check whether this is a local var, then we resort to scope-wide
variables *) variables *)
match Desugared.Ast.IdentMap.find_opt x ctxt.local_var_idmap with match Name_resolution.IdentMap.find_opt x ctxt.local_var_idmap with
| None -> ( | None -> (
match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with match Name_resolution.IdentMap.find_opt x scope_ctxt.var_idmap with
| Some (ScopeVar uid) -> | Some (ScopeVar uid) ->
(* If the referenced variable has states, then here are the rules to (* If the referenced variable has states, then here are the rules to
desambiguate. In general, only the last state can be referenced. desambiguate. In general, only the last state can be referenced.
@ -258,7 +258,7 @@ let rec translate_expr
| Ident y when Name_resolution.is_subscope_uid scope ctxt y -> | Ident y when Name_resolution.is_subscope_uid scope ctxt y ->
(* In this case, y.x is a subscope variable *) (* In this case, y.x is a subscope variable *)
let subscope_uid, subscope_real_uid = let subscope_uid, subscope_real_uid =
match Desugared.Ast.IdentMap.find y scope_ctxt.var_idmap with match Name_resolution.IdentMap.find y scope_ctxt.var_idmap with
| SubScope (sub, sc) -> sub, sc | SubScope (sub, sc) -> sub, sc
| ScopeVar _ -> assert false | ScopeVar _ -> assert false
in in
@ -273,7 +273,7 @@ let rec translate_expr
(* In this case e.x is the struct field x access of expression e *) (* In this case e.x is the struct field x access of expression e *)
let e = translate_expr scope inside_definition_of ctxt e in let e = translate_expr scope inside_definition_of ctxt e in
let x_possible_structs = let x_possible_structs =
try Desugared.Ast.IdentMap.find (Marked.unmark x) ctxt.field_idmap try Name_resolution.IdentMap.find (Marked.unmark x) ctxt.field_idmap
with Not_found -> with Not_found ->
Errors.raise_spanned_error (Marked.get_mark x) Errors.raise_spanned_error (Marked.get_mark x)
"Unknown subscope or struct field name" "Unknown subscope or struct field name"
@ -314,7 +314,7 @@ let rec translate_expr
(fun acc (fld_id, e) -> (fun acc (fld_id, e) ->
let var = let var =
match match
Desugared.Ast.IdentMap.find_opt (Marked.unmark fld_id) Name_resolution.IdentMap.find_opt (Marked.unmark fld_id)
scope_def.var_idmap scope_def.var_idmap
with with
| Some (ScopeVar v) -> v | Some (ScopeVar v) -> v
@ -353,7 +353,7 @@ let rec translate_expr
| StructLit (s_name, fields) -> | StructLit (s_name, fields) ->
let s_uid = let s_uid =
match match
Desugared.Ast.IdentMap.find_opt (Marked.unmark s_name) ctxt.typedefs Name_resolution.IdentMap.find_opt (Marked.unmark s_name) ctxt.typedefs
with with
| Some (Name_resolution.TStruct s_uid) -> s_uid | Some (Name_resolution.TStruct s_uid) -> s_uid
| _ -> | _ ->
@ -367,7 +367,7 @@ let rec translate_expr
let f_uid = let f_uid =
try try
StructMap.find s_uid StructMap.find s_uid
(Desugared.Ast.IdentMap.find (Marked.unmark f_name) (Name_resolution.IdentMap.find (Marked.unmark f_name)
ctxt.field_idmap) ctxt.field_idmap)
with Not_found -> with Not_found ->
Errors.raise_spanned_error (Marked.get_mark f_name) Errors.raise_spanned_error (Marked.get_mark f_name)
@ -397,7 +397,7 @@ let rec translate_expr
Expr.estruct s_uid s_fields emark Expr.estruct s_uid s_fields emark
| EnumInject (enum, (constructor, pos_constructor), payload) -> ( | EnumInject (enum, (constructor, pos_constructor), payload) -> (
let possible_c_uids = let possible_c_uids =
try Desugared.Ast.IdentMap.find constructor ctxt.constructor_idmap try Name_resolution.IdentMap.find constructor ctxt.constructor_idmap
with Not_found -> with Not_found ->
Errors.raise_spanned_error pos_constructor Errors.raise_spanned_error pos_constructor
"The name of this constructor has not been defined before, maybe it \ "The name of this constructor has not been defined before, maybe it \
@ -481,7 +481,7 @@ let rec translate_expr
enum_uid cases emark enum_uid cases emark
| ArrayLit es -> Expr.earray (List.map rec_helper es) emark | ArrayLit es -> Expr.earray (List.map rec_helper es) emark
| CollectionOp | CollectionOp
( (((Ast.Filter | Ast.Map) as op'), _pos_op'), ( (((Surface.Ast.Filter | Surface.Ast.Map) as op'), _pos_op'),
param', param',
collection, collection,
predicate ) -> predicate ) ->
@ -498,13 +498,14 @@ let rec translate_expr
Expr.eapp Expr.eapp
(Expr.eop (Expr.eop
(match op' with (match op' with
| Ast.Map -> Binop Map | Surface.Ast.Map -> Binop Map
| Ast.Filter -> Binop Filter | Surface.Ast.Filter -> Binop Filter
| _ -> assert false (* should not happen *)) | _ -> assert false (* should not happen *))
emark) emark)
[f_pred; collection] emark [f_pred; collection] emark
| CollectionOp | CollectionOp
( ( Ast.Aggregate (Ast.AggregateArgExtremum (max_or_min, pred_typ, init)), ( ( Surface.Ast.Aggregate
(Surface.Ast.AggregateArgExtremum (max_or_min, pred_typ, init)),
pos_op' ), pos_op' ),
param', param',
collection, collection,
@ -516,11 +517,11 @@ let rec translate_expr
in in
let op_kind = let op_kind =
match pred_typ with match pred_typ with
| Ast.Integer -> KInt | Surface.Ast.Integer -> KInt
| Ast.Decimal -> KRat | Surface.Ast.Decimal -> KRat
| Ast.Money -> KMoney | Surface.Ast.Money -> KMoney
| Ast.Duration -> KDuration | Surface.Ast.Duration -> KDuration
| Ast.Date -> KDate | Surface.Ast.Date -> KDate
| _ -> | _ ->
Errors.raise_spanned_error pos Errors.raise_spanned_error pos
"It is impossible to compute the arg-%s of two values of type %a" "It is impossible to compute the arg-%s of two values of type %a"
@ -568,26 +569,28 @@ let rec translate_expr
let mark = Untyped { pos = Marked.get_mark op' } in let mark = Untyped { pos = Marked.get_mark op' } in
let init = let init =
match Marked.unmark op' with match Marked.unmark op' with
| Ast.Map | Ast.Filter | Ast.Aggregate (Ast.AggregateArgExtremum _) -> | Surface.Ast.Map | Surface.Ast.Filter
| Surface.Ast.Aggregate (Surface.Ast.AggregateArgExtremum _) ->
assert false (* should not happen *) assert false (* should not happen *)
| Ast.Exists -> Expr.elit (LBool false) mark | Surface.Ast.Exists -> Expr.elit (LBool false) mark
| Ast.Forall -> Expr.elit (LBool true) mark | Surface.Ast.Forall -> Expr.elit (LBool true) mark
| Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Integer) ->
Expr.elit (LInt (Runtime.integer_of_int 0)) mark Expr.elit (LInt (Runtime.integer_of_int 0)) mark
| Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Decimal) ->
Expr.elit (LRat (Runtime.decimal_of_string "0")) mark Expr.elit (LRat (Runtime.decimal_of_string "0")) mark
| Ast.Aggregate (Ast.AggregateSum Ast.Money) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Money) ->
Expr.elit Expr.elit
(LMoney (Runtime.money_of_cents_integer (Runtime.integer_of_int 0))) (LMoney (Runtime.money_of_cents_integer (Runtime.integer_of_int 0)))
mark mark
| Ast.Aggregate (Ast.AggregateSum Ast.Duration) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Duration) ->
Expr.elit (LDuration (Runtime.duration_of_numbers 0 0 0)) mark Expr.elit (LDuration (Runtime.duration_of_numbers 0 0 0)) mark
| Ast.Aggregate (Ast.AggregateSum t) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum t) ->
Errors.raise_spanned_error pos Errors.raise_spanned_error pos
"It is impossible to sum two values of type %a together" "It is impossible to sum two values of type %a together"
SurfacePrint.format_primitive_typ t SurfacePrint.format_primitive_typ t
| Ast.Aggregate (Ast.AggregateExtremum (_, _, init)) -> rec_helper init | Surface.Ast.Aggregate (Surface.Ast.AggregateExtremum (_, _, init)) ->
| Ast.Aggregate Ast.AggregateCount -> rec_helper init
| Surface.Ast.Aggregate Surface.Ast.AggregateCount ->
Expr.elit (LInt (Runtime.integer_of_int 0)) mark Expr.elit (LInt (Runtime.integer_of_int 0)) mark
in in
let acc_var = Var.make "acc" in let acc_var = Var.make "acc" in
@ -613,25 +616,30 @@ let rec translate_expr
pos pos
in in
match Marked.unmark op' with match Marked.unmark op' with
| Ast.Map | Ast.Filter | Ast.Aggregate (Ast.AggregateArgExtremum _) -> | Surface.Ast.Map | Surface.Ast.Filter
| Surface.Ast.Aggregate (Surface.Ast.AggregateArgExtremum _) ->
assert false (* should not happen *) assert false (* should not happen *)
| Ast.Exists -> make_body Or | Surface.Ast.Exists -> make_body Or
| Ast.Forall -> make_body And | Surface.Ast.Forall -> make_body And
| Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> make_body (Add KInt) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Integer) ->
| Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> make_body (Add KRat) make_body (Add KInt)
| Ast.Aggregate (Ast.AggregateSum Ast.Money) -> make_body (Add KMoney) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Decimal) ->
| Ast.Aggregate (Ast.AggregateSum Ast.Duration) -> make_body (Add KRat)
| Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Money) ->
make_body (Add KMoney)
| Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Duration) ->
make_body (Add KDuration) make_body (Add KDuration)
| Ast.Aggregate (Ast.AggregateSum _) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateSum _) ->
assert false (* should not happen *) assert false (* should not happen *)
| Ast.Aggregate (Ast.AggregateExtremum (max_or_min, t, _)) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateExtremum (max_or_min, t, _))
->
let op_kind, typ = let op_kind, typ =
match t with match t with
| Ast.Integer -> KInt, (TLit TInt, pos) | Surface.Ast.Integer -> KInt, (TLit TInt, pos)
| Ast.Decimal -> KRat, (TLit TRat, pos) | Surface.Ast.Decimal -> KRat, (TLit TRat, pos)
| Ast.Money -> KMoney, (TLit TMoney, pos) | Surface.Ast.Money -> KMoney, (TLit TMoney, pos)
| Ast.Duration -> KDuration, (TLit TDuration, pos) | Surface.Ast.Duration -> KDuration, (TLit TDuration, pos)
| Ast.Date -> KDate, (TLit TDate, pos) | Surface.Ast.Date -> KDate, (TLit TDate, pos)
| _ -> | _ ->
Errors.raise_spanned_error pos Errors.raise_spanned_error pos
"It is impossible to compute the %s of two values of type %a" "It is impossible to compute the %s of two values of type %a"
@ -640,7 +648,7 @@ let rec translate_expr
in in
let cmp_op = if max_or_min then Gt op_kind else Lt op_kind in let cmp_op = if max_or_min then Gt op_kind else Lt op_kind in
make_extr_body cmp_op typ make_extr_body cmp_op typ
| Ast.Aggregate Ast.AggregateCount -> | Surface.Ast.Aggregate Surface.Ast.AggregateCount ->
let predicate = let predicate =
translate_expr scope inside_definition_of ctxt predicate translate_expr scope inside_definition_of ctxt predicate
in in
@ -670,26 +678,31 @@ let rec translate_expr
emark emark
in in
match Marked.unmark op' with match Marked.unmark op' with
| Ast.Map | Ast.Filter | Ast.Aggregate (Ast.AggregateArgExtremum _) -> | Surface.Ast.Map | Surface.Ast.Filter
| Surface.Ast.Aggregate (Surface.Ast.AggregateArgExtremum _) ->
assert false (* should not happen *) assert false (* should not happen *)
| Ast.Exists -> make_f TBool | Surface.Ast.Exists -> make_f TBool
| Ast.Forall -> make_f TBool | Surface.Ast.Forall -> make_f TBool
| Ast.Aggregate (Ast.AggregateSum Ast.Integer) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Integer)
| Ast.Aggregate (Ast.AggregateExtremum (_, Ast.Integer, _)) -> | Surface.Ast.Aggregate
(Surface.Ast.AggregateExtremum (_, Surface.Ast.Integer, _)) ->
make_f TInt make_f TInt
| Ast.Aggregate (Ast.AggregateSum Ast.Decimal) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Decimal)
| Ast.Aggregate (Ast.AggregateExtremum (_, Ast.Decimal, _)) -> | Surface.Ast.Aggregate
(Surface.Ast.AggregateExtremum (_, Surface.Ast.Decimal, _)) ->
make_f TRat make_f TRat
| Ast.Aggregate (Ast.AggregateSum Ast.Money) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Money)
| Ast.Aggregate (Ast.AggregateExtremum (_, Ast.Money, _)) -> | Surface.Ast.Aggregate
(Surface.Ast.AggregateExtremum (_, Surface.Ast.Money, _)) ->
make_f TMoney make_f TMoney
| Ast.Aggregate (Ast.AggregateSum Ast.Duration) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum Surface.Ast.Duration)
| Ast.Aggregate (Ast.AggregateExtremum (_, Ast.Duration, _)) -> | Surface.Ast.Aggregate
(Surface.Ast.AggregateExtremum (_, Surface.Ast.Duration, _)) ->
make_f TDuration make_f TDuration
| Ast.Aggregate (Ast.AggregateSum _) | Surface.Ast.Aggregate (Surface.Ast.AggregateSum _)
| Ast.Aggregate (Ast.AggregateExtremum _) -> | Surface.Ast.Aggregate (Surface.Ast.AggregateExtremum _) ->
assert false (* should not happen *) assert false (* should not happen *)
| Ast.Aggregate Ast.AggregateCount -> make_f TInt | Surface.Ast.Aggregate Surface.Ast.AggregateCount -> make_f TInt
in in
Expr.eapp (Expr.eop (Ternop Fold) emark) [f; init; collection] emark Expr.eapp (Expr.eop (Ternop Fold) emark) [f; init; collection] emark
| MemCollection (member, collection) -> | MemCollection (member, collection) ->
@ -727,10 +740,10 @@ let rec translate_expr
and disambiguate_match_and_build_expression and disambiguate_match_and_build_expression
(scope : ScopeName.t) (scope : ScopeName.t)
(inside_definition_of : Desugared.Ast.ScopeDef.t Marked.pos option) (inside_definition_of : Ast.ScopeDef.t Marked.pos option)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(cases : Ast.match_case Marked.pos list) : (cases : Surface.Ast.match_case Marked.pos list) :
Desugared.Ast.expr boxed EnumConstructorMap.t * EnumName.t = Ast.expr boxed EnumConstructorMap.t * EnumName.t =
let create_var = function let create_var = function
| None -> ctxt, Var.make "_" | None -> ctxt, Var.make "_"
| Some param -> | Some param ->
@ -752,11 +765,13 @@ and disambiguate_match_and_build_expression
in in
let bind_match_cases (cases_d, e_uid, curr_index) (case, case_pos) = let bind_match_cases (cases_d, e_uid, curr_index) (case, case_pos) =
match case with match case with
| Ast.MatchCase case -> | Surface.Ast.MatchCase case ->
let constructor, binding = Marked.unmark case.Ast.match_case_pattern in let constructor, binding =
Marked.unmark case.Surface.Ast.match_case_pattern
in
let e_uid', c_uid = let e_uid', c_uid =
disambiguate_constructor ctxt constructor disambiguate_constructor ctxt constructor
(Marked.get_mark case.Ast.match_case_pattern) (Marked.get_mark case.Surface.Ast.match_case_pattern)
in in
let e_uid = let e_uid =
match e_uid with match e_uid with
@ -765,7 +780,7 @@ and disambiguate_match_and_build_expression
if e_uid = e_uid' then e_uid if e_uid = e_uid' then e_uid
else else
Errors.raise_spanned_error Errors.raise_spanned_error
(Marked.get_mark case.Ast.match_case_pattern) (Marked.get_mark case.Surface.Ast.match_case_pattern)
"This case matches a constructor of enumeration %a but previous \ "This case matches a constructor of enumeration %a but previous \
case were matching constructors of enumeration %a" case were matching constructors of enumeration %a"
EnumName.format_t e_uid EnumName.format_t e_uid' EnumName.format_t e_uid EnumName.format_t e_uid'
@ -779,12 +794,13 @@ and disambiguate_match_and_build_expression
c_uid); c_uid);
let ctxt, param_var = create_var (Option.map Marked.unmark binding) in let ctxt, param_var = create_var (Option.map Marked.unmark binding) in
let case_body = let case_body =
translate_expr scope inside_definition_of ctxt case.Ast.match_case_expr translate_expr scope inside_definition_of ctxt
case.Surface.Ast.match_case_expr
in in
let e_binder = Expr.bind [| param_var |] case_body in let e_binder = Expr.bind [| param_var |] case_body in
let case_expr = bind_case_body c_uid e_uid ctxt case_body e_binder in let case_expr = bind_case_body c_uid e_uid ctxt case_body e_binder in
EnumConstructorMap.add c_uid case_expr cases_d, Some e_uid, curr_index + 1 EnumConstructorMap.add c_uid case_expr cases_d, Some e_uid, curr_index + 1
| Ast.WildCard match_case_expr -> ( | Surface.Ast.WildCard match_case_expr -> (
let nb_cases = List.length cases in let nb_cases = List.length cases in
let raise_wildcard_not_last_case_err () = let raise_wildcard_not_last_case_err () =
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -858,9 +874,9 @@ and disambiguate_match_and_build_expression
this precondition has to be appended to the justifications of each this precondition has to be appended to the justifications of each
definition in the subscope use. This is what this function does. *) definition in the subscope use. This is what this function does. *)
let merge_conditions let merge_conditions
(precond : Desugared.Ast.expr boxed option) (precond : Ast.expr boxed option)
(cond : Desugared.Ast.expr boxed option) (cond : Ast.expr boxed option)
(default_pos : Pos.t) : Desugared.Ast.expr boxed = (default_pos : Pos.t) : Ast.expr boxed =
match precond, cond with match precond, cond with
| Some precond, Some cond -> | Some precond, Some cond ->
let op_term = Expr.eop (Binop And) (Marked.get_mark cond) in let op_term = Expr.eop (Binop And) (Marked.get_mark cond) in
@ -870,18 +886,18 @@ let merge_conditions
| None, None -> Expr.elit (LBool true) (Untyped { pos = default_pos }) | None, None -> Expr.elit (LBool true) (Untyped { pos = default_pos })
(** Translates a surface definition into condition into a desugared {!type: (** Translates a surface definition into condition into a desugared {!type:
Desugared.Ast.rule} *) Ast.rule} *)
let process_default let process_default
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(scope : ScopeName.t) (scope : ScopeName.t)
(def_key : Desugared.Ast.ScopeDef.t Marked.pos) (def_key : Ast.ScopeDef.t Marked.pos)
(rule_id : Desugared.Ast.RuleName.t) (rule_id : RuleName.t)
(param_uid : Desugared.Ast.expr Var.t Marked.pos option) (param_uid : Ast.expr Var.t Marked.pos option)
(precond : Desugared.Ast.expr boxed option) (precond : Ast.expr boxed option)
(exception_situation : Desugared.Ast.exception_situation) (exception_situation : Ast.exception_situation)
(label_situation : Desugared.Ast.label_situation) (label_situation : Ast.label_situation)
(just : Ast.expression Marked.pos option) (just : Surface.Ast.expression Marked.pos option)
(cons : Ast.expression Marked.pos) : Desugared.Ast.rule = (cons : Surface.Ast.expression Marked.pos) : Ast.rule =
let just = let just =
match just with match just with
| Some just -> Some (translate_expr scope (Some def_key) ctxt just) | Some just -> Some (translate_expr scope (Some def_key) ctxt just)
@ -913,14 +929,12 @@ let process_default
(** Wrapper around {!val: process_default} that performs some name (** Wrapper around {!val: process_default} that performs some name
disambiguation *) disambiguation *)
let process_def let process_def
(precond : Desugared.Ast.expr boxed option) (precond : Ast.expr boxed option)
(scope_uid : ScopeName.t) (scope_uid : ScopeName.t)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(def : Ast.definition) : Desugared.Ast.program = (def : Surface.Ast.definition) : Ast.program =
let scope : Desugared.Ast.scope = let scope : Ast.scope = ScopeMap.find scope_uid prgm.program_scopes in
ScopeMap.find scope_uid prgm.program_scopes
in
let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in
let def_key = let def_key =
Name_resolution.get_def_key Name_resolution.get_def_key
@ -929,7 +943,7 @@ let process_def
(Marked.get_mark def.definition_name) (Marked.get_mark def.definition_name)
in in
let scope_def_ctxt = let scope_def_ctxt =
Desugared.Ast.ScopeDefMap.find def_key scope_ctxt.scope_defs_contexts Ast.ScopeDefMap.find def_key scope_ctxt.scope_defs_contexts
in in
(* We add to the name resolution context the name of the parameter variable *) (* We add to the name resolution context the name of the parameter variable *)
let param_uid, new_ctxt = let param_uid, new_ctxt =
@ -942,19 +956,19 @@ let process_def
Some (Marked.same_mark_as param_var param), ctxt Some (Marked.same_mark_as param_var param), ctxt
in in
let scope_updated = let scope_updated =
let scope_def = Desugared.Ast.ScopeDefMap.find def_key scope.scope_defs in let scope_def = Ast.ScopeDefMap.find def_key scope.scope_defs in
let rule_name = def.definition_id in let rule_name = def.definition_id in
let label_situation = let label_situation =
match def.definition_label with match def.definition_label with
| Some (label_str, label_pos) -> | Some (label_str, label_pos) ->
Desugared.Ast.ExplicitlyLabeled Ast.ExplicitlyLabeled
( Desugared.Ast.IdentMap.find label_str scope_def_ctxt.label_idmap, ( Name_resolution.IdentMap.find label_str scope_def_ctxt.label_idmap,
label_pos ) label_pos )
| None -> Desugared.Ast.Unlabeled | None -> Ast.Unlabeled
in in
let exception_situation = let exception_situation =
match def.Ast.definition_exception_to with match def.Surface.Ast.definition_exception_to with
| NotAnException -> Desugared.Ast.BaseCase | NotAnException -> Ast.BaseCase
| UnlabeledException -> ( | UnlabeledException -> (
match scope_def_ctxt.default_exception_rulename with match scope_def_ctxt.default_exception_rulename with
| None | Some (Name_resolution.Ambiguous _) -> | None | Some (Name_resolution.Ambiguous _) ->
@ -966,7 +980,7 @@ let process_def
| ExceptionToLabel label_str -> ( | ExceptionToLabel label_str -> (
try try
let label_id = let label_id =
Desugared.Ast.IdentMap.find (Marked.unmark label_str) Name_resolution.IdentMap.find (Marked.unmark label_str)
scope_def_ctxt.label_idmap scope_def_ctxt.label_idmap
in in
ExceptionToLabel (label_id, Marked.get_mark label_str) ExceptionToLabel (label_id, Marked.get_mark label_str)
@ -974,13 +988,13 @@ let process_def
Errors.raise_spanned_error Errors.raise_spanned_error
(Marked.get_mark label_str) (Marked.get_mark label_str)
"Unknown label for the scope variable %a: \"%s\"" "Unknown label for the scope variable %a: \"%s\""
Desugared.Ast.ScopeDef.format_t def_key (Marked.unmark label_str)) Ast.ScopeDef.format_t def_key (Marked.unmark label_str))
in in
let scope_def = let scope_def =
{ {
scope_def with scope_def with
scope_def_rules = scope_def_rules =
Desugared.Ast.RuleMap.add rule_name RuleMap.add rule_name
(process_default new_ctxt scope_uid (process_default new_ctxt scope_uid
(def_key, Marked.get_mark def.definition_name) (def_key, Marked.get_mark def.definition_name)
rule_name param_uid precond exception_situation label_situation rule_name param_uid precond exception_situation label_situation
@ -990,8 +1004,7 @@ let process_def
in in
{ {
scope with scope with
scope_defs = scope_defs = Ast.ScopeDefMap.add def_key scope_def scope.scope_defs;
Desugared.Ast.ScopeDefMap.add def_key scope_def scope.scope_defs;
} }
in in
{ {
@ -1001,33 +1014,32 @@ let process_def
(** Translates a {!type: Surface.Ast.rule} from the surface language *) (** Translates a {!type: Surface.Ast.rule} from the surface language *)
let process_rule let process_rule
(precond : Desugared.Ast.expr boxed option) (precond : Ast.expr boxed option)
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(rule : Ast.rule) : Desugared.Ast.program = (rule : Surface.Ast.rule) : Ast.program =
let def = Ast.rule_to_def rule in let def = Surface.Ast.rule_to_def rule in
process_def precond scope ctxt prgm def process_def precond scope ctxt prgm def
(** Translates assertions *) (** Translates assertions *)
let process_assert let process_assert
(precond : Desugared.Ast.expr boxed option) (precond : Ast.expr boxed option)
(scope_uid : ScopeName.t) (scope_uid : ScopeName.t)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(ass : Ast.assertion) : Desugared.Ast.program = (ass : Surface.Ast.assertion) : Ast.program =
let scope : Desugared.Ast.scope = let scope : Ast.scope = ScopeMap.find scope_uid prgm.program_scopes in
ScopeMap.find scope_uid prgm.program_scopes
in
let ass = let ass =
translate_expr scope_uid None ctxt translate_expr scope_uid None ctxt
(match ass.Ast.assertion_condition with (match ass.Surface.Ast.assertion_condition with
| None -> ass.Ast.assertion_content | None -> ass.Surface.Ast.assertion_content
| Some cond -> | Some cond ->
( Ast.IfThenElse ( Surface.Ast.IfThenElse
( cond, ( cond,
ass.Ast.assertion_content, ass.Surface.Ast.assertion_content,
Marked.same_mark_as (Ast.Literal (Ast.LBool true)) cond ), Marked.same_mark_as (Surface.Ast.Literal (Surface.Ast.LBool true))
cond ),
Marked.get_mark cond )) Marked.get_mark cond ))
in in
let ass = let ass =
@ -1048,16 +1060,16 @@ let process_assert
(** Translates a surface definition, rule or assertion *) (** Translates a surface definition, rule or assertion *)
let process_scope_use_item let process_scope_use_item
(precond : Ast.expression Marked.pos option) (precond : Surface.Ast.expression Marked.pos option)
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(item : Ast.scope_use_item Marked.pos) : Desugared.Ast.program = (item : Surface.Ast.scope_use_item Marked.pos) : Ast.program =
let precond = Option.map (translate_expr scope None ctxt) precond in let precond = Option.map (translate_expr scope None ctxt) precond in
match Marked.unmark item with match Marked.unmark item with
| Ast.Rule rule -> process_rule precond scope ctxt prgm rule | Surface.Ast.Rule rule -> process_rule precond scope ctxt prgm rule
| Ast.Definition def -> process_def precond scope ctxt prgm def | Surface.Ast.Definition def -> process_def precond scope ctxt prgm def
| Ast.Assertion ass -> process_assert precond scope ctxt prgm ass | Surface.Ast.Assertion ass -> process_assert precond scope ctxt prgm ass
| _ -> prgm | _ -> prgm
(** {1 Translating top-level items} *) (** {1 Translating top-level items} *)
@ -1067,19 +1079,19 @@ let process_scope_use_item
let check_unlabeled_exception let check_unlabeled_exception
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(item : Ast.scope_use_item Marked.pos) : unit = (item : Surface.Ast.scope_use_item Marked.pos) : unit =
let scope_ctxt = ScopeMap.find scope ctxt.scopes in let scope_ctxt = ScopeMap.find scope ctxt.scopes in
match Marked.unmark item with match Marked.unmark item with
| Ast.Rule _ | Ast.Definition _ -> ( | Surface.Ast.Rule _ | Surface.Ast.Definition _ -> (
let def_key, exception_to = let def_key, exception_to =
match Marked.unmark item with match Marked.unmark item with
| Ast.Rule rule -> | Surface.Ast.Rule rule ->
( Name_resolution.get_def_key ( Name_resolution.get_def_key
(Marked.unmark rule.rule_name) (Marked.unmark rule.rule_name)
rule.rule_state scope ctxt rule.rule_state scope ctxt
(Marked.get_mark rule.rule_name), (Marked.get_mark rule.rule_name),
rule.rule_exception_to ) rule.rule_exception_to )
| Ast.Definition def -> | Surface.Ast.Definition def ->
( Name_resolution.get_def_key ( Name_resolution.get_def_key
(Marked.unmark def.definition_name) (Marked.unmark def.definition_name)
def.definition_state scope ctxt def.definition_state scope ctxt
@ -1089,13 +1101,13 @@ let check_unlabeled_exception
(* should not happen *) (* should not happen *)
in in
let scope_def_ctxt = let scope_def_ctxt =
Desugared.Ast.ScopeDefMap.find def_key scope_ctxt.scope_defs_contexts Ast.ScopeDefMap.find def_key scope_ctxt.scope_defs_contexts
in in
match exception_to with match exception_to with
| Ast.NotAnException | Ast.ExceptionToLabel _ -> () | Surface.Ast.NotAnException | Surface.Ast.ExceptionToLabel _ -> ()
(* If this is an unlabeled exception, we check that it has a unique default (* If this is an unlabeled exception, we check that it has a unique default
definition *) definition *)
| Ast.UnlabeledException -> ( | Surface.Ast.UnlabeledException -> (
match scope_def_ctxt.default_exception_rulename with match scope_def_ctxt.default_exception_rulename with
| None -> | None ->
Errors.raise_spanned_error (Marked.get_mark item) Errors.raise_spanned_error (Marked.get_mark item)
@ -1112,8 +1124,8 @@ let check_unlabeled_exception
(** Translates a surface scope use, which is a bunch of definitions *) (** Translates a surface scope use, which is a bunch of definitions *)
let process_scope_use let process_scope_use
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(use : Ast.scope_use) : Desugared.Ast.program = (use : Surface.Ast.scope_use) : Ast.program =
let scope_uid = Name_resolution.get_scope ctxt use.scope_use_name in let scope_uid = Name_resolution.get_scope ctxt use.scope_use_name in
(* Make sure the scope exists *) (* Make sure the scope exists *)
let prgm = let prgm =
@ -1128,24 +1140,24 @@ let process_scope_use
(process_scope_use_item precond scope_uid ctxt) (process_scope_use_item precond scope_uid ctxt)
prgm use.scope_use_items prgm use.scope_use_items
let attribute_to_io (attr : Ast.scope_decl_context_io) : Scopelang.Ast.io = let attribute_to_io (attr : Surface.Ast.scope_decl_context_io) : Ast.io =
{ {
Scopelang.Ast.io_output = attr.scope_decl_context_io_output; Ast.io_output = attr.scope_decl_context_io_output;
Scopelang.Ast.io_input = Ast.io_input =
Marked.map_under_mark Marked.map_under_mark
(fun io -> (fun io ->
match io with match io with
| Ast.Input -> Scopelang.Ast.OnlyInput | Surface.Ast.Input -> Ast.OnlyInput
| Ast.Internal -> Scopelang.Ast.NoInput | Surface.Ast.Internal -> Ast.NoInput
| Ast.Context -> Scopelang.Ast.Reentrant) | Surface.Ast.Context -> Ast.Reentrant)
attr.scope_decl_context_io_input; attr.scope_decl_context_io_input;
} }
let init_scope_defs let init_scope_defs
(ctxt : Name_resolution.context) (ctxt : Name_resolution.context)
(scope_idmap : (scope_idmap :
Name_resolution.scope_var_or_subscope Desugared.Ast.IdentMap.t) : Name_resolution.scope_var_or_subscope Name_resolution.IdentMap.t) :
Desugared.Ast.scope_def Desugared.Ast.ScopeDefMap.t = Ast.scope_def Ast.ScopeDefMap.t =
(* Initializing the definitions of all scopes and subscope vars, with no rules (* Initializing the definitions of all scopes and subscope vars, with no rules
yet inside *) yet inside *)
let add_def _ v scope_def_map = let add_def _ v scope_def_map =
@ -1154,27 +1166,26 @@ let init_scope_defs
let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in
match v_sig.var_sig_states_list with match v_sig.var_sig_states_list with
| [] -> | [] ->
let def_key = Desugared.Ast.ScopeDef.Var (v, None) in let def_key = Ast.ScopeDef.Var (v, None) in
Desugared.Ast.ScopeDefMap.add def_key Ast.ScopeDefMap.add def_key
{ {
Desugared.Ast.scope_def_rules = Desugared.Ast.RuleMap.empty; Ast.scope_def_rules = RuleMap.empty;
Desugared.Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_typ = v_sig.var_sig_typ;
Desugared.Ast.scope_def_is_condition = v_sig.var_sig_is_condition; Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
Desugared.Ast.scope_def_io = attribute_to_io v_sig.var_sig_io; Ast.scope_def_io = attribute_to_io v_sig.var_sig_io;
} }
scope_def_map scope_def_map
| states -> | states ->
let scope_def, _ = let scope_def, _ =
List.fold_left List.fold_left
(fun (acc, i) state -> (fun (acc, i) state ->
let def_key = Desugared.Ast.ScopeDef.Var (v, Some state) in let def_key = Ast.ScopeDef.Var (v, Some state) in
let def = let def =
{ {
Desugared.Ast.scope_def_rules = Desugared.Ast.RuleMap.empty; Ast.scope_def_rules = RuleMap.empty;
Desugared.Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_typ = v_sig.var_sig_typ;
Desugared.Ast.scope_def_is_condition = Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
v_sig.var_sig_is_condition; Ast.scope_def_io =
Desugared.Ast.scope_def_io =
(* The first state should have the input I/O of the original (* The first state should have the input I/O of the original
variable, and the last state should have the output I/O variable, and the last state should have the output I/O
of the original variable. All intermediate states shall of the original variable. All intermediate states shall
@ -1183,8 +1194,7 @@ let init_scope_defs
let io_input = let io_input =
if i = 0 then original_io.io_input if i = 0 then original_io.io_input
else else
( Scopelang.Ast.NoInput, Ast.NoInput, Marked.get_mark (StateName.get_info state)
Marked.get_mark (StateName.get_info state) )
in in
let io_output = let io_output =
if i = List.length states - 1 then original_io.io_output if i = List.length states - 1 then original_io.io_output
@ -1193,7 +1203,7 @@ let init_scope_defs
{ io_input; io_output }); { io_input; io_output });
} }
in in
Desugared.Ast.ScopeDefMap.add def_key def acc, i + 1) Ast.ScopeDefMap.add def_key def acc, i + 1)
(scope_def_map, 0) states (scope_def_map, 0) states
in in
scope_def) scope_def)
@ -1201,7 +1211,7 @@ let init_scope_defs
let sub_scope_def = let sub_scope_def =
ScopeMap.find subscope_uid ctxt.Name_resolution.scopes ScopeMap.find subscope_uid ctxt.Name_resolution.scopes
in in
Desugared.Ast.IdentMap.fold Name_resolution.IdentMap.fold
(fun _ v scope_def_map -> (fun _ v scope_def_map ->
match v with match v with
| Name_resolution.SubScope _ -> scope_def_map | Name_resolution.SubScope _ -> scope_def_map
@ -1210,45 +1220,43 @@ let init_scope_defs
? *) ? *)
let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in
let def_key = let def_key =
Desugared.Ast.ScopeDef.SubScopeVar Ast.ScopeDef.SubScopeVar
(v0, v, Marked.get_mark (ScopeVar.get_info v)) (v0, v, Marked.get_mark (ScopeVar.get_info v))
in in
Desugared.Ast.ScopeDefMap.add def_key Ast.ScopeDefMap.add def_key
{ {
Desugared.Ast.scope_def_rules = Desugared.Ast.RuleMap.empty; Ast.scope_def_rules = RuleMap.empty;
Desugared.Ast.scope_def_typ = v_sig.var_sig_typ; Ast.scope_def_typ = v_sig.var_sig_typ;
Desugared.Ast.scope_def_is_condition = Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
v_sig.var_sig_is_condition; Ast.scope_def_io = attribute_to_io v_sig.var_sig_io;
Desugared.Ast.scope_def_io = attribute_to_io v_sig.var_sig_io;
} }
scope_def_map) scope_def_map)
sub_scope_def.Name_resolution.var_idmap scope_def_map sub_scope_def.Name_resolution.var_idmap scope_def_map
in in
Desugared.Ast.IdentMap.fold add_def scope_idmap Name_resolution.IdentMap.fold add_def scope_idmap Ast.ScopeDefMap.empty
Desugared.Ast.ScopeDefMap.empty
(** Main function of this module *) (** Main function of this module *)
let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : let translate_program
Desugared.Ast.program = (ctxt : Name_resolution.context)
(prgm : Surface.Ast.program) : Ast.program =
let empty_prgm = let empty_prgm =
let program_scopes = let program_scopes =
ScopeMap.mapi ScopeMap.mapi
(fun s_uid s_context -> (fun s_uid s_context ->
let scope_vars = let scope_vars =
Desugared.Ast.IdentMap.fold Name_resolution.IdentMap.fold
(fun _ v acc -> (fun _ v acc ->
match v with match v with
| Name_resolution.SubScope _ -> acc | Name_resolution.SubScope _ -> acc
| Name_resolution.ScopeVar v -> ( | Name_resolution.ScopeVar v -> (
let v_sig = ScopeVarMap.find v ctxt.var_typs in let v_sig = ScopeVarMap.find v ctxt.var_typs in
match v_sig.var_sig_states_list with match v_sig.var_sig_states_list with
| [] -> ScopeVarMap.add v Desugared.Ast.WholeVar acc | [] -> ScopeVarMap.add v Ast.WholeVar acc
| states -> | states -> ScopeVarMap.add v (Ast.States states) acc))
ScopeVarMap.add v (Desugared.Ast.States states) acc))
s_context.Name_resolution.var_idmap ScopeVarMap.empty s_context.Name_resolution.var_idmap ScopeVarMap.empty
in in
let scope_sub_scopes = let scope_sub_scopes =
Desugared.Ast.IdentMap.fold Name_resolution.IdentMap.fold
(fun _ v acc -> (fun _ v acc ->
match v with match v with
| Name_resolution.ScopeVar _ -> acc | Name_resolution.ScopeVar _ -> acc
@ -1257,7 +1265,7 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) :
s_context.Name_resolution.var_idmap SubScopeMap.empty s_context.Name_resolution.var_idmap SubScopeMap.empty
in in
{ {
Desugared.Ast.scope_vars; Ast.scope_vars;
scope_sub_scopes; scope_sub_scopes;
scope_defs = init_scope_defs ctxt s_context.var_idmap; scope_defs = init_scope_defs ctxt s_context.var_idmap;
scope_assertions = []; scope_assertions = [];
@ -1267,12 +1275,12 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) :
ctxt.Name_resolution.scopes ctxt.Name_resolution.scopes
in in
{ {
Desugared.Ast.program_ctx = Ast.program_ctx =
{ {
ctx_structs = ctxt.Name_resolution.structs; ctx_structs = ctxt.Name_resolution.structs;
ctx_enums = ctxt.Name_resolution.enums; ctx_enums = ctxt.Name_resolution.enums;
ctx_scopes = ctx_scopes =
Desugared.Ast.IdentMap.fold Name_resolution.IdentMap.fold
(fun _ def acc -> (fun _ def acc ->
match def with match def with
| Name_resolution.TScope (scope, scope_out_struct) -> | Name_resolution.TScope (scope, scope_out_struct) ->
@ -1280,12 +1288,12 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) :
| _ -> acc) | _ -> acc)
ctxt.Name_resolution.typedefs ScopeMap.empty; ctxt.Name_resolution.typedefs ScopeMap.empty;
}; };
Desugared.Ast.program_scopes; Ast.program_scopes;
} }
in in
let rec processer_structure let rec processer_structure
(prgm : Desugared.Ast.program) (prgm : Ast.program)
(item : Ast.law_structure) : Desugared.Ast.program = (item : Surface.Ast.law_structure) : Ast.program =
match item with match item with
| LawHeading (_, children) -> | LawHeading (_, children) ->
List.fold_left List.fold_left
@ -1295,7 +1303,7 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) :
List.fold_left List.fold_left
(fun prgm item -> (fun prgm item ->
match Marked.unmark item with match Marked.unmark item with
| Ast.ScopeUse use -> process_scope_use ctxt prgm use | Surface.Ast.ScopeUse use -> process_scope_use ctxt prgm use
| _ -> prgm) | _ -> prgm)
prgm block prgm block
| LawInclude _ | LawText _ -> prgm | LawInclude _ | LawText _ -> prgm

View File

@ -20,6 +20,6 @@
- Removes syntactic sugars - Removes syntactic sugars
- Separate code from legislation *) - Separate code from legislation *)
val desugar_program : val translate_program :
Name_resolution.context -> Ast.program -> Desugared.Ast.program Name_resolution.context -> Surface.Ast.program -> Ast.program
(** Main function of this module *) (** Main function of this module *)

View File

@ -25,13 +25,15 @@ open Shared_ast
type ident = string type ident = string
module IdentMap : Map.S with type key = String.t = Map.Make (String)
type unique_rulename = type unique_rulename =
| Ambiguous of Pos.t list | Ambiguous of Pos.t list
| Unique of Desugared.Ast.RuleName.t Marked.pos | Unique of RuleName.t Marked.pos
type scope_def_context = { type scope_def_context = {
default_exception_rulename : unique_rulename option; default_exception_rulename : unique_rulename option;
label_idmap : Desugared.Ast.LabelName.t Desugared.Ast.IdentMap.t; label_idmap : LabelName.t IdentMap.t;
} }
type scope_var_or_subscope = type scope_var_or_subscope =
@ -39,9 +41,9 @@ type scope_var_or_subscope =
| SubScope of SubScopeName.t * ScopeName.t | SubScope of SubScopeName.t * ScopeName.t
type scope_context = { type scope_context = {
var_idmap : scope_var_or_subscope Desugared.Ast.IdentMap.t; var_idmap : scope_var_or_subscope IdentMap.t;
(** All variables, including scope variables and subscopes *) (** All variables, including scope variables and subscopes *)
scope_defs_contexts : scope_def_context Desugared.Ast.ScopeDefMap.t; scope_defs_contexts : scope_def_context Ast.ScopeDefMap.t;
(** What is the default rule to refer to for unnamed exceptions, if any *) (** What is the default rule to refer to for unnamed exceptions, if any *)
sub_scopes : ScopeSet.t; sub_scopes : ScopeSet.t;
(** Other scopes referred to by this scope. Used for dependency analysis *) (** Other scopes referred to by this scope. Used for dependency analysis *)
@ -57,8 +59,8 @@ type enum_context = typ EnumConstructorMap.t
type var_sig = { type var_sig = {
var_sig_typ : typ; var_sig_typ : typ;
var_sig_is_condition : bool; var_sig_is_condition : bool;
var_sig_io : Ast.scope_decl_context_io; var_sig_io : Surface.Ast.scope_decl_context_io;
var_sig_states_idmap : StateName.t Desugared.Ast.IdentMap.t; var_sig_states_idmap : StateName.t IdentMap.t;
var_sig_states_list : StateName.t list; var_sig_states_list : StateName.t list;
} }
@ -71,15 +73,15 @@ type typedef =
(** Implicitly defined output struct *) (** Implicitly defined output struct *)
type context = { type context = {
local_var_idmap : Desugared.Ast.expr Var.t Desugared.Ast.IdentMap.t; local_var_idmap : Ast.expr Var.t IdentMap.t;
(** Inside a definition, local variables can be introduced by functions (** Inside a definition, local variables can be introduced by functions
arguments or pattern matching *) arguments or pattern matching *)
typedefs : typedef Desugared.Ast.IdentMap.t; typedefs : typedef IdentMap.t;
(** Gathers the names of the scopes, structs and enums *) (** Gathers the names of the scopes, structs and enums *)
field_idmap : StructFieldName.t StructMap.t Desugared.Ast.IdentMap.t; field_idmap : StructFieldName.t StructMap.t IdentMap.t;
(** The names of the struct fields. Names of fields can be shared between (** The names of the struct fields. Names of fields can be shared between
different structs *) different structs *)
constructor_idmap : EnumConstructor.t EnumMap.t Desugared.Ast.IdentMap.t; constructor_idmap : EnumConstructor.t EnumMap.t IdentMap.t;
(** The names of the enum constructors. Constructor names can be shared (** The names of the enum constructors. Constructor names can be shared
between different enums *) between different enums *)
scopes : scope_context ScopeMap.t; (** For each scope, its context *) scopes : scope_context ScopeMap.t; (** For each scope, its context *)
@ -112,7 +114,8 @@ let get_var_typ (ctxt : context) (uid : ScopeVar.t) : typ =
let is_var_cond (ctxt : context) (uid : ScopeVar.t) : bool = let is_var_cond (ctxt : context) (uid : ScopeVar.t) : bool =
(ScopeVarMap.find uid ctxt.var_typs).var_sig_is_condition (ScopeVarMap.find uid ctxt.var_typs).var_sig_is_condition
let get_var_io (ctxt : context) (uid : ScopeVar.t) : Ast.scope_decl_context_io = let get_var_io (ctxt : context) (uid : ScopeVar.t) :
Surface.Ast.scope_decl_context_io =
(ScopeVarMap.find uid ctxt.var_typs).var_sig_io (ScopeVarMap.find uid ctxt.var_typs).var_sig_io
(** Get the variable uid inside the scope given in argument *) (** Get the variable uid inside the scope given in argument *)
@ -121,7 +124,7 @@ let get_var_uid
(ctxt : context) (ctxt : context)
((x, pos) : ident Marked.pos) : ScopeVar.t = ((x, pos) : ident Marked.pos) : ScopeVar.t =
let scope = ScopeMap.find scope_uid ctxt.scopes in let scope = ScopeMap.find scope_uid ctxt.scopes in
match Desugared.Ast.IdentMap.find_opt x scope.var_idmap with match IdentMap.find_opt x scope.var_idmap with
| Some (ScopeVar uid) -> uid | Some (ScopeVar uid) -> uid
| _ -> | _ ->
raise_unknown_identifier raise_unknown_identifier
@ -134,7 +137,7 @@ let get_subscope_uid
(ctxt : context) (ctxt : context)
((y, pos) : ident Marked.pos) : SubScopeName.t = ((y, pos) : ident Marked.pos) : SubScopeName.t =
let scope = ScopeMap.find scope_uid ctxt.scopes in let scope = ScopeMap.find scope_uid ctxt.scopes in
match Desugared.Ast.IdentMap.find_opt y scope.var_idmap with match IdentMap.find_opt y scope.var_idmap with
| Some (SubScope (sub_uid, _sub_id)) -> sub_uid | Some (SubScope (sub_uid, _sub_id)) -> sub_uid
| _ -> raise_unknown_identifier "for a subscope of this scope" (y, pos) | _ -> raise_unknown_identifier "for a subscope of this scope" (y, pos)
@ -143,7 +146,7 @@ let get_subscope_uid
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : ident) : let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : ident) :
bool = bool =
let scope = ScopeMap.find scope_uid ctxt.scopes in let scope = ScopeMap.find scope_uid ctxt.scopes in
match Desugared.Ast.IdentMap.find_opt y scope.var_idmap with match IdentMap.find_opt y scope.var_idmap with
| Some (SubScope _) -> true | Some (SubScope _) -> true
| _ -> false | _ -> false
@ -151,31 +154,31 @@ let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : ident) :
let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) : let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) :
bool = bool =
let scope = ScopeMap.find scope_uid ctxt.scopes in let scope = ScopeMap.find scope_uid ctxt.scopes in
Desugared.Ast.IdentMap.exists IdentMap.exists
(fun _ -> function (fun _ -> function
| ScopeVar var_uid -> ScopeVar.equal uid var_uid | ScopeVar var_uid -> ScopeVar.equal uid var_uid
| _ -> false) | _ -> false)
scope.var_idmap scope.var_idmap
(** Retrieves the type of a scope definition from the context *) (** Retrieves the type of a scope definition from the context *)
let get_def_typ (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : typ = let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ =
match def with match def with
| Desugared.Ast.ScopeDef.SubScopeVar (_, x, _) | Ast.ScopeDef.SubScopeVar (_, x, _)
(* we don't need to look at the subscope prefix because [x] is already the uid (* we don't need to look at the subscope prefix because [x] is already the uid
referring back to the original subscope *) referring back to the original subscope *)
| Desugared.Ast.ScopeDef.Var (x, _) -> | Ast.ScopeDef.Var (x, _) ->
get_var_typ ctxt x get_var_typ ctxt x
let is_def_cond (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : bool = let is_def_cond (ctxt : context) (def : Ast.ScopeDef.t) : bool =
match def with match def with
| Desugared.Ast.ScopeDef.SubScopeVar (_, x, _) | Ast.ScopeDef.SubScopeVar (_, x, _)
(* we don't need to look at the subscope prefix because [x] is already the uid (* we don't need to look at the subscope prefix because [x] is already the uid
referring back to the original subscope *) referring back to the original subscope *)
| Desugared.Ast.ScopeDef.Var (x, _) -> | Ast.ScopeDef.Var (x, _) ->
is_var_cond ctxt x is_var_cond ctxt x
let get_enum ctxt id = let get_enum ctxt id =
match Desugared.Ast.IdentMap.find (Marked.unmark id) ctxt.typedefs with match IdentMap.find (Marked.unmark id) ctxt.typedefs with
| TEnum id -> id | TEnum id -> id
| TStruct sid -> | TStruct sid ->
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -196,7 +199,7 @@ let get_enum ctxt id =
(Marked.unmark id) (Marked.unmark id)
let get_struct ctxt id = let get_struct ctxt id =
match Desugared.Ast.IdentMap.find (Marked.unmark id) ctxt.typedefs with match IdentMap.find (Marked.unmark id) ctxt.typedefs with
| TStruct id | TScope (_, { out_struct_name = id; _ }) -> id | TStruct id | TScope (_, { out_struct_name = id; _ }) -> id
| TEnum eid -> | TEnum eid ->
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -210,7 +213,7 @@ let get_struct ctxt id =
(Marked.unmark id) (Marked.unmark id)
let get_scope ctxt id = let get_scope ctxt id =
match Desugared.Ast.IdentMap.find (Marked.unmark id) ctxt.typedefs with match IdentMap.find (Marked.unmark id) ctxt.typedefs with
| TScope (id, _) -> id | TScope (id, _) -> id
| TEnum eid -> | TEnum eid ->
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -236,11 +239,11 @@ let get_scope ctxt id =
let process_subscope_decl let process_subscope_decl
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : context) (ctxt : context)
(decl : Ast.scope_decl_context_scope) : context = (decl : Surface.Ast.scope_decl_context_scope) : context =
let name, name_pos = decl.scope_decl_context_scope_name in let name, name_pos = decl.scope_decl_context_scope_name in
let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in
let scope_ctxt = ScopeMap.find scope ctxt.scopes in let scope_ctxt = ScopeMap.find scope ctxt.scopes in
match Desugared.Ast.IdentMap.find_opt subscope scope_ctxt.var_idmap with match IdentMap.find_opt subscope scope_ctxt.var_idmap with
| Some use -> | Some use ->
let info = let info =
match use with match use with
@ -261,7 +264,7 @@ let process_subscope_decl
{ {
scope_ctxt with scope_ctxt with
var_idmap = var_idmap =
Desugared.Ast.IdentMap.add name IdentMap.add name
(SubScope (sub_scope_uid, original_subscope_uid)) (SubScope (sub_scope_uid, original_subscope_uid))
scope_ctxt.var_idmap; scope_ctxt.var_idmap;
sub_scopes = ScopeSet.add original_subscope_uid scope_ctxt.sub_scopes; sub_scopes = ScopeSet.add original_subscope_uid scope_ctxt.sub_scopes;
@ -269,34 +272,35 @@ let process_subscope_decl
in in
{ ctxt with scopes = ScopeMap.add scope scope_ctxt ctxt.scopes } { ctxt with scopes = ScopeMap.add scope scope_ctxt ctxt.scopes }
let is_type_cond ((typ, _) : Ast.typ) = let is_type_cond ((typ, _) : Surface.Ast.typ) =
match typ with match typ with
| Ast.Base Ast.Condition | Surface.Ast.Base Surface.Ast.Condition
| Ast.Func { arg_typ = _; return_typ = Ast.Condition, _ } -> | Surface.Ast.Func { arg_typ = _; return_typ = Surface.Ast.Condition, _ } ->
true true
| _ -> false | _ -> false
(** Process a basic type (all types except function types) *) (** Process a basic type (all types except function types) *)
let rec process_base_typ let rec process_base_typ
(ctxt : context) (ctxt : context)
((typ, typ_pos) : Ast.base_typ Marked.pos) : typ = ((typ, typ_pos) : Surface.Ast.base_typ Marked.pos) : typ =
match typ with match typ with
| Ast.Condition -> TLit TBool, typ_pos | Surface.Ast.Condition -> TLit TBool, typ_pos
| Ast.Data (Ast.Collection t) -> | Surface.Ast.Data (Surface.Ast.Collection t) ->
( TArray ( TArray
(process_base_typ ctxt (Ast.Data (Marked.unmark t), Marked.get_mark t)), (process_base_typ ctxt
(Surface.Ast.Data (Marked.unmark t), Marked.get_mark t)),
typ_pos ) typ_pos )
| Ast.Data (Ast.Primitive prim) -> ( | Surface.Ast.Data (Surface.Ast.Primitive prim) -> (
match prim with match prim with
| Ast.Integer -> TLit TInt, typ_pos | Surface.Ast.Integer -> TLit TInt, typ_pos
| Ast.Decimal -> TLit TRat, typ_pos | Surface.Ast.Decimal -> TLit TRat, typ_pos
| Ast.Money -> TLit TMoney, typ_pos | Surface.Ast.Money -> TLit TMoney, typ_pos
| Ast.Duration -> TLit TDuration, typ_pos | Surface.Ast.Duration -> TLit TDuration, typ_pos
| Ast.Date -> TLit TDate, typ_pos | Surface.Ast.Date -> TLit TDate, typ_pos
| Ast.Boolean -> TLit TBool, typ_pos | Surface.Ast.Boolean -> TLit TBool, typ_pos
| Ast.Text -> raise_unsupported_feature "text type" typ_pos | Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos
| Ast.Named ident -> ( | Surface.Ast.Named ident -> (
match Desugared.Ast.IdentMap.find_opt ident ctxt.typedefs with match IdentMap.find_opt ident ctxt.typedefs with
| Some (TStruct s_uid) -> TStruct s_uid, typ_pos | Some (TStruct s_uid) -> TStruct s_uid, typ_pos
| Some (TEnum e_uid) -> TEnum e_uid, typ_pos | Some (TEnum e_uid) -> TEnum e_uid, typ_pos
| Some (TScope (_, scope_str)) -> | Some (TScope (_, scope_str)) ->
@ -308,10 +312,11 @@ let rec process_base_typ
ident)) ident))
(** Process a type (function or not) *) (** Process a type (function or not) *)
let process_type (ctxt : context) ((naked_typ, typ_pos) : Ast.typ) : typ = let process_type (ctxt : context) ((naked_typ, typ_pos) : Surface.Ast.typ) : typ
=
match naked_typ with match naked_typ with
| Ast.Base base_typ -> process_base_typ ctxt (base_typ, typ_pos) | Surface.Ast.Base base_typ -> process_base_typ ctxt (base_typ, typ_pos)
| Ast.Func { arg_typ; return_typ } -> | Surface.Ast.Func { arg_typ; return_typ } ->
( TArrow (process_base_typ ctxt arg_typ, process_base_typ ctxt return_typ), ( TArrow (process_base_typ ctxt arg_typ, process_base_typ ctxt return_typ),
typ_pos ) typ_pos )
@ -319,13 +324,13 @@ let process_type (ctxt : context) ((naked_typ, typ_pos) : Ast.typ) : typ =
let process_data_decl let process_data_decl
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : context) (ctxt : context)
(decl : Ast.scope_decl_context_data) : context = (decl : Surface.Ast.scope_decl_context_data) : context =
(* First check the type of the context data *) (* First check the type of the context data *)
let data_typ = process_type ctxt decl.scope_decl_context_item_typ in let data_typ = process_type ctxt decl.scope_decl_context_item_typ in
let is_cond = is_type_cond decl.scope_decl_context_item_typ in let is_cond = is_type_cond decl.scope_decl_context_item_typ in
let name, pos = decl.scope_decl_context_item_name in let name, pos = decl.scope_decl_context_item_name in
let scope_ctxt = ScopeMap.find scope ctxt.scopes in let scope_ctxt = ScopeMap.find scope ctxt.scopes in
match Desugared.Ast.IdentMap.find_opt name scope_ctxt.var_idmap with match IdentMap.find_opt name scope_ctxt.var_idmap with
| Some use -> | Some use ->
let info = let info =
match use with match use with
@ -342,19 +347,16 @@ let process_data_decl
let scope_ctxt = let scope_ctxt =
{ {
scope_ctxt with scope_ctxt with
var_idmap = var_idmap = IdentMap.add name (ScopeVar uid) scope_ctxt.var_idmap;
Desugared.Ast.IdentMap.add name (ScopeVar uid) scope_ctxt.var_idmap;
} }
in in
let states_idmap, states_list = let states_idmap, states_list =
List.fold_right List.fold_right
(fun state_id (states_idmap, states_list) -> (fun state_id (states_idmap, states_list) ->
let state_uid = StateName.fresh state_id in let state_uid = StateName.fresh state_id in
( Desugared.Ast.IdentMap.add (Marked.unmark state_id) state_uid ( IdentMap.add (Marked.unmark state_id) state_uid states_idmap,
states_idmap,
state_uid :: states_list )) state_uid :: states_list ))
decl.scope_decl_context_item_states decl.scope_decl_context_item_states (IdentMap.empty, [])
(Desugared.Ast.IdentMap.empty, [])
in in
{ {
ctxt with ctxt with
@ -372,20 +374,20 @@ let process_data_decl
} }
(** Adds a binding to the context *) (** Adds a binding to the context *)
let add_def_local_var (ctxt : context) (name : ident) : let add_def_local_var (ctxt : context) (name : ident) : context * Ast.expr Var.t
context * Desugared.Ast.expr Var.t = =
let local_var_uid = Var.make name in let local_var_uid = Var.make name in
let ctxt = let ctxt =
{ {
ctxt with ctxt with
local_var_idmap = local_var_idmap = IdentMap.add name local_var_uid ctxt.local_var_idmap;
Desugared.Ast.IdentMap.add name local_var_uid ctxt.local_var_idmap;
} }
in in
ctxt, local_var_uid ctxt, local_var_uid
(** Process a struct declaration *) (** Process a struct declaration *)
let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = let process_struct_decl (ctxt : context) (sdecl : Surface.Ast.struct_decl) :
context =
let s_uid = get_struct ctxt sdecl.struct_decl_name in let s_uid = get_struct ctxt sdecl.struct_decl_name in
if sdecl.struct_decl_fields = [] then if sdecl.struct_decl_fields = [] then
Errors.raise_spanned_error Errors.raise_spanned_error
@ -395,13 +397,15 @@ let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context =
(Marked.unmark sdecl.struct_decl_name); (Marked.unmark sdecl.struct_decl_name);
List.fold_left List.fold_left
(fun ctxt (fdecl, _) -> (fun ctxt (fdecl, _) ->
let f_uid = StructFieldName.fresh fdecl.Ast.struct_decl_field_name in let f_uid =
StructFieldName.fresh fdecl.Surface.Ast.struct_decl_field_name
in
let ctxt = let ctxt =
{ {
ctxt with ctxt with
field_idmap = field_idmap =
Desugared.Ast.IdentMap.update IdentMap.update
(Marked.unmark fdecl.Ast.struct_decl_field_name) (Marked.unmark fdecl.Surface.Ast.struct_decl_field_name)
(fun uids -> (fun uids ->
match uids with match uids with
| None -> Some (StructMap.singleton s_uid f_uid) | None -> Some (StructMap.singleton s_uid f_uid)
@ -418,18 +422,19 @@ let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context =
| None -> | None ->
Some Some
(StructFieldMap.singleton f_uid (StructFieldMap.singleton f_uid
(process_type ctxt fdecl.Ast.struct_decl_field_typ)) (process_type ctxt fdecl.Surface.Ast.struct_decl_field_typ))
| Some fields -> | Some fields ->
Some Some
(StructFieldMap.add f_uid (StructFieldMap.add f_uid
(process_type ctxt fdecl.Ast.struct_decl_field_typ) (process_type ctxt fdecl.Surface.Ast.struct_decl_field_typ)
fields)) fields))
ctxt.structs; ctxt.structs;
}) })
ctxt sdecl.struct_decl_fields ctxt sdecl.struct_decl_fields
(** Process an enum declaration *) (** Process an enum declaration *)
let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = let process_enum_decl (ctxt : context) (edecl : Surface.Ast.enum_decl) : context
=
let e_uid = get_enum ctxt edecl.enum_decl_name in let e_uid = get_enum ctxt edecl.enum_decl_name in
if List.length edecl.enum_decl_cases = 0 then if List.length edecl.enum_decl_cases = 0 then
Errors.raise_spanned_error Errors.raise_spanned_error
@ -439,13 +444,13 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context =
(Marked.unmark edecl.enum_decl_name); (Marked.unmark edecl.enum_decl_name);
List.fold_left List.fold_left
(fun ctxt (cdecl, cdecl_pos) -> (fun ctxt (cdecl, cdecl_pos) ->
let c_uid = EnumConstructor.fresh cdecl.Ast.enum_decl_case_name in let c_uid = EnumConstructor.fresh cdecl.Surface.Ast.enum_decl_case_name in
let ctxt = let ctxt =
{ {
ctxt with ctxt with
constructor_idmap = constructor_idmap =
Desugared.Ast.IdentMap.update IdentMap.update
(Marked.unmark cdecl.Ast.enum_decl_case_name) (Marked.unmark cdecl.Surface.Ast.enum_decl_case_name)
(fun uids -> (fun uids ->
match uids with match uids with
| None -> Some (EnumMap.singleton e_uid c_uid) | None -> Some (EnumMap.singleton e_uid c_uid)
@ -459,7 +464,7 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context =
EnumMap.update e_uid EnumMap.update e_uid
(fun cases -> (fun cases ->
let typ = let typ =
match cdecl.Ast.enum_decl_case_typ with match cdecl.Surface.Ast.enum_decl_case_typ with
| None -> TLit TUnit, cdecl_pos | None -> TLit TUnit, cdecl_pos
| Some typ -> process_type ctxt typ | Some typ -> process_type ctxt typ
in in
@ -474,13 +479,15 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context =
let process_item_decl let process_item_decl
(scope : ScopeName.t) (scope : ScopeName.t)
(ctxt : context) (ctxt : context)
(decl : Ast.scope_decl_context_item) : context = (decl : Surface.Ast.scope_decl_context_item) : context =
match decl with match decl with
| Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl | Surface.Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl
| Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl | Surface.Ast.ContextScope sub_decl ->
process_subscope_decl scope ctxt sub_decl
(** Process a scope declaration *) (** Process a scope declaration *)
let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) :
context =
let scope_uid = get_scope ctxt decl.scope_decl_name in let scope_uid = get_scope ctxt decl.scope_decl_name in
let ctxt = let ctxt =
List.fold_left List.fold_left
@ -492,7 +499,7 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context =
List.fold_right List.fold_right
(fun item acc -> (fun item acc ->
match Marked.unmark item with match Marked.unmark item with
| Ast.ContextData | Surface.Ast.ContextData
({ ({
scope_decl_context_item_attribute = scope_decl_context_item_attribute =
{ scope_decl_context_io_output = true, _; _ }; { scope_decl_context_io_output = true, _; _ };
@ -500,8 +507,10 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context =
} as data) -> } as data) ->
Marked.mark (Marked.get_mark item) Marked.mark (Marked.get_mark item)
{ {
Ast.struct_decl_field_name = data.scope_decl_context_item_name; Surface.Ast.struct_decl_field_name =
Ast.struct_decl_field_typ = data.scope_decl_context_item_typ; data.scope_decl_context_item_name;
Surface.Ast.struct_decl_field_typ =
data.scope_decl_context_item_typ;
} }
:: acc :: acc
| _ -> acc) | _ -> acc)
@ -528,22 +537,21 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context =
let out_struct_fields = let out_struct_fields =
let sco = ScopeMap.find scope_uid ctxt.scopes in let sco = ScopeMap.find scope_uid ctxt.scopes in
let str = get_struct ctxt decl.scope_decl_name in let str = get_struct ctxt decl.scope_decl_name in
Desugared.Ast.IdentMap.fold IdentMap.fold
(fun id var svmap -> (fun id var svmap ->
match var with match var with
| SubScope _ -> svmap | SubScope _ -> svmap
| ScopeVar v -> ( | ScopeVar v -> (
try try
let field = let field =
StructMap.find str StructMap.find str (IdentMap.find id ctxt.field_idmap)
(Desugared.Ast.IdentMap.find id ctxt.field_idmap)
in in
ScopeVarMap.add v field svmap ScopeVarMap.add v field svmap
with Not_found -> svmap)) with Not_found -> svmap))
sco.var_idmap ScopeVarMap.empty sco.var_idmap ScopeVarMap.empty
in in
let typedefs = let typedefs =
Desugared.Ast.IdentMap.update IdentMap.update
(Marked.unmark decl.scope_decl_name) (Marked.unmark decl.scope_decl_name)
(function (function
| Some (TScope (scope, { out_struct_name; _ })) -> | Some (TScope (scope, { out_struct_name; _ })) ->
@ -559,8 +567,8 @@ let typedef_info = function
| TScope (s, _) -> ScopeName.get_info s | TScope (s, _) -> ScopeName.get_info s
(** Process the names of all declaration items *) (** Process the names of all declaration items *)
let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) : let process_name_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
context = : context =
let raise_already_defined_error (use : Uid.MarkedString.info) name pos msg = let raise_already_defined_error (use : Uid.MarkedString.info) name pos msg =
Errors.raise_multispanned_error Errors.raise_multispanned_error
[ [
@ -578,13 +586,13 @@ let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) :
Option.iter Option.iter
(fun use -> (fun use ->
raise_already_defined_error (typedef_info use) name pos "scope") raise_already_defined_error (typedef_info use) name pos "scope")
(Desugared.Ast.IdentMap.find_opt name ctxt.typedefs); (IdentMap.find_opt name ctxt.typedefs);
let scope_uid = ScopeName.fresh (name, pos) in let scope_uid = ScopeName.fresh (name, pos) in
let out_struct_uid = StructName.fresh (name, pos) in let out_struct_uid = StructName.fresh (name, pos) in
{ {
ctxt with ctxt with
typedefs = typedefs =
Desugared.Ast.IdentMap.add name IdentMap.add name
(TScope (TScope
( scope_uid, ( scope_uid,
{ {
@ -595,8 +603,8 @@ let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) :
scopes = scopes =
ScopeMap.add scope_uid ScopeMap.add scope_uid
{ {
var_idmap = Desugared.Ast.IdentMap.empty; var_idmap = IdentMap.empty;
scope_defs_contexts = Desugared.Ast.ScopeDefMap.empty; scope_defs_contexts = Ast.ScopeDefMap.empty;
sub_scopes = ScopeSet.empty; sub_scopes = ScopeSet.empty;
} }
ctxt.scopes; ctxt.scopes;
@ -606,12 +614,12 @@ let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) :
Option.iter Option.iter
(fun use -> (fun use ->
raise_already_defined_error (typedef_info use) name pos "struct") raise_already_defined_error (typedef_info use) name pos "struct")
(Desugared.Ast.IdentMap.find_opt name ctxt.typedefs); (IdentMap.find_opt name ctxt.typedefs);
let s_uid = StructName.fresh sdecl.struct_decl_name in let s_uid = StructName.fresh sdecl.struct_decl_name in
{ {
ctxt with ctxt with
typedefs = typedefs =
Desugared.Ast.IdentMap.add IdentMap.add
(Marked.unmark sdecl.struct_decl_name) (Marked.unmark sdecl.struct_decl_name)
(TStruct s_uid) ctxt.typedefs; (TStruct s_uid) ctxt.typedefs;
} }
@ -620,20 +628,20 @@ let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) :
Option.iter Option.iter
(fun use -> (fun use ->
raise_already_defined_error (typedef_info use) name pos "enum") raise_already_defined_error (typedef_info use) name pos "enum")
(Desugared.Ast.IdentMap.find_opt name ctxt.typedefs); (IdentMap.find_opt name ctxt.typedefs);
let e_uid = EnumName.fresh edecl.enum_decl_name in let e_uid = EnumName.fresh edecl.enum_decl_name in
{ {
ctxt with ctxt with
typedefs = typedefs =
Desugared.Ast.IdentMap.add IdentMap.add
(Marked.unmark edecl.enum_decl_name) (Marked.unmark edecl.enum_decl_name)
(TEnum e_uid) ctxt.typedefs; (TEnum e_uid) ctxt.typedefs;
} }
| ScopeUse _ -> ctxt | ScopeUse _ -> ctxt
(** Process a code item that is a declaration *) (** Process a code item that is a declaration *)
let process_decl_item (ctxt : context) (item : Ast.code_item Marked.pos) : let process_decl_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
context = : context =
match Marked.unmark item with match Marked.unmark item with
| ScopeDecl decl -> process_scope_decl ctxt decl | ScopeDecl decl -> process_scope_decl ctxt decl
| StructDecl sdecl -> process_struct_decl ctxt sdecl | StructDecl sdecl -> process_struct_decl ctxt sdecl
@ -643,44 +651,46 @@ let process_decl_item (ctxt : context) (item : Ast.code_item Marked.pos) :
(** Process a code block *) (** Process a code block *)
let process_code_block let process_code_block
(ctxt : context) (ctxt : context)
(block : Ast.code_block) (block : Surface.Ast.code_block)
(process_item : context -> Ast.code_item Marked.pos -> context) : context = (process_item : context -> Surface.Ast.code_item Marked.pos -> context) :
context =
List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block
(** Process a law structure, only considering the code blocks *) (** Process a law structure, only considering the code blocks *)
let rec process_law_structure let rec process_law_structure
(ctxt : context) (ctxt : context)
(s : Ast.law_structure) (s : Surface.Ast.law_structure)
(process_item : context -> Ast.code_item Marked.pos -> context) : context = (process_item : context -> Surface.Ast.code_item Marked.pos -> context) :
context =
match s with match s with
| Ast.LawHeading (_, children) -> | Surface.Ast.LawHeading (_, children) ->
List.fold_left List.fold_left
(fun ctxt child -> process_law_structure ctxt child process_item) (fun ctxt child -> process_law_structure ctxt child process_item)
ctxt children ctxt children
| Ast.CodeBlock (block, _, _) -> process_code_block ctxt block process_item | Surface.Ast.CodeBlock (block, _, _) ->
| Ast.LawInclude _ | Ast.LawText _ -> ctxt process_code_block ctxt block process_item
| Surface.Ast.LawInclude _ | Surface.Ast.LawText _ -> ctxt
(** {1 Scope uses pass} *) (** {1 Scope uses pass} *)
let get_def_key let get_def_key
(name : Ast.qident) (name : Surface.Ast.qident)
(state : Ast.ident Marked.pos option) (state : Surface.Ast.ident Marked.pos option)
(scope_uid : ScopeName.t) (scope_uid : ScopeName.t)
(ctxt : context) (ctxt : context)
(pos : Pos.t) : Desugared.Ast.ScopeDef.t = (pos : Pos.t) : Ast.ScopeDef.t =
let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in
match name with match name with
| [x] -> | [x] ->
let x_uid = get_var_uid scope_uid ctxt x in let x_uid = get_var_uid scope_uid ctxt x in
let var_sig = ScopeVarMap.find x_uid ctxt.var_typs in let var_sig = ScopeVarMap.find x_uid ctxt.var_typs in
Desugared.Ast.ScopeDef.Var Ast.ScopeDef.Var
( x_uid, ( x_uid,
match state with match state with
| Some state -> ( | Some state -> (
try try
Some Some
(Desugared.Ast.IdentMap.find (Marked.unmark state) (IdentMap.find (Marked.unmark state) var_sig.var_sig_states_idmap)
var_sig.var_sig_states_idmap)
with Not_found -> with Not_found ->
Errors.raise_multispanned_error Errors.raise_multispanned_error
[ [
@ -691,8 +701,7 @@ let get_def_key
"This identifier is not a state declared for variable %a." "This identifier is not a state declared for variable %a."
ScopeVar.format_t x_uid) ScopeVar.format_t x_uid)
| None -> | None ->
if not (Desugared.Ast.IdentMap.is_empty var_sig.var_sig_states_idmap) if not (IdentMap.is_empty var_sig.var_sig_states_idmap) then
then
Errors.raise_multispanned_error Errors.raise_multispanned_error
[ [
None, Marked.get_mark x; None, Marked.get_mark x;
@ -705,9 +714,7 @@ let get_def_key
else None ) else None )
| [y; x] -> | [y; x] ->
let (subscope_uid, subscope_real_uid) : SubScopeName.t * ScopeName.t = let (subscope_uid, subscope_real_uid) : SubScopeName.t * ScopeName.t =
match match IdentMap.find_opt (Marked.unmark y) scope_ctxt.var_idmap with
Desugared.Ast.IdentMap.find_opt (Marked.unmark y) scope_ctxt.var_idmap
with
| Some (SubScope (v, u)) -> v, u | Some (SubScope (v, u)) -> v, u
| Some _ -> | Some _ ->
Errors.raise_spanned_error pos Errors.raise_spanned_error pos
@ -718,7 +725,7 @@ let get_def_key
Print.lit_style (Marked.unmark y) Print.lit_style (Marked.unmark y)
in in
let x_uid = get_var_uid subscope_real_uid ctxt x in let x_uid = get_var_uid subscope_real_uid ctxt x in
Desugared.Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid, pos) Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid, pos)
| _ -> | _ ->
Errors.raise_spanned_error pos Errors.raise_spanned_error pos
"This line is defining a quantity that is neither a scope variable nor a \ "This line is defining a quantity that is neither a scope variable nor a \
@ -728,7 +735,7 @@ let get_def_key
let process_definition let process_definition
(ctxt : context) (ctxt : context)
(s_name : ScopeName.t) (s_name : ScopeName.t)
(d : Ast.definition) : context = (d : Surface.Ast.definition) : context =
(* We update the definition context inside the big context *) (* We update the definition context inside the big context *)
{ {
ctxt with ctxt with
@ -748,7 +755,7 @@ let process_definition
{ {
s_ctxt with s_ctxt with
scope_defs_contexts = scope_defs_contexts =
Desugared.Ast.ScopeDefMap.update def_key Ast.ScopeDefMap.update def_key
(fun def_key_ctx -> (fun def_key_ctx ->
let def_key_ctx : scope_def_context = let def_key_ctx : scope_def_context =
Option.fold Option.fold
@ -757,7 +764,7 @@ let process_definition
(* Here, this is the first time we encounter a (* Here, this is the first time we encounter a
definition for this definition key *) definition for this definition key *)
default_exception_rulename = None; default_exception_rulename = None;
label_idmap = Desugared.Ast.IdentMap.empty; label_idmap = IdentMap.empty;
} }
~some:(fun x -> x) ~some:(fun x -> x)
def_key_ctx def_key_ctx
@ -765,16 +772,15 @@ let process_definition
(* First, we update the def key context with information (* First, we update the def key context with information
about the definition's label*) about the definition's label*)
let def_key_ctx = let def_key_ctx =
match d.Ast.definition_label with match d.Surface.Ast.definition_label with
| None -> def_key_ctx | None -> def_key_ctx
| Some label -> | Some label ->
let new_label_idmap = let new_label_idmap =
Desugared.Ast.IdentMap.update (Marked.unmark label) IdentMap.update (Marked.unmark label)
(fun existing_label -> (fun existing_label ->
match existing_label with match existing_label with
| Some existing_label -> Some existing_label | Some existing_label -> Some existing_label
| None -> | None -> Some (LabelName.fresh label))
Some (Desugared.Ast.LabelName.fresh label))
def_key_ctx.label_idmap def_key_ctx.label_idmap
in in
{ def_key_ctx with label_idmap = new_label_idmap } { def_key_ctx with label_idmap = new_label_idmap }
@ -782,7 +788,7 @@ let process_definition
(* And second, we update the map of default rulenames for (* And second, we update the map of default rulenames for
unlabeled exceptions *) unlabeled exceptions *)
let def_key_ctx = let def_key_ctx =
match d.Ast.definition_exception_to with match d.Surface.Ast.definition_exception_to with
(* If this definition is an exception, it cannot be a (* If this definition is an exception, it cannot be a
default definition *) default definition *)
| UnlabeledException | ExceptionToLabel _ -> def_key_ctx | UnlabeledException | ExceptionToLabel _ -> def_key_ctx
@ -806,7 +812,7 @@ let process_definition
} }
(* No definition has been set yet for this key *) (* No definition has been set yet for this key *)
| None -> ( | None -> (
match d.Ast.definition_label with match d.Surface.Ast.definition_label with
(* This default definition has a label. This is not (* This default definition has a label. This is not
allowed for unlabeled exceptions *) allowed for unlabeled exceptions *)
| Some _ -> | Some _ ->
@ -838,31 +844,34 @@ let process_definition
let process_scope_use_item let process_scope_use_item
(s_name : ScopeName.t) (s_name : ScopeName.t)
(ctxt : context) (ctxt : context)
(sitem : Ast.scope_use_item Marked.pos) : context = (sitem : Surface.Ast.scope_use_item Marked.pos) : context =
match Marked.unmark sitem with match Marked.unmark sitem with
| Rule r -> process_definition ctxt s_name (Ast.rule_to_def r) | Rule r -> process_definition ctxt s_name (Surface.Ast.rule_to_def r)
| Definition d -> process_definition ctxt s_name d | Definition d -> process_definition ctxt s_name d
| _ -> ctxt | _ -> ctxt
let process_scope_use (ctxt : context) (suse : Ast.scope_use) : context = let process_scope_use (ctxt : context) (suse : Surface.Ast.scope_use) : context
=
let s_name = let s_name =
match match
Desugared.Ast.IdentMap.find_opt IdentMap.find_opt
(Marked.unmark suse.Ast.scope_use_name) (Marked.unmark suse.Surface.Ast.scope_use_name)
ctxt.typedefs ctxt.typedefs
with with
| Some (TScope (sn, _)) -> sn | Some (TScope (sn, _)) -> sn
| _ -> | _ ->
Errors.raise_spanned_error Errors.raise_spanned_error
(Marked.get_mark suse.Ast.scope_use_name) (Marked.get_mark suse.Surface.Ast.scope_use_name)
"\"%a\": this scope has not been declared anywhere, is it a typo?" "\"%a\": this scope has not been declared anywhere, is it a typo?"
(Utils.Cli.format_with_style [ANSITerminal.yellow]) (Utils.Cli.format_with_style [ANSITerminal.yellow])
(Marked.unmark suse.Ast.scope_use_name) (Marked.unmark suse.Surface.Ast.scope_use_name)
in in
List.fold_left (process_scope_use_item s_name) ctxt suse.Ast.scope_use_items List.fold_left
(process_scope_use_item s_name)
ctxt suse.Surface.Ast.scope_use_items
let process_use_item (ctxt : context) (item : Ast.code_item Marked.pos) : let process_use_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
context = : context =
match Marked.unmark item with match Marked.unmark item with
| ScopeDecl _ | StructDecl _ | EnumDecl _ -> ctxt | ScopeDecl _ | StructDecl _ | EnumDecl _ -> ctxt
| ScopeUse suse -> process_scope_use ctxt suse | ScopeUse suse -> process_scope_use ctxt suse
@ -870,17 +879,17 @@ let process_use_item (ctxt : context) (item : Ast.code_item Marked.pos) :
(** {1 API} *) (** {1 API} *)
(** Derive the context from metadata, in one pass over the declarations *) (** Derive the context from metadata, in one pass over the declarations *)
let form_context (prgm : Ast.program) : context = let form_context (prgm : Surface.Ast.program) : context =
let empty_ctxt = let empty_ctxt =
{ {
local_var_idmap = Desugared.Ast.IdentMap.empty; local_var_idmap = IdentMap.empty;
typedefs = Desugared.Ast.IdentMap.empty; typedefs = IdentMap.empty;
scopes = ScopeMap.empty; scopes = ScopeMap.empty;
var_typs = ScopeVarMap.empty; var_typs = ScopeVarMap.empty;
structs = StructMap.empty; structs = StructMap.empty;
field_idmap = Desugared.Ast.IdentMap.empty; field_idmap = IdentMap.empty;
enums = EnumMap.empty; enums = EnumMap.empty;
constructor_idmap = Desugared.Ast.IdentMap.empty; constructor_idmap = IdentMap.empty;
} }
in in
let ctxt = let ctxt =

View File

@ -25,13 +25,15 @@ open Shared_ast
type ident = string type ident = string
module IdentMap : Map.S with type key = String.t
type unique_rulename = type unique_rulename =
| Ambiguous of Pos.t list | Ambiguous of Pos.t list
| Unique of Desugared.Ast.RuleName.t Marked.pos | Unique of RuleName.t Marked.pos
type scope_def_context = { type scope_def_context = {
default_exception_rulename : unique_rulename option; default_exception_rulename : unique_rulename option;
label_idmap : Desugared.Ast.LabelName.t Desugared.Ast.IdentMap.t; label_idmap : LabelName.t IdentMap.t;
} }
type scope_var_or_subscope = type scope_var_or_subscope =
@ -39,9 +41,9 @@ type scope_var_or_subscope =
| SubScope of SubScopeName.t * ScopeName.t | SubScope of SubScopeName.t * ScopeName.t
type scope_context = { type scope_context = {
var_idmap : scope_var_or_subscope Desugared.Ast.IdentMap.t; var_idmap : scope_var_or_subscope IdentMap.t;
(** All variables, including scope variables and subscopes *) (** All variables, including scope variables and subscopes *)
scope_defs_contexts : scope_def_context Desugared.Ast.ScopeDefMap.t; scope_defs_contexts : scope_def_context Ast.ScopeDefMap.t;
(** What is the default rule to refer to for unnamed exceptions, if any *) (** What is the default rule to refer to for unnamed exceptions, if any *)
sub_scopes : ScopeSet.t; sub_scopes : ScopeSet.t;
(** Other scopes referred to by this scope. Used for dependency analysis *) (** Other scopes referred to by this scope. Used for dependency analysis *)
@ -57,8 +59,8 @@ type enum_context = typ EnumConstructorMap.t
type var_sig = { type var_sig = {
var_sig_typ : typ; var_sig_typ : typ;
var_sig_is_condition : bool; var_sig_is_condition : bool;
var_sig_io : Ast.scope_decl_context_io; var_sig_io : Surface.Ast.scope_decl_context_io;
var_sig_states_idmap : StateName.t Desugared.Ast.IdentMap.t; var_sig_states_idmap : StateName.t IdentMap.t;
var_sig_states_list : StateName.t list; var_sig_states_list : StateName.t list;
} }
@ -71,15 +73,15 @@ type typedef =
(** Implicitly defined output struct *) (** Implicitly defined output struct *)
type context = { type context = {
local_var_idmap : Desugared.Ast.expr Var.t Desugared.Ast.IdentMap.t; local_var_idmap : Ast.expr Var.t IdentMap.t;
(** Inside a definition, local variables can be introduced by functions (** Inside a definition, local variables can be introduced by functions
arguments or pattern matching *) arguments or pattern matching *)
typedefs : typedef Desugared.Ast.IdentMap.t; typedefs : typedef IdentMap.t;
(** Gathers the names of the scopes, structs and enums *) (** Gathers the names of the scopes, structs and enums *)
field_idmap : StructFieldName.t StructMap.t Desugared.Ast.IdentMap.t; field_idmap : StructFieldName.t StructMap.t IdentMap.t;
(** The names of the struct fields. Names of fields can be shared between (** The names of the struct fields. Names of fields can be shared between
different structs *) different structs *)
constructor_idmap : EnumConstructor.t EnumMap.t Desugared.Ast.IdentMap.t; constructor_idmap : EnumConstructor.t EnumMap.t IdentMap.t;
(** The names of the enum constructors. Constructor names can be shared (** The names of the enum constructors. Constructor names can be shared
between different enums *) between different enums *)
scopes : scope_context ScopeMap.t; (** For each scope, its context *) scopes : scope_context ScopeMap.t; (** For each scope, its context *)
@ -104,7 +106,7 @@ val get_var_typ : context -> ScopeVar.t -> typ
(** Gets the type associated to an uid *) (** Gets the type associated to an uid *)
val is_var_cond : context -> ScopeVar.t -> bool val is_var_cond : context -> ScopeVar.t -> bool
val get_var_io : context -> ScopeVar.t -> Ast.scope_decl_context_io val get_var_io : context -> ScopeVar.t -> Surface.Ast.scope_decl_context_io
val get_var_uid : ScopeName.t -> context -> ident Marked.pos -> ScopeVar.t val get_var_uid : ScopeName.t -> context -> ident Marked.pos -> ScopeVar.t
(** Get the variable uid inside the scope given in argument *) (** Get the variable uid inside the scope given in argument *)
@ -120,22 +122,22 @@ val is_subscope_uid : ScopeName.t -> context -> ident -> bool
val belongs_to : context -> ScopeVar.t -> ScopeName.t -> bool val belongs_to : context -> ScopeVar.t -> ScopeName.t -> bool
(** Checks if the var_uid belongs to the scope scope_uid *) (** Checks if the var_uid belongs to the scope scope_uid *)
val get_def_typ : context -> Desugared.Ast.ScopeDef.t -> typ val get_def_typ : context -> Ast.ScopeDef.t -> typ
(** Retrieves the type of a scope definition from the context *) (** Retrieves the type of a scope definition from the context *)
val is_def_cond : context -> Desugared.Ast.ScopeDef.t -> bool val is_def_cond : context -> Ast.ScopeDef.t -> bool
val is_type_cond : Ast.typ -> bool val is_type_cond : Surface.Ast.typ -> bool
val add_def_local_var : context -> ident -> context * Desugared.Ast.expr Var.t val add_def_local_var : context -> ident -> context * Ast.expr Var.t
(** Adds a binding to the context *) (** Adds a binding to the context *)
val get_def_key : val get_def_key :
Ast.qident -> Surface.Ast.qident ->
Ast.ident Marked.pos option -> Surface.Ast.ident Marked.pos option ->
ScopeName.t -> ScopeName.t ->
context -> context ->
Pos.t -> Pos.t ->
Desugared.Ast.ScopeDef.t Ast.ScopeDef.t
(** Usage: [get_def_key var_name var_state scope_uid ctxt pos]*) (** Usage: [get_def_key var_name var_state scope_uid ctxt pos]*)
val get_enum : context -> ident Marked.pos -> EnumName.t val get_enum : context -> ident Marked.pos -> EnumName.t
@ -152,5 +154,5 @@ val get_scope : context -> ident Marked.pos -> ScopeName.t
(** {1 API} *) (** {1 API} *)
val form_context : Ast.program -> context val form_context : Surface.Ast.program -> context
(** Derive the context from metadata, in one pass over the declarations *) (** Derive the context from metadata, in one pass over the declarations *)

View File

@ -143,7 +143,7 @@ let driver source_file (options : Cli.options) : int =
| ( `Interpret | `Typecheck | `OCaml | `Python | `Scalc | `Lcalc | `Dcalc | ( `Interpret | `Typecheck | `OCaml | `Python | `Scalc | `Lcalc | `Dcalc
| `Scopelang | `Proof | `Plugin _ ) as backend -> ( | `Scopelang | `Proof | `Plugin _ ) as backend -> (
Cli.debug_print "Name resolution..."; Cli.debug_print "Name resolution...";
let ctxt = Surface.Name_resolution.form_context prgm in let ctxt = Desugared.Name_resolution.form_context prgm in
let scope_uid = let scope_uid =
match options.ex_scope, backend with match options.ex_scope, backend with
| None, `Interpret -> | None, `Interpret ->
@ -151,27 +151,29 @@ let driver source_file (options : Cli.options) : int =
| None, _ -> | None, _ ->
let _, scope = let _, scope =
try try
Desugared.Ast.IdentMap.filter_map Desugared.Name_resolution.IdentMap.filter_map
(fun _ -> function (fun _ -> function
| Surface.Name_resolution.TScope (uid, _) -> Some uid | Desugared.Name_resolution.TScope (uid, _) -> Some uid
| _ -> None) | _ -> None)
ctxt.typedefs ctxt.typedefs
|> Desugared.Ast.IdentMap.choose |> Desugared.Name_resolution.IdentMap.choose
with Not_found -> with Not_found ->
Errors.raise_error "There isn't any scope inside the program." Errors.raise_error "There isn't any scope inside the program."
in in
scope scope
| Some name, _ -> ( | Some name, _ -> (
match Desugared.Ast.IdentMap.find_opt name ctxt.typedefs with match
| Some (Surface.Name_resolution.TScope (uid, _)) -> uid Desugared.Name_resolution.IdentMap.find_opt name ctxt.typedefs
with
| Some (Desugared.Name_resolution.TScope (uid, _)) -> uid
| _ -> | _ ->
Errors.raise_error "There is no scope \"%s\" inside the program." Errors.raise_error "There is no scope \"%s\" inside the program."
name) name)
in in
Cli.debug_print "Desugaring..."; Cli.debug_print "Desugaring...";
let prgm = Surface.Desugaring.desugar_program ctxt prgm in let prgm = Desugared.From_surface.translate_program ctxt prgm in
Cli.debug_print "Collecting rules..."; Cli.debug_print "Collecting rules...";
let prgm = Desugared.Desugared_to_scope.translate_program prgm in let prgm = Scopelang.From_desugared.translate_program prgm in
match backend with match backend with
| `Scopelang -> | `Scopelang ->
let _output_file, with_output = get_output_format () in let _output_file, with_output = get_output_format () in
@ -194,7 +196,7 @@ let driver source_file (options : Cli.options) : int =
in in
let prgm = Scopelang.Ast.type_program prgm in let prgm = Scopelang.Ast.type_program prgm in
Cli.debug_print "Translating to default calculus..."; Cli.debug_print "Translating to default calculus...";
let prgm = Scopelang.Scope_to_dcalc.translate_program prgm in let prgm = Dcalc.From_scopelang.translate_program prgm in
let prgm = let prgm =
if options.optimize then begin if options.optimize then begin
Cli.debug_print "Optimizing default calculus..."; Cli.debug_print "Optimizing default calculus...";

View File

@ -0,0 +1,21 @@
(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 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. *)
let translate_program_with_exceptions =
Compile_with_exceptions.translate_program
let translate_program_without_exceptions =
Compile_without_exceptions.translate_program

View File

@ -0,0 +1,26 @@
(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 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. *)
val translate_program_with_exceptions : 'm Dcalc.Ast.program -> 'm Ast.program
(** Translation from the default calculus to the lambda calculus. This
translation uses exceptions to handle empty default terms. *)
val translate_program_without_exceptions :
'm Dcalc.Ast.program -> 'm Ast.program
(** Translation from the default calculus to the lambda calculus. This
translation uses an option monad to handle empty defaults terms. This
transformation is one piece to permit to compile toward legacy languages
that does not contains exceptions. *)

View File

@ -39,17 +39,14 @@ let rec locations_used (e : 'm expr) : LocationSet.t =
(fun e -> LocationSet.union (locations_used e)) (fun e -> LocationSet.union (locations_used e))
e LocationSet.empty e LocationSet.empty
type io_input = NoInput | OnlyInput | Reentrant
type io = { io_output : bool Marked.pos; io_input : io_input Marked.pos }
type 'm rule = type 'm rule =
| Definition of location Marked.pos * typ * io * 'm expr | Definition of location Marked.pos * typ * Desugared.Ast.io * 'm expr
| Assertion of 'm expr | Assertion of 'm expr
| Call of ScopeName.t * SubScopeName.t * 'm mark | Call of ScopeName.t * SubScopeName.t * 'm mark
type 'm scope_decl = { type 'm scope_decl = {
scope_decl_name : ScopeName.t; scope_decl_name : ScopeName.t;
scope_sig : (typ * io) ScopeVarMap.t; scope_sig : (typ * Desugared.Ast.io) ScopeVarMap.t;
scope_decl_rules : 'm rule list; scope_decl_rules : 'm rule list;
scope_mark : 'm mark; scope_mark : 'm mark;
} }

View File

@ -31,35 +31,14 @@ type 'm expr = (scopelang, 'm mark) gexpr
val locations_used : 'm expr -> LocationSet.t val locations_used : 'm expr -> LocationSet.t
(** This type characterizes the three levels of visibility for a given scope
variable with regards to the scope's input and possible redefinitions inside
the scope.. *)
type io_input =
| NoInput
(** For an internal variable defined only in the scope, and does not
appear in the input. *)
| OnlyInput
(** For variables that should not be redefined in the scope, because they
appear in the input. *)
| Reentrant
(** For variables defined in the scope that can also be redefined by the
caller as they appear in the input. *)
type io = {
io_output : bool Marked.pos;
(** [true] is present in the output of the scope. *)
io_input : io_input Marked.pos;
}
(** Characterization of the input/output status of a scope variable. *)
type 'm rule = type 'm rule =
| Definition of location Marked.pos * typ * io * 'm expr | Definition of location Marked.pos * typ * Desugared.Ast.io * 'm expr
| Assertion of 'm expr | Assertion of 'm expr
| Call of ScopeName.t * SubScopeName.t * 'm mark | Call of ScopeName.t * SubScopeName.t * 'm mark
type 'm scope_decl = { type 'm scope_decl = {
scope_decl_name : ScopeName.t; scope_decl_name : ScopeName.t;
scope_sig : (typ * io) ScopeVarMap.t; scope_sig : (typ * Desugared.Ast.io) ScopeVarMap.t;
scope_decl_rules : 'm rule list; scope_decl_rules : 'm rule list;
scope_mark : 'm mark; scope_mark : 'm mark;
} }

View File

@ -1,7 +1,7 @@
(library (library
(name scopelang) (name scopelang)
(public_name catala.scopelang) (public_name catala.scopelang)
(libraries utils dcalc ocamlgraph) (libraries utils ocamlgraph desugared)
(flags (flags
(:standard -short-paths))) (:standard -short-paths)))

View File

@ -27,20 +27,19 @@ type target_scope_vars =
type ctx = { type ctx = {
scope_var_mapping : target_scope_vars ScopeVarMap.t; scope_var_mapping : target_scope_vars ScopeVarMap.t;
var_mapping : (Ast.expr, untyped Scopelang.Ast.expr Var.t) Var.Map.t; var_mapping : (Desugared.Ast.expr, untyped Ast.expr Var.t) Var.Map.t;
} }
let tag_with_log_entry let tag_with_log_entry
(e : untyped Scopelang.Ast.expr boxed) (e : untyped Ast.expr boxed)
(l : log_entry) (l : log_entry)
(markings : Utils.Uid.MarkedString.info list) : (markings : Utils.Uid.MarkedString.info list) : untyped Ast.expr boxed =
untyped Scopelang.Ast.expr boxed =
Expr.eapp Expr.eapp
(Expr.eop (Unop (Log (l, markings))) (Marked.get_mark e)) (Expr.eop (Unop (Log (l, markings))) (Marked.get_mark e))
[e] (Marked.get_mark e) [e] (Marked.get_mark e)
let rec translate_expr (ctx : ctx) (e : Ast.expr) : let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
untyped Scopelang.Ast.expr boxed = untyped Ast.expr boxed =
let m = Marked.get_mark e in let m = Marked.get_mark e in
match Marked.unmark e with match Marked.unmark e with
| ELocation (SubScopeVar (s_name, ss_name, s_var)) -> | ELocation (SubScopeVar (s_name, ss_name, s_var)) ->
@ -130,36 +129,36 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr) :
(** Intermediate representation for the exception tree of rules for a particular (** Intermediate representation for the exception tree of rules for a particular
scope definition. *) scope definition. *)
type rule_tree = type rule_tree =
| Leaf of Ast.rule list | Leaf of Desugared.Ast.rule list
(** Rules defining a base case piecewise. List is non-empty. *) (** Rules defining a base case piecewise. List is non-empty. *)
| Node of rule_tree list * Ast.rule list | Node of rule_tree list * Desugared.Ast.rule list
(** [Node (exceptions, base_case)] is a list of exceptions to a non-empty (** [Node (exceptions, base_case)] is a list of exceptions to a non-empty
list of rules defining a base case piecewise. *) list of rules defining a base case piecewise. *)
(** Transforms a flat list of rules into a tree, taking into account the (** Transforms a flat list of rules into a tree, taking into account the
priorities declared between rules *) priorities declared between rules *)
let def_map_to_tree (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) : let def_map_to_tree
rule_tree list = (def_info : Desugared.Ast.ScopeDef.t)
let exc_graph = Dependency.build_exceptions_graph def def_info in (def : Desugared.Ast.rule RuleMap.t) : rule_tree list =
Dependency.check_for_exception_cycle exc_graph; let exc_graph = Desugared.Dependency.build_exceptions_graph def def_info in
Desugared.Dependency.check_for_exception_cycle exc_graph;
(* we start by the base cases: they are the vertices which have no (* we start by the base cases: they are the vertices which have no
successors *) successors *)
let base_cases = let base_cases =
Dependency.ExceptionsDependencies.fold_vertex Desugared.Dependency.ExceptionsDependencies.fold_vertex
(fun v base_cases -> (fun v base_cases ->
if Dependency.ExceptionsDependencies.out_degree exc_graph v = 0 then if
v :: base_cases Desugared.Dependency.ExceptionsDependencies.out_degree exc_graph v = 0
then v :: base_cases
else base_cases) else base_cases)
exc_graph [] exc_graph []
in in
let rec build_tree (base_cases : Ast.RuleSet.t) : rule_tree = let rec build_tree (base_cases : RuleSet.t) : rule_tree =
let exceptions = let exceptions =
Dependency.ExceptionsDependencies.pred exc_graph base_cases Desugared.Dependency.ExceptionsDependencies.pred exc_graph base_cases
in in
let base_case_as_rule_list = let base_case_as_rule_list =
List.map List.map (fun r -> RuleMap.find r def) (RuleSet.elements base_cases)
(fun r -> Ast.RuleMap.find r def)
(Ast.RuleSet.elements base_cases)
in in
match exceptions with match exceptions with
| [] -> Leaf base_case_as_rule_list | [] -> Leaf base_case_as_rule_list
@ -174,8 +173,8 @@ let rec rule_tree_to_expr
~(toplevel : bool) ~(toplevel : bool)
(ctx : ctx) (ctx : ctx)
(def_pos : Pos.t) (def_pos : Pos.t)
(is_func : Ast.expr Var.t option) (is_func : Desugared.Ast.expr Var.t option)
(tree : rule_tree) : untyped Scopelang.Ast.expr boxed = (tree : rule_tree) : untyped Ast.expr boxed =
let emark = Untyped { pos = def_pos } in let emark = Untyped { pos = def_pos } in
let exceptions, base_rules = let exceptions, base_rules =
match tree with Leaf r -> [], r | Node (exceptions, r) -> exceptions, r match tree with Leaf r -> [], r | Node (exceptions, r) -> exceptions, r
@ -183,9 +182,10 @@ let rec rule_tree_to_expr
(* because each rule has its own variable parameter and we want to convert the (* because each rule has its own variable parameter and we want to convert the
whole rule tree into a function, we need to perform some alpha-renaming of whole rule tree into a function, we need to perform some alpha-renaming of
all the expressions *) all the expressions *)
let substitute_parameter (e : Ast.expr boxed) (rule : Ast.rule) : let substitute_parameter
Ast.expr boxed = (e : Desugared.Ast.expr boxed)
match is_func, rule.Ast.rule_parameter with (rule : Desugared.Ast.rule) : Desugared.Ast.expr boxed =
match is_func, rule.Desugared.Ast.rule_parameter with
| Some new_param, Some (old_param, _) -> | Some new_param, Some (old_param, _) ->
let binder = Bindlib.bind_var old_param (Marked.unmark e) in let binder = Bindlib.bind_var old_param (Marked.unmark e) in
Marked.mark (Marked.get_mark e) Marked.mark (Marked.get_mark e)
@ -217,16 +217,16 @@ let rec rule_tree_to_expr
in in
let base_just_list = let base_just_list =
List.map List.map
(fun rule -> substitute_parameter rule.Ast.rule_just rule) (fun rule -> substitute_parameter rule.Desugared.Ast.rule_just rule)
base_rules base_rules
in in
let base_cons_list = let base_cons_list =
List.map List.map
(fun rule -> substitute_parameter rule.Ast.rule_cons rule) (fun rule -> substitute_parameter rule.Desugared.Ast.rule_cons rule)
base_rules base_rules
in in
let translate_and_unbox_list (list : Ast.expr boxed list) : let translate_and_unbox_list (list : Desugared.Ast.expr boxed list) :
untyped Scopelang.Ast.expr boxed list = untyped Ast.expr boxed list =
List.map List.map
(fun e -> (fun e ->
(* There are two levels of boxing here, the outermost is introduced by (* There are two levels of boxing here, the outermost is introduced by
@ -258,7 +258,7 @@ let rec rule_tree_to_expr
(Expr.elit (LBool true) emark) (Expr.elit (LBool true) emark)
default_containing_base_cases emark default_containing_base_cases emark
in in
match is_func, (List.hd base_rules).Ast.rule_parameter with match is_func, (List.hd base_rules).Desugared.Ast.rule_parameter with
| None, None -> default | None, None -> default
| Some new_param, Some (_, typ) -> | Some new_param, Some (_, typ) ->
if toplevel then if toplevel then
@ -277,22 +277,22 @@ let rec rule_tree_to_expr
an {!constructor: Dcalc.EDefault} *) an {!constructor: Dcalc.EDefault} *)
let translate_def let translate_def
(ctx : ctx) (ctx : ctx)
(def_info : Ast.ScopeDef.t) (def_info : Desugared.Ast.ScopeDef.t)
(def : Ast.rule Ast.RuleMap.t) (def : Desugared.Ast.rule RuleMap.t)
(typ : typ) (typ : typ)
(io : Scopelang.Ast.io) (io : Desugared.Ast.io)
~(is_cond : bool) ~(is_cond : bool)
~(is_subscope_var : bool) : untyped Scopelang.Ast.expr boxed = ~(is_subscope_var : bool) : untyped Ast.expr boxed =
(* Here, we have to transform this list of rules into a default tree. *) (* Here, we have to transform this list of rules into a default tree. *)
let is_def_func = let is_def_func =
match Marked.unmark typ with TArrow (_, _) -> true | _ -> false match Marked.unmark typ with TArrow (_, _) -> true | _ -> false
in in
let is_rule_func _ (r : Ast.rule) : bool = let is_rule_func _ (r : Desugared.Ast.rule) : bool =
Option.is_some r.Ast.rule_parameter Option.is_some r.Desugared.Ast.rule_parameter
in in
let all_rules_func = Ast.RuleMap.for_all is_rule_func def in let all_rules_func = RuleMap.for_all is_rule_func def in
let all_rules_not_func = let all_rules_not_func =
Ast.RuleMap.for_all (fun n r -> not (is_rule_func n r)) def RuleMap.for_all (fun n r -> not (is_rule_func n r)) def
in in
let is_def_func_param_typ : typ option = let is_def_func_param_typ : typ option =
if is_def_func && all_rules_func then if is_def_func && all_rules_func then
@ -302,20 +302,21 @@ let translate_def
Errors.raise_spanned_error (Marked.get_mark typ) Errors.raise_spanned_error (Marked.get_mark typ)
"The definitions of %a are function but it doesn't have a function \ "The definitions of %a are function but it doesn't have a function \
type" type"
Ast.ScopeDef.format_t def_info Desugared.Ast.ScopeDef.format_t def_info
else if (not is_def_func) && all_rules_not_func then None else if (not is_def_func) && all_rules_not_func then None
else else
let spans = let spans =
List.map List.map
(fun (_, r) -> (fun (_, r) ->
Some "This definition is a function:", Expr.pos r.Ast.rule_cons) ( Some "This definition is a function:",
(Ast.RuleMap.bindings (Ast.RuleMap.filter is_rule_func def)) Expr.pos r.Desugared.Ast.rule_cons ))
(RuleMap.bindings (RuleMap.filter is_rule_func def))
@ List.map @ List.map
(fun (_, r) -> (fun (_, r) ->
( Some "This definition is not a function:", ( Some "This definition is not a function:",
Expr.pos r.Ast.rule_cons )) Expr.pos r.Desugared.Ast.rule_cons ))
(Ast.RuleMap.bindings (RuleMap.bindings
(Ast.RuleMap.filter (fun n r -> not (is_rule_func n r)) def)) (RuleMap.filter (fun n r -> not (is_rule_func n r)) def))
in in
Errors.raise_multispanned_error spans Errors.raise_multispanned_error spans
"some definitions of the same variable are functions while others \ "some definitions of the same variable are functions while others \
@ -323,7 +324,7 @@ let translate_def
in in
let top_list = def_map_to_tree def_info def in let top_list = def_map_to_tree def_info def in
let is_input = let is_input =
match Marked.unmark io.Scopelang.Ast.io_input with match Marked.unmark io.Desugared.Ast.io_input with
| OnlyInput -> true | OnlyInput -> true
| _ -> false | _ -> false
in in
@ -333,13 +334,13 @@ let translate_def
where the condition is declared. Except when the variable is an input, where the condition is declared. Except when the variable is an input,
where we want the [false] to be added at each caller parent scope. *) where we want the [false] to be added at each caller parent scope. *)
Some Some
(Ast.always_false_rule (Desugared.Ast.always_false_rule
(Ast.ScopeDef.get_position def_info) (Desugared.Ast.ScopeDef.get_position def_info)
is_def_func_param_typ) is_def_func_param_typ)
else None else None
in in
if if
Ast.RuleMap.cardinal def = 0 RuleMap.cardinal def = 0
&& is_subscope_var && is_subscope_var
(* Here we have a special case for the empty definitions. Indeed, we could (* Here we have a special case for the empty definitions. Indeed, we could
use the code for the regular case below that would create a convoluted use the code for the regular case below that would create a convoluted
@ -364,16 +365,18 @@ let translate_def
will not be provided by the calee scope, it has to be placed in the will not be provided by the calee scope, it has to be placed in the
caller. *) caller. *)
then then
Expr.elit LEmptyError (Untyped { pos = Ast.ScopeDef.get_position def_info }) Expr.elit LEmptyError
(Untyped { pos = Desugared.Ast.ScopeDef.get_position def_info })
else else
rule_tree_to_expr ~toplevel:true ctx rule_tree_to_expr ~toplevel:true ctx
(Ast.ScopeDef.get_position def_info) (Desugared.Ast.ScopeDef.get_position def_info)
(Option.map (fun _ -> Var.make "param") is_def_func_param_typ) (Option.map (fun _ -> Var.make "param") is_def_func_param_typ)
(match top_list, top_value with (match top_list, top_value with
| [], None -> | [], None ->
(* In this case, there are no rules to define the expression and no (* In this case, there are no rules to define the expression and no
default value so we put an empty rule. *) default value so we put an empty rule. *)
Leaf [Ast.empty_rule (Marked.get_mark typ) is_def_func_param_typ] Leaf
[Desugared.Ast.empty_rule (Marked.get_mark typ) is_def_func_param_typ]
| [], Some top_value -> | [], Some top_value ->
(* In this case, there are no rules to define the expression but a (* In this case, there are no rules to define the expression but a
default value so we put it. *) default value so we put it. *)
@ -386,32 +389,39 @@ let translate_def
| _, None -> | _, None ->
Node Node
( top_list, ( top_list,
[Ast.empty_rule (Marked.get_mark typ) is_def_func_param_typ] )) [
Desugared.Ast.empty_rule (Marked.get_mark typ)
is_def_func_param_typ;
] ))
(** Translates a scope *) (** Translates a scope *)
let translate_scope (ctx : ctx) (scope : Ast.scope) : let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
untyped Scopelang.Ast.scope_decl = untyped Ast.scope_decl =
let scope_dependencies = Dependency.build_scope_dependencies scope in let scope_dependencies =
Dependency.check_for_cycle scope scope_dependencies; Desugared.Dependency.build_scope_dependencies scope
in
Desugared.Dependency.check_for_cycle scope scope_dependencies;
let scope_ordering = let scope_ordering =
Dependency.correct_computation_ordering scope_dependencies Desugared.Dependency.correct_computation_ordering scope_dependencies
in in
let scope_decl_rules = let scope_decl_rules =
List.flatten List.flatten
(List.map (List.map
(fun vertex -> (fun vertex ->
match vertex with match vertex with
| Dependency.Vertex.Var (var, state) -> ( | Desugared.Dependency.Vertex.Var (var, state) -> (
let scope_def = let scope_def =
Ast.ScopeDefMap.find Desugared.Ast.ScopeDefMap.find
(Ast.ScopeDef.Var (var, state)) (Desugared.Ast.ScopeDef.Var (var, state))
scope.scope_defs scope.scope_defs
in in
let var_def = scope_def.scope_def_rules in let var_def = scope_def.scope_def_rules in
let var_typ = scope_def.scope_def_typ in let var_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in let is_cond = scope_def.scope_def_is_condition in
match Marked.unmark scope_def.Ast.scope_def_io.io_input with match
| OnlyInput when not (Ast.RuleMap.is_empty var_def) -> Marked.unmark scope_def.Desugared.Ast.scope_def_io.io_input
with
| OnlyInput when not (RuleMap.is_empty var_def) ->
(* If the variable is tagged as input, then it shall not be (* If the variable is tagged as input, then it shall not be
redefined. *) redefined. *)
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -420,8 +430,8 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
:: List.map :: List.map
(fun (rule, _) -> (fun (rule, _) ->
( Some "Incriminated variable definition:", ( Some "Incriminated variable definition:",
Marked.get_mark (Ast.RuleName.get_info rule) )) Marked.get_mark (RuleName.get_info rule) ))
(Ast.RuleMap.bindings var_def)) (RuleMap.bindings var_def))
"It is impossible to give a definition to a scope variable \ "It is impossible to give a definition to a scope variable \
tagged as input." tagged as input."
| OnlyInput -> | OnlyInput ->
@ -430,8 +440,8 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
| _ -> | _ ->
let expr_def = let expr_def =
translate_def ctx translate_def ctx
(Ast.ScopeDef.Var (var, state)) (Desugared.Ast.ScopeDef.Var (var, state))
var_def var_typ scope_def.Ast.scope_def_io ~is_cond var_def var_typ scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:false ~is_subscope_var:false
in in
let scope_var = let scope_var =
@ -441,56 +451,61 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
| _ -> failwith "should not happen" | _ -> failwith "should not happen"
in in
[ [
Scopelang.Ast.Definition Ast.Definition
( ( ScopelangScopeVar ( ( ScopelangScopeVar
( scope_var, ( scope_var,
Marked.get_mark (ScopeVar.get_info scope_var) ), Marked.get_mark (ScopeVar.get_info scope_var) ),
Marked.get_mark (ScopeVar.get_info scope_var) ), Marked.get_mark (ScopeVar.get_info scope_var) ),
var_typ, var_typ,
scope_def.Ast.scope_def_io, scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def ); Expr.unbox expr_def );
]) ])
| Dependency.Vertex.SubScope sub_scope_index -> | Desugared.Dependency.Vertex.SubScope sub_scope_index ->
(* Before calling the sub_scope, we need to include all the (* Before calling the sub_scope, we need to include all the
re-definitions of subscope parameters*) re-definitions of subscope parameters*)
let sub_scope = let sub_scope =
SubScopeMap.find sub_scope_index scope.scope_sub_scopes SubScopeMap.find sub_scope_index scope.scope_sub_scopes
in in
let sub_scope_vars_redefs_candidates = let sub_scope_vars_redefs_candidates =
Ast.ScopeDefMap.filter Desugared.Ast.ScopeDefMap.filter
(fun def_key scope_def -> (fun def_key scope_def ->
match def_key with match def_key with
| Ast.ScopeDef.Var _ -> false | Desugared.Ast.ScopeDef.Var _ -> false
| Ast.ScopeDef.SubScopeVar (sub_scope_index', _, _) -> | Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_index', _, _)
->
sub_scope_index = sub_scope_index' sub_scope_index = sub_scope_index'
(* We exclude subscope variables that have 0 re-definitions (* We exclude subscope variables that have 0 re-definitions
and are not visible in the input of the subscope *) and are not visible in the input of the subscope *)
&& not && not
((match ((match
Marked.unmark scope_def.Ast.scope_def_io.io_input Marked.unmark
scope_def.Desugared.Ast.scope_def_io.io_input
with with
| Scopelang.Ast.NoInput -> true | Desugared.Ast.NoInput -> true
| _ -> false) | _ -> false)
&& Ast.RuleMap.is_empty scope_def.scope_def_rules)) && RuleMap.is_empty scope_def.scope_def_rules))
scope.scope_defs scope.scope_defs
in in
let sub_scope_vars_redefs = let sub_scope_vars_redefs =
Ast.ScopeDefMap.mapi Desugared.Ast.ScopeDefMap.mapi
(fun def_key scope_def -> (fun def_key scope_def ->
let def = scope_def.Ast.scope_def_rules in let def = scope_def.Desugared.Ast.scope_def_rules in
let def_typ = scope_def.scope_def_typ in let def_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in let is_cond = scope_def.scope_def_is_condition in
match def_key with match def_key with
| Ast.ScopeDef.Var _ -> assert false (* should not happen *) | Desugared.Ast.ScopeDef.Var _ ->
| Ast.ScopeDef.SubScopeVar (sscope, sub_scope_var, pos) -> assert false (* should not happen *)
| Desugared.Ast.ScopeDef.SubScopeVar
(sscope, sub_scope_var, pos) ->
(* This definition redefines a variable of the correct (* This definition redefines a variable of the correct
subscope. But we have to check that this redefinition is subscope. But we have to check that this redefinition is
allowed with respect to the io parameters of that allowed with respect to the io parameters of that
subscope variable. *) subscope variable. *)
(match (match
Marked.unmark scope_def.Ast.scope_def_io.io_input Marked.unmark
scope_def.Desugared.Ast.scope_def_io.io_input
with with
| Scopelang.Ast.NoInput -> | Desugared.Ast.NoInput ->
Errors.raise_multispanned_error Errors.raise_multispanned_error
(( Some "Incriminated subscope:", (( Some "Incriminated subscope:",
Marked.get_mark (SubScopeName.get_info sscope) ) Marked.get_mark (SubScopeName.get_info sscope) )
@ -501,11 +516,11 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
(fun (rule, _) -> (fun (rule, _) ->
( Some ( Some
"Incriminated subscope variable definition:", "Incriminated subscope variable definition:",
Marked.get_mark (Ast.RuleName.get_info rule) )) Marked.get_mark (RuleName.get_info rule) ))
(Ast.RuleMap.bindings def)) (RuleMap.bindings def))
"It is impossible to give a definition to a subscope \ "It is impossible to give a definition to a subscope \
variable not tagged as input or context." variable not tagged as input or context."
| OnlyInput when Ast.RuleMap.is_empty def && not is_cond -> | OnlyInput when RuleMap.is_empty def && not is_cond ->
(* If the subscope variable is tagged as input, then it (* If the subscope variable is tagged as input, then it
shall be defined. *) shall be defined. *)
Errors.raise_multispanned_error Errors.raise_multispanned_error
@ -521,14 +536,16 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
this redefinition to a proper Scopelang term. *) this redefinition to a proper Scopelang term. *)
let expr_def = let expr_def =
translate_def ctx def_key def def_typ translate_def ctx def_key def def_typ
scope_def.Ast.scope_def_io ~is_cond scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:true ~is_subscope_var:true
in in
let subscop_real_name = let subscop_real_name =
SubScopeMap.find sub_scope_index scope.scope_sub_scopes SubScopeMap.find sub_scope_index scope.scope_sub_scopes
in in
let var_pos = Ast.ScopeDef.get_position def_key in let var_pos =
Scopelang.Ast.Definition Desugared.Ast.ScopeDef.get_position def_key
in
Ast.Definition
( ( SubScopeVar ( ( SubScopeVar
( subscop_real_name, ( subscop_real_name,
(sub_scope_index, var_pos), (sub_scope_index, var_pos),
@ -544,16 +561,17 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
snd (List.hd states), var_pos ), snd (List.hd states), var_pos ),
var_pos ), var_pos ),
def_typ, def_typ,
scope_def.Ast.scope_def_io, scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def )) Expr.unbox expr_def ))
sub_scope_vars_redefs_candidates sub_scope_vars_redefs_candidates
in in
let sub_scope_vars_redefs = let sub_scope_vars_redefs =
List.map snd (Ast.ScopeDefMap.bindings sub_scope_vars_redefs) List.map snd
(Desugared.Ast.ScopeDefMap.bindings sub_scope_vars_redefs)
in in
sub_scope_vars_redefs sub_scope_vars_redefs
@ [ @ [
Scopelang.Ast.Call Ast.Call
( sub_scope, ( sub_scope,
sub_scope_index, sub_scope_index,
Untyped Untyped
@ -573,16 +591,18 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
@ List.map @ List.map
(fun e -> (fun e ->
let scope_e = translate_expr ctx (Expr.unbox e) in let scope_e = translate_expr ctx (Expr.unbox e) in
Scopelang.Ast.Assertion (Expr.unbox scope_e)) Ast.Assertion (Expr.unbox scope_e))
scope.Ast.scope_assertions scope.Desugared.Ast.scope_assertions
in in
let scope_sig = let scope_sig =
ScopeVarMap.fold ScopeVarMap.fold
(fun var (states : Ast.var_or_states) acc -> (fun var (states : Desugared.Ast.var_or_states) acc ->
match states with match states with
| WholeVar -> | WholeVar ->
let scope_def = let scope_def =
Ast.ScopeDefMap.find (Ast.ScopeDef.Var (var, None)) scope.scope_defs Desugared.Ast.ScopeDefMap.find
(Desugared.Ast.ScopeDef.Var (var, None))
scope.scope_defs
in in
let typ = scope_def.scope_def_typ in let typ = scope_def.scope_def_typ in
ScopeVarMap.add ScopeVarMap.add
@ -593,13 +613,13 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
acc acc
| States states -> | States states ->
(* What happens in the case of variables with multiple states is (* What happens in the case of variables with multiple states is
interesting. We need to create as many Scopelang.Var entries in the interesting. We need to create as many Var entries in the scope
scope signature as there are states. *) signature as there are states. *)
List.fold_left List.fold_left
(fun acc (state : StateName.t) -> (fun acc (state : StateName.t) ->
let scope_def = let scope_def =
Ast.ScopeDefMap.find Desugared.Ast.ScopeDefMap.find
(Ast.ScopeDef.Var (var, Some state)) (Desugared.Ast.ScopeDef.Var (var, Some state))
scope.scope_defs scope.scope_defs
in in
ScopeVarMap.add ScopeVarMap.add
@ -613,27 +633,27 @@ let translate_scope (ctx : ctx) (scope : Ast.scope) :
in in
let pos = Marked.get_mark (ScopeName.get_info scope.scope_uid) in let pos = Marked.get_mark (ScopeName.get_info scope.scope_uid) in
{ {
Scopelang.Ast.scope_decl_name = scope.scope_uid; Ast.scope_decl_name = scope.scope_uid;
Scopelang.Ast.scope_decl_rules; Ast.scope_decl_rules;
Scopelang.Ast.scope_sig; Ast.scope_sig;
Scopelang.Ast.scope_mark = Untyped { pos }; Ast.scope_mark = Untyped { pos };
} }
(** {1 API} *) (** {1 API} *)
let translate_program (pgrm : Ast.program) : untyped Scopelang.Ast.program = let translate_program (pgrm : Desugared.Ast.program) : untyped Ast.program =
(* First we give mappings to all the locations between Desugared and (* First we give mappings to all the locations between Desugared and This
Scopelang. This involves creating a new Scopelang scope variable for every involves creating a new Scopelang scope variable for every state of a
state of a Desugared variable. *) Desugared variable. *)
let ctx = let ctx =
(* Todo: since we rename all scope vars at this point, it would be better to (* Todo: since we rename all scope vars at this point, it would be better to
have different types for Desugared.ScopeVar.t and Scopelang.ScopeVar.t *) have different types for Desugared.ScopeVar.t and Scopelang.ScopeVar.t *)
ScopeMap.fold ScopeMap.fold
(fun _scope scope_decl ctx -> (fun _scope scope_decl ctx ->
ScopeVarMap.fold ScopeVarMap.fold
(fun scope_var (states : Ast.var_or_states) ctx -> (fun scope_var (states : Desugared.Ast.var_or_states) ctx ->
match states with match states with
| Ast.WholeVar -> | Desugared.Ast.WholeVar ->
{ {
ctx with ctx with
scope_var_mapping = scope_var_mapping =
@ -661,8 +681,8 @@ let translate_program (pgrm : Ast.program) : untyped Scopelang.Ast.program =
states)) states))
ctx.scope_var_mapping; ctx.scope_var_mapping;
}) })
scope_decl.Ast.scope_vars ctx) scope_decl.Desugared.Ast.scope_vars ctx)
pgrm.Ast.program_scopes pgrm.Desugared.Ast.program_scopes
{ scope_var_mapping = ScopeVarMap.empty; var_mapping = Var.Map.empty } { scope_var_mapping = ScopeVarMap.empty; var_mapping = Var.Map.empty }
in in
let ctx_scopes = let ctx_scopes =
@ -680,10 +700,9 @@ let translate_program (pgrm : Ast.program) : untyped Scopelang.Ast.program =
out_str.out_struct_fields ScopeVarMap.empty out_str.out_struct_fields ScopeVarMap.empty
in in
{ out_str with out_struct_fields }) { out_str with out_struct_fields })
pgrm.Ast.program_ctx.ctx_scopes pgrm.Desugared.Ast.program_ctx.ctx_scopes
in in
{ {
Scopelang.Ast.program_scopes = Ast.program_scopes = ScopeMap.map (translate_scope ctx) pgrm.program_scopes;
ScopeMap.map (translate_scope ctx) pgrm.program_scopes;
program_ctx = { pgrm.program_ctx with ctx_scopes }; program_ctx = { pgrm.program_ctx with ctx_scopes };
} }

View File

@ -16,4 +16,4 @@
(** Translation from {!module: Desugared.Ast} to {!module: Scopelang.Ast} *) (** Translation from {!module: Desugared.Ast} to {!module: Scopelang.Ast} *)
val translate_program : Ast.program -> Shared_ast.untyped Scopelang.Ast.program val translate_program : Desugared.Ast.program -> Shared_ast.untyped Ast.program

View File

@ -56,11 +56,11 @@ let scope ?(debug = false) ctx fmt (name, decl) =
Format.fprintf fmt "%a%a%a %a%a%a%a%a" Print.punctuation "(" Format.fprintf fmt "%a%a%a %a%a%a%a%a" Print.punctuation "("
ScopeVar.format_t scope_var Print.punctuation ":" (Print.typ ctx) typ ScopeVar.format_t scope_var Print.punctuation ":" (Print.typ ctx) typ
Print.punctuation "|" Print.keyword Print.punctuation "|" Print.keyword
(match Marked.unmark vis.io_input with (match Marked.unmark vis.Desugared.Ast.io_input with
| NoInput -> "internal" | NoInput -> "internal"
| OnlyInput -> "input" | OnlyInput -> "input"
| Reentrant -> "context") | Reentrant -> "context")
(if Marked.unmark vis.io_output then fun fmt () -> (if Marked.unmark vis.Desugared.Ast.io_output then fun fmt () ->
Format.fprintf fmt "%a@,%a" Print.punctuation "|" Print.keyword Format.fprintf fmt "%a@,%a" Print.punctuation "|" Print.keyword
"output" "output"
else fun fmt () -> Format.fprintf fmt "@<0>") else fun fmt () -> Format.fprintf fmt "@<0>")

View File

@ -45,6 +45,20 @@ module EnumConstructor : Uid.Id with type info = Uid.MarkedString.info =
module EnumMap : Map.S with type key = EnumName.t = Map.Make (EnumName) module EnumMap : Map.S with type key = EnumName.t = Map.Make (EnumName)
(** Only used by surface *)
module RuleName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module RuleMap : Map.S with type key = RuleName.t = Map.Make (RuleName)
module RuleSet : Set.S with type elt = RuleName.t = Set.Make (RuleName)
module LabelName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module LabelMap : Map.S with type key = LabelName.t = Map.Make (LabelName)
module LabelSet : Set.S with type elt = LabelName.t = Set.Make (LabelName)
(** Only used by desugared/scopelang *) (** Only used by desugared/scopelang *)
module ScopeVar : Uid.Id with type info = Uid.MarkedString.info = module ScopeVar : Uid.Id with type info = Uid.MarkedString.info =

View File

@ -493,7 +493,7 @@ type rule = {
rule_parameter : ident Marked.pos option; rule_parameter : ident Marked.pos option;
rule_condition : expression Marked.pos option; rule_condition : expression Marked.pos option;
rule_name : qident Marked.pos; rule_name : qident Marked.pos;
rule_id : Desugared.Ast.RuleName.t; [@opaque] rule_id : Shared_ast.RuleName.t; [@opaque]
rule_consequence : (bool[@opaque]) Marked.pos; rule_consequence : (bool[@opaque]) Marked.pos;
rule_state : ident Marked.pos option; rule_state : ident Marked.pos option;
} }
@ -517,7 +517,7 @@ type definition = {
definition_name : qident Marked.pos; definition_name : qident Marked.pos;
definition_parameter : ident Marked.pos option; definition_parameter : ident Marked.pos option;
definition_condition : expression Marked.pos option; definition_condition : expression Marked.pos option;
definition_id : Desugared.Ast.RuleName.t; [@opaque] definition_id : Shared_ast.RuleName.t; [@opaque]
definition_expr : expression Marked.pos; definition_expr : expression Marked.pos;
definition_state : ident Marked.pos option; definition_state : ident Marked.pos option;
} }

View File

@ -6,11 +6,10 @@
menhirLib menhirLib
sedlex sedlex
re re
desugared
scopelang
zarith zarith
zarith_stubs_js zarith_stubs_js
dates_calc) dates_calc
shared_ast)
(preprocess (preprocess
(pps sedlex.ppx visitors.ppx))) (pps sedlex.ppx visitors.ppx)))

View File

@ -392,7 +392,7 @@ rule:
rule_parameter = param_applied; rule_parameter = param_applied;
rule_condition = cond; rule_condition = cond;
rule_name = name; rule_name = name;
rule_id = Desugared.Ast.RuleName.fresh rule_id = Shared_ast.RuleName.fresh
(String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)), (String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)),
Pos.from_lpos $sloc); Pos.from_lpos $sloc);
rule_consequence = cons; rule_consequence = cons;
@ -429,7 +429,7 @@ definition:
definition_parameter = param; definition_parameter = param;
definition_condition = cond; definition_condition = cond;
definition_id = definition_id =
Desugared.Ast.RuleName.fresh Shared_ast.RuleName.fresh
(String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)), (String.concat "." (List.map (fun i -> Marked.unmark i) (Marked.unmark name)),
Pos.from_lpos $sloc); Pos.from_lpos $sloc);
definition_expr = e; definition_expr = e;