Merge branch 'master' into fix_362

This commit is contained in:
Denis Merigoux 2022-12-07 15:32:08 +01:00
commit 619461dba8
No known key found for this signature in database
GPG Key ID: EE99DCFA365C3EE3
196 changed files with 1925 additions and 1842 deletions

View File

@ -16,7 +16,7 @@
the License. *)
open Cmdliner
open Utils
open Catala_utils
open Ninja_utils
module Nj = Ninja_utils

View File

@ -9,7 +9,7 @@
(public_name clerk.driver)
(libraries
catala.runtime_ocaml
catala.utils
catala.catala_utils
ninja_utils
cmdliner
re

View File

@ -7,12 +7,12 @@ In {{: desugared.html} the desugared representation} or in the
global identifiers. These identifiers use OCaml's type system to statically
distinguish e.g. a scope identifier from a struct identifier.
The {!module: Utils.Uid} module provides a generative functor whose output is
The {!module: Uid} module provides a generative functor whose output is
a fresh sort of global identifiers.
Related modules:
{!modules: Utils.Uid}
{!modules: Uid}
{1 Source code positions}
@ -22,7 +22,7 @@ code. These annotations are critical to produce readable error messages.
Related modules:
{!modules: Utils.Pos}
{!modules: Pos}
{1 Error messages}

View File

@ -1,8 +1,8 @@
(library
(name utils)
(public_name catala.utils)
(name catala_utils)
(public_name catala.catala_utils)
(libraries cmdliner ubase ANSITerminal re bindlib catala.runtime_ocaml))
(documentation
(package catala)
(mld_files utils))
(mld_files catala_utils))

View File

@ -79,11 +79,11 @@ let to_string (pos : t) : string =
let to_string_short (pos : t) : string =
let s, e = pos.code_pos in
if e.Lexing.pos_lnum = s.Lexing.pos_lnum then
Printf.sprintf "%s:%d.%d-%d" s.Lexing.pos_fname s.Lexing.pos_lnum
Printf.sprintf "%s:%d.%d-%d:" s.Lexing.pos_fname s.Lexing.pos_lnum
(s.Lexing.pos_cnum - s.Lexing.pos_bol)
(e.Lexing.pos_cnum - e.Lexing.pos_bol)
else
Printf.sprintf "%s:%d.%d-%d.%d" s.Lexing.pos_fname s.Lexing.pos_lnum
Printf.sprintf "%s:%d.%d-%d.%d:" s.Lexing.pos_fname s.Lexing.pos_lnum
(s.Lexing.pos_cnum - s.Lexing.pos_bol)
e.Lexing.pos_lnum
(e.Lexing.pos_cnum - e.Lexing.pos_bol)
@ -102,6 +102,27 @@ let string_repeat n s =
done;
Bytes.to_string buf
(* Note: this should do, but remains incorrect for combined unicode characters
that display as one (e.g. `e` + postfix `'`). We should switch to Uuseg at
some poing *)
let string_columns s =
let len = String.length s in
let rec aux ncols i =
if i >= len then ncols
else if s.[i] = '\t' then aux (ncols + 8) (i + 1)
else
aux (ncols + 1) (i + Uchar.utf_decode_length (String.get_utf_8_uchar s i))
in
aux 0 0
let utf8_byte_index s ui0 =
let rec aux bi ui =
if ui >= ui0 then bi
else
aux (bi + Uchar.utf_decode_length (String.get_utf_8_uchar s bi)) (ui + 1)
in
aux 0 0
let retrieve_loc_text (pos : t) : string =
try
let filename = get_file pos in
@ -132,34 +153,32 @@ let retrieve_loc_text (pos : t) : string =
let print_matched_line (line : string) (line_no : int) : string =
let line_indent = indent_number line in
let error_indicator_style = [ANSITerminal.red; ANSITerminal.Bold] in
line
^
if line_no >= sline && line_no <= eline then
"\n"
^
if line_no = sline && line_no = eline then
Cli.with_style error_indicator_style "%*s%s"
(get_start_column pos - 1)
""
(string_repeat
(max (get_end_column pos - get_start_column pos) 0)
"")
else if line_no = sline && line_no <> eline then
Cli.with_style error_indicator_style "%*s%s"
(get_start_column pos - 1)
""
(string_repeat
(max (String.length line - get_start_column pos) 0)
"")
else if line_no <> sline && line_no <> eline then
Cli.with_style error_indicator_style "%*s%s" line_indent ""
(string_repeat (max (String.length line - line_indent) 0) "")
else if line_no <> sline && line_no = eline then
Cli.with_style error_indicator_style "%*s%*s" line_indent ""
(get_end_column pos - 1 - line_indent)
(string_repeat (max (get_end_column pos - line_indent) 0) "")
else assert false (* should not happen *)
else ""
let match_start_index =
utf8_byte_index line
(if line_no = sline then get_start_column pos - 1 else line_indent)
in
let match_end_index =
if line_no = eline then utf8_byte_index line (get_end_column pos - 1)
else String.length line
in
let unmatched_prefix = String.sub line 0 match_start_index in
let matched_substring =
String.sub line match_start_index
(max 0 (match_end_index - match_start_index))
in
let match_start_col = string_columns unmatched_prefix in
let match_num_cols = string_columns matched_substring in
String.concat ""
(line
:: "\n"
::
(if line_no >= sline && line_no <= eline then
[
string_repeat match_start_col " ";
Cli.with_style error_indicator_style "%s"
(string_repeat match_num_cols "");
]
else []))
in
let include_extra_count = 0 in
let rec get_lines (n : int) : string list =
@ -193,10 +212,8 @@ let retrieve_loc_text (pos : t) : string =
(Cli.with_style blue_style "└%s┐" (string_repeat spaces ""));
Buffer.add_char buf '\n';
Buffer.add_string buf
(Cli.add_prefix_to_each_line
(String.concat "\n" ("" :: pos_lines))
(fun i ->
let cur_line = sline - include_extra_count + i - 1 in
(Cli.add_prefix_to_each_line (String.concat "\n" pos_lines) (fun i ->
let cur_line = sline - include_extra_count + i in
if
cur_line >= sline
&& cur_line <= sline + (2 * (eline - sline))

View File

@ -14,39 +14,41 @@
License for the specific language governing permissions and limitations under
the License. *)
let to_ascii : string -> string = Ubase.from_utf8
include Stdlib.String
let is_uppercase_ascii (c : char) : bool =
let c = Char.code c in
(* 'A' <= c && c <= 'Z' *)
0x41 <= c && c <= 0x5b
let to_ascii : string -> string = Ubase.from_utf8
let is_uppercase_ascii = function 'A' .. 'Z' -> true | _ -> false
let begins_with_uppercase (s : string) : bool =
if "" = s then false else is_uppercase_ascii (to_ascii s).[0]
"" <> s && is_uppercase_ascii (get (to_ascii s) 0)
let to_snake_case (s : string) : string =
let out = ref "" in
to_ascii s
|> String.iteri (fun i c ->
|> iteri (fun i c ->
out :=
!out
^ (if is_uppercase_ascii c && 0 <> i then "_" else "")
^ String.lowercase_ascii (String.make 1 c));
^ lowercase_ascii (make 1 c));
!out
let to_camel_case (s : string) : string =
let last_was_underscore = ref false in
let out = ref "" in
to_ascii s
|> String.iteri (fun i c ->
|> iteri (fun i c ->
let is_underscore = c = '_' in
let c_string = String.make 1 c in
let c_string = make 1 c in
out :=
!out
^
if is_underscore then ""
else if !last_was_underscore || 0 = i then
String.uppercase_ascii c_string
else if !last_was_underscore || 0 = i then uppercase_ascii c_string
else c_string;
last_was_underscore := is_underscore);
!out
let format_t = Format.pp_print_string
module Set = Set.Make (Stdlib.String)
module Map = Map.Make (Stdlib.String)

View File

@ -14,6 +14,10 @@
License for the specific language governing permissions and limitations under
the License. *)
include module type of Stdlib.String
module Set : Set.S with type elt = string
module Map : Map.S with type key = string
(** Helper functions used for string manipulation. *)
val to_ascii : string -> string
@ -34,3 +38,5 @@ val to_snake_case : string -> string
val to_camel_case : string -> string
(** Converts snake_case into CamlCase after removing Remove all diacritics on
Latin letters. *)
val format_t : Format.formatter -> string -> unit

View File

@ -18,7 +18,7 @@ module type Info = sig
type info
val to_string : info -> string
val format_info : Format.formatter -> info -> unit
val format : Format.formatter -> info -> unit
val equal : info -> info -> bool
val compare : info -> info -> int
end
@ -33,10 +33,21 @@ module type Id = sig
val equal : t -> t -> bool
val format_t : Format.formatter -> t -> unit
val hash : t -> int
module Set : Set.S with type elt = t
module Map : Map.S with type key = t
end
module Make (X : Info) () : Id with type info = X.info = struct
type t = { id : int; info : X.info }
module Ordering = struct
type t = { id : int; info : X.info }
let compare (x : t) (y : t) : int = compare x.id y.id
let equal x y = Int.equal x.id y.id
end
include Ordering
type info = X.info
let counter = ref 0
@ -46,20 +57,20 @@ module Make (X : Info) () : Id with type info = X.info = struct
{ id = !counter; info }
let get_info (uid : t) : X.info = uid.info
let compare (x : t) (y : t) : int = compare x.id y.id
let equal x y = Int.equal x.id y.id
let format_t (fmt : Format.formatter) (x : t) : unit =
X.format_info fmt x.info
let format_t (fmt : Format.formatter) (x : t) : unit = X.format fmt x.info
let hash (x : t) : int = x.id
module Set = Set.Make (Ordering)
module Map = Map.Make (Ordering)
end
module MarkedString = struct
type info = string Marked.pos
let to_string (s, _) = s
let format_info fmt i = Format.pp_print_string fmt (to_string i)
let format fmt i = Format.pp_print_string fmt (to_string i)
let equal i1 i2 = String.equal (Marked.unmark i1) (Marked.unmark i2)
let compare i1 i2 = String.compare (Marked.unmark i1) (Marked.unmark i2)
end
module Gen () = Make (MarkedString) ()

View File

@ -21,7 +21,7 @@ module type Info = sig
type info
val to_string : info -> string
val format_info : Format.formatter -> info -> unit
val format : Format.formatter -> info -> unit
val equal : info -> info -> bool
(** Equality disregards position *)
@ -48,9 +48,15 @@ module type Id = sig
val equal : t -> t -> bool
val format_t : Format.formatter -> t -> unit
val hash : t -> int
module Set : Set.S with type elt = t
module Map : Map.S with type key = t
end
(** This is the generative functor that ensures that two modules resulting from
two different calls to [Make] will be viewed as different types [t] by the
OCaml typechecker. Prevents mixing up different sorts of identifiers. *)
module Make (X : Info) () : Id with type info = X.info
module Gen () : Id with type info = MarkedString.info
(** Shortcut for creating a kind of uids over marked strings *)

View File

@ -1,3 +1,4 @@
open Catala_utils
open Driver
open Js_of_ocaml
@ -12,7 +13,7 @@ let _ =
driver
(Contents (Js.to_string contents))
{
Utils.Cli.debug = false;
Cli.debug = false;
color = Never;
wrap_weaved_output = false;
avoid_exceptions = false;

View File

@ -4,7 +4,7 @@
(libraries
bindlib
unionFind
utils
catala_utils
re
ubase
catala.runtime_ocaml

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
type scope_var_ctx = {
@ -24,7 +24,7 @@ type scope_var_ctx = {
}
type scope_input_var_ctx = {
scope_input_name : StructFieldName.t;
scope_input_name : StructField.t;
scope_input_io : Desugared.Ast.io_input Marked.pos;
scope_input_typ : naked_typ;
}
@ -36,25 +36,26 @@ type 'm scope_sig_ctx = {
(** Var representing the scope input inside the scope func *)
scope_sig_input_struct : StructName.t; (** Scope input *)
scope_sig_output_struct : StructName.t; (** Scope output *)
scope_sig_in_fields : scope_input_var_ctx ScopeVarMap.t;
scope_sig_in_fields : scope_input_var_ctx ScopeVar.Map.t;
(** Mapping between the input scope variables and the input struct fields. *)
scope_sig_out_fields : StructFieldName.t ScopeVarMap.t;
scope_sig_out_fields : StructField.t ScopeVar.Map.t;
(** Mapping between the output scope variables and the output struct
fields. TODO: could likely be removed now that we have it in the
program ctx *)
}
type 'm scope_sigs_ctx = 'm scope_sig_ctx ScopeMap.t
type 'm scope_sigs_ctx = 'm scope_sig_ctx ScopeName.Map.t
type 'm ctx = {
structs : struct_ctx;
enums : enum_ctx;
scope_name : ScopeName.t;
scopes_parameters : 'm scope_sigs_ctx;
scope_vars : ('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVarMap.t;
scope_vars :
('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVar.Map.t;
subscope_vars :
('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVarMap.t
SubScopeMap.t;
('m Ast.expr Var.t * naked_typ * Desugared.Ast.io) ScopeVar.Map.t
SubScopeName.Map.t;
local_vars : ('m Scopelang.Ast.expr, 'm Ast.expr Var.t) Var.Map.t;
}
@ -68,8 +69,8 @@ let empty_ctx
enums = enum_ctx;
scope_name;
scopes_parameters = scopes_ctx;
scope_vars = ScopeVarMap.empty;
subscope_vars = SubScopeMap.empty;
scope_vars = ScopeVar.Map.empty;
subscope_vars = SubScopeName.Map.empty;
local_vars = Var.Map.empty;
}
@ -149,7 +150,7 @@ let merge_defaults
let tag_with_log_entry
(e : 'm Ast.expr boxed)
(l : log_entry)
(markings : Utils.Uid.MarkedString.info list) : 'm Ast.expr boxed =
(markings : Uid.MarkedString.info list) : 'm Ast.expr boxed =
let m = mark_tany (Marked.get_mark e) (Expr.pos e) in
Expr.eapp (Expr.eop (Unop (Log (l, markings))) m) [e] m
@ -221,7 +222,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
| LDuration _ ) as l) ->
Expr.elit l m
| EStruct { name; fields } ->
let fields = StructFieldMap.map (translate_expr ctx) fields in
let fields = StructField.Map.map (translate_expr ctx) fields in
Expr.estruct name fields m
| EStructAccess { e; field; name } ->
Expr.estructaccess (translate_expr ctx e) field name m
@ -229,13 +230,13 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
let e' = translate_expr ctx e in
Expr.einj e' cons name m
| EMatch { e = e1; name; cases = e_cases } ->
let enum_sig = EnumMap.find name ctx.enums in
let enum_sig = EnumName.Map.find name ctx.enums in
let d_cases, remaining_e_cases =
(* FIXME: these checks should probably be moved to a better place *)
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun constructor _ (d_cases, e_cases) ->
let case_e =
try EnumConstructorMap.find constructor e_cases
try EnumConstructor.Map.find constructor e_cases
with Not_found ->
Errors.raise_spanned_error (Expr.pos e)
"The constructor %a of enum %a is missing from this pattern \
@ -243,26 +244,26 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
EnumConstructor.format_t constructor EnumName.format_t name
in
let case_d = translate_expr ctx case_e in
( EnumConstructorMap.add constructor case_d d_cases,
EnumConstructorMap.remove constructor e_cases ))
( EnumConstructor.Map.add constructor case_d d_cases,
EnumConstructor.Map.remove constructor e_cases ))
enum_sig
(EnumConstructorMap.empty, e_cases)
(EnumConstructor.Map.empty, e_cases)
in
if not (EnumConstructorMap.is_empty remaining_e_cases) then
if not (EnumConstructor.Map.is_empty remaining_e_cases) then
Errors.raise_spanned_error (Expr.pos e)
"Pattern matching is incomplete for enum %a: missing cases %a"
EnumName.format_t name
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ", ")
(fun fmt (case_name, _) -> EnumConstructor.format_t fmt case_name))
(EnumConstructorMap.bindings remaining_e_cases);
(EnumConstructor.Map.bindings remaining_e_cases);
let e1 = translate_expr ctx e1 in
Expr.ematch e1 name d_cases m
| EScopeCall { scope; args } ->
let pos = Expr.mark_pos m in
let sc_sig = ScopeMap.find scope ctx.scopes_parameters in
let sc_sig = ScopeName.Map.find scope ctx.scopes_parameters in
let in_var_map =
ScopeVarMap.merge
ScopeVar.Map.merge
(fun var_name (str_field : scope_input_var_ctx option) expr ->
let expr =
match str_field, expr with
@ -287,7 +288,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
None, pos;
( Some "Declaration of the missing input variable",
Marked.get_mark
(StructFieldName.get_info var_ctx.scope_input_name) );
(StructField.get_info var_ctx.scope_input_name) );
]
"Definition of input variable '%a' missing in this scope call"
ScopeVar.format_t var_name
@ -303,9 +304,9 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
sc_sig.scope_sig_in_fields args
in
let field_map =
ScopeVarMap.fold
(fun _ (fld, e) acc -> StructFieldMap.add fld e acc)
in_var_map StructFieldMap.empty
ScopeVar.Map.fold
(fun _ (fld, e) acc -> StructField.Map.add fld e acc)
in_var_map StructField.Map.empty
in
let arg_struct =
Expr.estruct sc_sig.scope_sig_input_struct field_map (mark_tany m pos)
@ -336,7 +337,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
-- for more information see
https://github.com/CatalaLang/catala/pull/280#discussion_r898851693. *)
let retrieve_in_and_out_typ_or_any var vars =
let _, typ, _ = ScopeVarMap.find (Marked.unmark var) vars in
let _, typ, _ = ScopeVar.Map.find (Marked.unmark var) vars in
match typ with
| TArrow (marked_input_typ, marked_output_typ) ->
Marked.unmark marked_input_typ, Marked.unmark marked_output_typ
@ -347,7 +348,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
retrieve_in_and_out_typ_or_any var ctx.scope_vars
| ELocation (SubScopeVar (_, sname, var)) ->
ctx.subscope_vars
|> SubScopeMap.find (Marked.unmark sname)
|> SubScopeName.Map.find (Marked.unmark sname)
|> retrieve_in_and_out_typ_or_any var
| _ -> TAny, TAny
in
@ -394,13 +395,13 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
(List.map (translate_expr ctx) excepts)
(translate_expr ctx just) (translate_expr ctx cons) m
| ELocation (ScopelangScopeVar a) ->
let v, _, _ = ScopeVarMap.find (Marked.unmark a) ctx.scope_vars in
let v, _, _ = ScopeVar.Map.find (Marked.unmark a) ctx.scope_vars in
Expr.evar v m
| ELocation (SubScopeVar (_, s, a)) -> (
try
let v, _, _ =
ScopeVarMap.find (Marked.unmark a)
(SubScopeMap.find (Marked.unmark s) ctx.subscope_vars)
ScopeVar.Map.find (Marked.unmark a)
(SubScopeName.Map.find (Marked.unmark s) ctx.subscope_vars)
in
Expr.evar v m
with Not_found ->
@ -420,7 +421,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
Expr.eifthenelse (translate_expr ctx cond) (translate_expr ctx etrue)
(translate_expr ctx efalse)
m
| EOp op -> Expr.eop op m
| EOp op -> Expr.eop (Expr.translate_op op) m
| EErrorOnEmpty e' -> Expr.eerroronempty (translate_expr ctx e') m
| EArray es -> Expr.earray (List.map (translate_expr ctx) es) m
@ -432,7 +433,7 @@ let rec translate_expr (ctx : 'm ctx) (e : 'm Scopelang.Ast.expr) :
let translate_rule
(ctx : 'm ctx)
(rule : 'm Scopelang.Ast.rule)
((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) :
((sigma_name, pos_sigma) : Uid.MarkedString.info) :
('m Ast.expr scope_body_expr Bindlib.box ->
'm Ast.expr scope_body_expr Bindlib.box)
* 'm ctx =
@ -475,7 +476,7 @@ let translate_rule
{
ctx with
scope_vars =
ScopeVarMap.add (Marked.unmark a)
ScopeVar.Map.add (Marked.unmark a)
(a_var, Marked.unmark tau, a_io)
ctx.scope_vars;
} )
@ -524,22 +525,22 @@ let translate_rule
{
ctx with
subscope_vars =
SubScopeMap.update (Marked.unmark subs_index)
SubScopeName.Map.update (Marked.unmark subs_index)
(fun map ->
match map with
| Some map ->
Some
(ScopeVarMap.add (Marked.unmark subs_var)
(ScopeVar.Map.add (Marked.unmark subs_var)
(a_var, Marked.unmark tau, a_io)
map)
| None ->
Some
(ScopeVarMap.singleton (Marked.unmark subs_var)
(ScopeVar.Map.singleton (Marked.unmark subs_var)
(a_var, Marked.unmark tau, a_io)))
ctx.subscope_vars;
} )
| Call (subname, subindex, m) ->
let subscope_sig = ScopeMap.find subname ctx.scopes_parameters in
let subscope_sig = ScopeName.Map.find subname ctx.scopes_parameters in
let all_subscope_vars = subscope_sig.scope_sig_local_vars in
let all_subscope_input_vars =
List.filter
@ -559,11 +560,11 @@ let translate_rule
let called_scope_input_struct = subscope_sig.scope_sig_input_struct in
let called_scope_return_struct = subscope_sig.scope_sig_output_struct in
let subscope_vars_defined =
try SubScopeMap.find subindex ctx.subscope_vars
with Not_found -> ScopeVarMap.empty
try SubScopeName.Map.find subindex ctx.subscope_vars
with Not_found -> ScopeVar.Map.empty
in
let subscope_var_not_yet_defined subvar =
not (ScopeVarMap.mem subvar subscope_vars_defined)
not (ScopeVar.Map.mem subvar subscope_vars_defined)
in
let pos_call = Marked.get_mark (SubScopeName.get_info subindex) in
let subscope_args =
@ -578,17 +579,17 @@ let translate_rule
Expr.empty_thunked_term m
else
let a_var, _, _ =
ScopeVarMap.find subvar.scope_var_name subscope_vars_defined
ScopeVar.Map.find subvar.scope_var_name subscope_vars_defined
in
Expr.make_var a_var (mark_tany m pos_call)
in
let field =
(ScopeVarMap.find subvar.scope_var_name
(ScopeVar.Map.find subvar.scope_var_name
subscope_sig.scope_sig_in_fields)
.scope_input_name
in
StructFieldMap.add field e acc)
StructFieldMap.empty all_subscope_input_vars
StructField.Map.add field e acc)
StructField.Map.empty all_subscope_input_vars
in
let subscope_struct_arg =
Expr.estruct called_scope_input_struct subscope_args
@ -646,7 +647,7 @@ let translate_rule
List.fold_right
(fun (var_ctx, v) next ->
let field =
ScopeVarMap.find var_ctx.scope_var_name
ScopeVar.Map.find var_ctx.scope_var_name
subscope_sig.scope_sig_out_fields
in
Bindlib.box_apply2
@ -671,13 +672,13 @@ let translate_rule
{
ctx with
subscope_vars =
SubScopeMap.add subindex
SubScopeName.Map.add subindex
(List.fold_left
(fun acc (var_ctx, dvar) ->
ScopeVarMap.add var_ctx.scope_var_name
ScopeVar.Map.add var_ctx.scope_var_name
(dvar, var_ctx.scope_var_typ, var_ctx.scope_var_io)
acc)
ScopeVarMap.empty all_subscope_output_vars_dcalc)
ScopeVar.Map.empty all_subscope_output_vars_dcalc)
ctx.subscope_vars;
} )
| Assertion e ->
@ -707,7 +708,7 @@ let translate_rule
let translate_rules
(ctx : 'm ctx)
(rules : 'm Scopelang.Ast.rule list)
((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info)
((sigma_name, pos_sigma) : Uid.MarkedString.info)
(mark : 'm mark)
(scope_sig : 'm scope_sig_ctx) :
'm Ast.expr scope_body_expr Bindlib.box * 'm ctx =
@ -723,15 +724,15 @@ let translate_rules
in
let return_exp =
Expr.estruct scope_sig.scope_sig_output_struct
(ScopeVarMap.fold
(ScopeVar.Map.fold
(fun var (dcalc_var, _, io) acc ->
if Marked.unmark io.Desugared.Ast.io_output then
let field = ScopeVarMap.find var scope_sig.scope_sig_out_fields in
StructFieldMap.add field
let field = ScopeVar.Map.find var scope_sig.scope_sig_out_fields in
StructField.Map.add field
(Expr.make_var dcalc_var (mark_tany mark pos_sigma))
acc
else acc)
new_ctx.scope_vars StructFieldMap.empty)
new_ctx.scope_vars StructField.Map.empty)
(mark_tany mark pos_sigma)
in
( scope_lets
@ -748,7 +749,7 @@ let translate_scope_decl
(sigma : 'm Scopelang.Ast.scope_decl) :
'm Ast.expr scope_body Bindlib.box * struct_ctx =
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 = ScopeName.Map.find sigma.scope_decl_name sctx in
let scope_variables = scope_sig.scope_sig_local_vars in
let ctx =
(* the context must be initialized for fresh variables for all only-input
@ -762,7 +763,7 @@ let translate_scope_decl
{
ctx with
scope_vars =
ScopeVarMap.add scope_var.scope_var_name
ScopeVar.Map.add scope_var.scope_var_name
( scope_var_dcalc,
scope_var.scope_var_typ,
scope_var.scope_var_io )
@ -784,7 +785,7 @@ let translate_scope_decl
List.map
(fun var_ctx ->
let dcalc_x, _, _ =
ScopeVarMap.find var_ctx.scope_var_name ctx.scope_vars
ScopeVar.Map.find var_ctx.scope_var_name ctx.scope_vars
in
var_ctx, dcalc_x)
scope_variables
@ -813,7 +814,8 @@ let translate_scope_decl
List.fold_right
(fun (var_ctx, v) next ->
let field =
(ScopeVarMap.find var_ctx.scope_var_name scope_sig.scope_sig_in_fields)
(ScopeVar.Map.find var_ctx.scope_var_name
scope_sig.scope_sig_in_fields)
.scope_input_name
in
Bindlib.box_apply2
@ -840,12 +842,14 @@ let translate_scope_decl
(fun acc (var_ctx, _) ->
let var = var_ctx.scope_var_name in
let field =
(ScopeVarMap.find var scope_sig.scope_sig_in_fields).scope_input_name
(ScopeVar.Map.find var scope_sig.scope_sig_in_fields).scope_input_name
in
StructFieldMap.add field (input_var_typ var_ctx) acc)
StructFieldMap.empty scope_input_variables
StructField.Map.add field (input_var_typ var_ctx) acc)
StructField.Map.empty scope_input_variables
in
let new_struct_ctx =
StructName.Map.singleton scope_input_struct_name field_map
in
let new_struct_ctx = StructMap.singleton scope_input_struct_name field_map in
( Bindlib.box_apply
(fun scope_body_expr ->
{
@ -865,14 +869,14 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
in
let decl_ctx = prgm.program_ctx in
let sctx : 'm scope_sigs_ctx =
ScopeMap.mapi
ScopeName.Map.mapi
(fun scope_name scope ->
let scope_dvar =
Var.make
(Marked.unmark
(ScopeName.get_info scope.Scopelang.Ast.scope_decl_name))
in
let scope_return = ScopeMap.find scope_name decl_ctx.ctx_scopes in
let scope_return = ScopeName.Map.find scope_name decl_ctx.ctx_scopes in
let scope_input_var =
Var.make (Marked.unmark (ScopeName.get_info scope_name) ^ "_in")
in
@ -883,7 +887,7 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
(ScopeName.get_info scope_name))
in
let scope_sig_in_fields =
ScopeVarMap.filter_map
ScopeVar.Map.filter_map
(fun dvar (typ, vis) ->
match Marked.unmark vis.Desugared.Ast.io_input with
| NoInput -> None
@ -893,7 +897,7 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
Some
{
scope_input_name =
StructFieldName.fresh (s, Marked.get_mark info);
StructField.fresh (s, Marked.get_mark info);
scope_input_io = vis.Desugared.Ast.io_input;
scope_input_typ = Marked.unmark typ;
})
@ -908,7 +912,7 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
scope_var_typ = Marked.unmark tau;
scope_var_io = vis;
})
(ScopeVarMap.bindings scope.scope_sig);
(ScopeVar.Map.bindings scope.scope_sig);
scope_sig_scope_var = scope_dvar;
scope_sig_input_var = scope_input_var;
scope_sig_input_struct = scope_input_struct_name;
@ -923,17 +927,17 @@ let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
order, then the chained scopes aggregated from the right. *)
let rec translate_scopes decl_ctx = function
| scope_name :: next_scopes ->
let scope = ScopeMap.find scope_name prgm.program_scopes in
let scope = ScopeName.Map.find scope_name prgm.program_scopes in
let scope_body, scope_in_struct =
translate_scope_decl decl_ctx.ctx_structs decl_ctx.ctx_enums sctx
scope_name scope
in
let dvar = (ScopeMap.find scope_name sctx).scope_sig_scope_var in
let dvar = (ScopeName.Map.find scope_name sctx).scope_sig_scope_var in
let decl_ctx =
{
decl_ctx with
ctx_structs =
StructMap.union
StructName.Map.union
(fun _ _ -> assert false (* should not happen *))
decl_ctx.ctx_structs scope_in_struct;
}

View File

@ -16,7 +16,7 @@
(** Reference interpreter for the default calculus *)
open Utils
open Catala_utils
open Shared_ast
module Runtime = Runtime_ocaml.Runtime
@ -31,7 +31,7 @@ let log_indent = ref 0
let rec evaluate_operator
(ctx : decl_ctx)
(op : operator)
(op : dcalc operator)
(pos : Pos.t)
(args : 'm Ast.expr list) : 'm Ast.naked_expr =
(* Try to apply [div] and if a [Division_by_zero] exceptions is catched, use
@ -180,7 +180,7 @@ let rec evaluate_operator
ELit
(LBool
(StructName.equal s1 s2
&& StructFieldMap.equal
&& StructField.Map.equal
(fun e1 e2 ->
match evaluate_operator ctx op pos [e1; e2] with
| ELit (LBool b) -> b
@ -342,8 +342,8 @@ and evaluate_expr (ctx : decl_ctx) (e : 'm Ast.expr) : 'm Ast.expr =
happen if the term was well-typed")
| EAbs _ | ELit _ | EOp _ -> e (* these are values *)
| EStruct { fields = es; name } ->
let new_es = StructFieldMap.map (evaluate_expr ctx) es in
if StructFieldMap.exists (fun _ e -> is_empty_error e) new_es then
let new_es = StructField.Map.map (evaluate_expr ctx) es in
if StructField.Map.exists (fun _ e -> is_empty_error e) new_es then
Marked.same_mark_as (ELit LEmptyError) e
else Marked.same_mark_as (EStruct { fields = new_es; name }) e
| EStructAccess { e = e1; name = s; field } -> (
@ -355,13 +355,13 @@ and evaluate_expr (ctx : decl_ctx) (e : 'm Ast.expr) : 'm Ast.expr =
[None, Expr.pos e; None, Expr.pos e1]
"Error during struct access: not the same structs (should not happen \
if the term was well-typed)";
match StructFieldMap.find_opt field es with
match StructField.Map.find_opt field es with
| Some e' -> e'
| None ->
Errors.raise_spanned_error (Expr.pos e1)
"Invalid field access %a in struct %a (should not happen if the term \
was well-typed)"
StructFieldName.format_t field StructName.format_t s)
StructField.format_t field StructName.format_t s)
| ELit LEmptyError -> Marked.same_mark_as (ELit LEmptyError) e
| _ ->
Errors.raise_spanned_error (Expr.pos e1)
@ -383,7 +383,7 @@ and evaluate_expr (ctx : decl_ctx) (e : 'm Ast.expr) : 'm Ast.expr =
"Error during match: two different enums found (should not happen if \
the term was well-typed)";
let es_n =
match EnumConstructorMap.find_opt cons es with
match EnumConstructor.Map.find_opt cons es with
| Some es_n -> es_n
| None ->
Errors.raise_spanned_error (Expr.pos e)
@ -499,9 +499,9 @@ let interpret_program :
the types of the scope arguments. For [context] arguments, we can provide
an empty thunked term. But for [input] arguments of another type, we
cannot provide anything so we have to fail. *)
let taus = StructMap.find s_in ctx.ctx_structs in
let taus = StructName.Map.find s_in ctx.ctx_structs in
let application_term =
StructFieldMap.map
StructField.Map.map
(fun ty ->
match Marked.unmark ty with
| TArrow (ty_in, ty_out) ->
@ -526,8 +526,8 @@ let interpret_program :
match Marked.unmark (evaluate_expr ctx (Expr.unbox to_interpret)) with
| EStruct { fields; _ } ->
List.map
(fun (fld, e) -> StructFieldName.get_info fld, e)
(StructFieldMap.bindings fields)
(fun (fld, e) -> StructField.get_info fld, e)
(StructField.Map.bindings fields)
| _ ->
Errors.raise_spanned_error (Expr.pos e)
"The interpretation of a program should always yield a struct \

View File

@ -16,7 +16,7 @@
(** Reference interpreter for the default calculus *)
open Utils
open Catala_utils
open Shared_ast
val evaluate_expr : decl_ctx -> 'm Ast.expr -> 'm Ast.expr

View File

@ -14,7 +14,7 @@
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
@ -80,7 +80,7 @@ let rec partial_evaluation (ctx : partial_evaluation_ctx) (e : 'm expr) :
| EMatch { e = EInj { e; name = name1; cons }, _; cases; name }
when EnumName.equal name name1 ->
(* iota reduction *)
EApp { f = EnumConstructorMap.find cons cases; args = [e] }
EApp { f = EnumConstructor.Map.find cons cases; args = [e] }
| EApp { f = EAbs { binder; _ }, _; args } ->
(* beta reduction *)
Marked.unmark (Bindlib.msubst binder (List.map fst args |> Array.of_list))

View File

@ -16,7 +16,7 @@
(** Abstract syntax tree of the desugared representation *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Names, Maps and Keys} *)
@ -178,7 +178,7 @@ type meta_assertion =
| VariesWith of unit * variation_typ Marked.pos option
type scope_def = {
scope_def_rules : rule RuleMap.t;
scope_def_rules : rule RuleName.Map.t;
scope_def_typ : typ;
scope_def_is_condition : bool;
scope_def_io : io;
@ -187,15 +187,18 @@ type scope_def = {
type var_or_states = WholeVar | States of StateName.t list
type scope = {
scope_vars : var_or_states ScopeVarMap.t;
scope_sub_scopes : ScopeName.t SubScopeMap.t;
scope_vars : var_or_states ScopeVar.Map.t;
scope_sub_scopes : ScopeName.t SubScopeName.Map.t;
scope_uid : ScopeName.t;
scope_defs : scope_def ScopeDefMap.t;
scope_assertions : assertion list;
scope_meta_assertions : meta_assertion list;
}
type program = { program_scopes : scope ScopeMap.t; program_ctx : decl_ctx }
type program = {
program_scopes : scope ScopeName.Map.t;
program_ctx : decl_ctx;
}
let rec locations_used e : LocationSet.t =
match e with
@ -208,7 +211,7 @@ let rec locations_used e : LocationSet.t =
(fun e -> LocationSet.union (locations_used e))
e LocationSet.empty
let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t =
let free_variables (def : rule RuleName.Map.t) : Pos.t ScopeDefMap.t =
let add_locs (acc : Pos.t ScopeDefMap.t) (locs : LocationSet.t) :
Pos.t ScopeDefMap.t =
LocationSet.fold
@ -224,7 +227,7 @@ let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t =
loc_pos acc)
locs acc
in
RuleMap.fold
RuleName.Map.fold
(fun _ rule acc ->
let locs =
LocationSet.union

View File

@ -16,7 +16,7 @@
(** Abstract syntax tree of the desugared representation *)
open Utils
open Catala_utils
open Shared_ast
(** Inside a scope, a definition can refer either to a scope def, or a subscope
@ -100,7 +100,7 @@ type io = {
(** Characterization of the input/output status of a scope variable. *)
type scope_def = {
scope_def_rules : rule RuleMap.t;
scope_def_rules : rule RuleName.Map.t;
scope_def_typ : typ;
scope_def_is_condition : bool;
scope_def_io : io;
@ -109,17 +109,20 @@ type scope_def = {
type var_or_states = WholeVar | States of StateName.t list
type scope = {
scope_vars : var_or_states ScopeVarMap.t;
scope_sub_scopes : ScopeName.t SubScopeMap.t;
scope_vars : var_or_states ScopeVar.Map.t;
scope_sub_scopes : ScopeName.t SubScopeName.Map.t;
scope_uid : ScopeName.t;
scope_defs : scope_def ScopeDefMap.t;
scope_assertions : assertion list;
scope_meta_assertions : meta_assertion list;
}
type program = { program_scopes : scope ScopeMap.t; program_ctx : decl_ctx }
type program = {
program_scopes : scope ScopeName.Map.t;
program_ctx : decl_ctx;
}
(** {1 Helpers} *)
val locations_used : expr -> LocationSet.t
val free_variables : rule RuleMap.t -> Pos.t ScopeDefMap.t
val free_variables : rule RuleName.Map.t -> Pos.t ScopeDefMap.t

View File

@ -17,7 +17,7 @@
(** Scope dependencies computations using {{:http://ocamlgraph.lri.fr/}
OCamlgraph} *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Scope variables dependency graph} *)
@ -143,7 +143,7 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t =
let g = ScopeDependencies.empty in
(* Add all the vertices to the graph *)
let g =
ScopeVarMap.fold
ScopeVar.Map.fold
(fun (v : ScopeVar.t) var_or_state g ->
match var_or_state with
| Ast.WholeVar -> ScopeDependencies.add_vertex g (Vertex.Var (v, None))
@ -155,7 +155,7 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t =
scope.scope_vars g
in
let g =
SubScopeMap.fold
SubScopeName.Map.fold
(fun (v : SubScopeName.t) _ g ->
ScopeDependencies.add_vertex g (Vertex.SubScope v))
scope.scope_sub_scopes g
@ -229,10 +229,10 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t =
(** {2 Graph declaration} *)
module ExceptionVertex = struct
include RuleSet
include RuleName.Set
let hash (x : t) : int =
RuleSet.fold (fun r acc -> Int.logxor (RuleName.hash r) acc) x 0
RuleName.Set.fold (fun r acc -> Int.logxor (RuleName.hash r) acc) x 0
let equal x y = compare x y = 0
end
@ -263,7 +263,7 @@ type exception_edge = {
}
let build_exceptions_graph
(def : Ast.rule RuleMap.t)
(def : Ast.rule RuleName.Map.t)
(def_info : Ast.ScopeDef.t) : ExceptionsDependencies.t =
(* 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
@ -275,53 +275,55 @@ let build_exceptions_graph
(* 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
all the rules that are implicitly exceptions to rule [R]. *)
let exception_to_rule_implicit_labels : LabelName.t RuleMap.t =
RuleMap.fold
let exception_to_rule_implicit_labels : LabelName.t RuleName.Map.t =
RuleName.Map.fold
(fun _ rule_from exception_to_rule_implicit_labels ->
match rule_from.Ast.rule_exception with
| Ast.ExceptionToRule (rule_to, _) -> (
match RuleMap.find_opt rule_to exception_to_rule_implicit_labels with
match
RuleName.Map.find_opt rule_to exception_to_rule_implicit_labels
with
| Some _ ->
(* we already created the label *) exception_to_rule_implicit_labels
| None ->
RuleMap.add rule_to
RuleName.Map.add rule_to
(LabelName.fresh
( "exception_to_" ^ Marked.unmark (RuleName.get_info rule_to),
Pos.no_pos ))
exception_to_rule_implicit_labels)
| _ -> exception_to_rule_implicit_labels)
def RuleMap.empty
def RuleName.Map.empty
in
(* 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
rules that are implicitly exceptions to rule [foo_l]. *)
let exception_to_label_implicit_labels : LabelName.t LabelMap.t =
RuleMap.fold
let exception_to_label_implicit_labels : LabelName.t LabelName.Map.t =
RuleName.Map.fold
(fun _ rule_from
(exception_to_label_implicit_labels : LabelName.t LabelMap.t) ->
(exception_to_label_implicit_labels : LabelName.t LabelName.Map.t) ->
match rule_from.Ast.rule_exception with
| Ast.ExceptionToLabel (label_to, _) -> (
match
LabelMap.find_opt label_to exception_to_label_implicit_labels
LabelName.Map.find_opt label_to exception_to_label_implicit_labels
with
| Some _ ->
(* we already created the label *)
exception_to_label_implicit_labels
| None ->
LabelMap.add label_to
LabelName.Map.add label_to
(LabelName.fresh
( "exception_to_" ^ Marked.unmark (LabelName.get_info label_to),
Pos.no_pos ))
exception_to_label_implicit_labels)
| _ -> exception_to_label_implicit_labels)
def LabelMap.empty
def LabelName.Map.empty
in
(* 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
DAG. *)
let label_to_rule_sets =
RuleMap.fold
RuleName.Map.fold
(fun rule_name rule rule_sets ->
let label_of_rule =
match rule.Ast.rule_label with
@ -330,23 +332,23 @@ let build_exceptions_graph
match rule.Ast.rule_exception with
| BaseCase -> base_case_implicit_label
| ExceptionToRule (r, _) ->
RuleMap.find r exception_to_rule_implicit_labels
RuleName.Map.find r exception_to_rule_implicit_labels
| ExceptionToLabel (l', _) ->
LabelMap.find l' exception_to_label_implicit_labels)
LabelName.Map.find l' exception_to_label_implicit_labels)
in
LabelMap.update label_of_rule
LabelName.Map.update label_of_rule
(fun rule_set ->
match rule_set with
| None -> Some (RuleSet.singleton rule_name)
| Some rule_set -> Some (RuleSet.add rule_name rule_set))
| None -> Some (RuleName.Set.singleton rule_name)
| Some rule_set -> Some (RuleName.Set.add rule_name rule_set))
rule_sets)
def LabelMap.empty
def LabelName.Map.empty
in
let find_label_of_rule (r : RuleName.t) : LabelName.t =
fst
(LabelMap.choose
(LabelMap.filter
(fun _ rule_set -> RuleSet.mem r rule_set)
(LabelName.Map.choose
(LabelName.Map.filter
(fun _ rule_set -> RuleName.Set.mem r rule_set)
label_to_rule_sets))
in
(* Next, we collect the exception edges between those groups of rules referred
@ -354,7 +356,7 @@ let build_exceptions_graph
edges as they are declared at each rule but should be the same for all the
rules of the same group. *)
let exception_edges : exception_edge list =
RuleMap.fold
RuleName.Map.fold
(fun rule_name rule exception_edges ->
let label_from = find_label_of_rule rule_name in
let label_to_and_pos =
@ -414,7 +416,7 @@ let build_exceptions_graph
in
(* We've got the vertices and the edges, let's build the graph! *)
let g =
LabelMap.fold
LabelName.Map.fold
(fun _label rule_set g -> ExceptionsDependencies.add_vertex g rule_set)
label_to_rule_sets ExceptionsDependencies.empty
in
@ -423,9 +425,11 @@ let build_exceptions_graph
List.fold_left
(fun g edge ->
let rule_group_from =
LabelMap.find edge.label_from label_to_rule_sets
LabelName.Map.find edge.label_from label_to_rule_sets
in
let rule_group_to =
LabelName.Map.find edge.label_to label_to_rule_sets
in
let rule_group_to = LabelMap.find edge.label_to label_to_rule_sets in
let edge =
ExceptionsDependencies.E.create rule_group_from edge.edge_positions
rule_group_to
@ -445,8 +449,8 @@ let check_for_exception_cycle (g : ExceptionsDependencies.t) : unit =
let spans =
List.flatten
(List.map
(fun (vs : RuleSet.t) ->
let v = RuleSet.choose vs in
(fun (vs : RuleName.Set.t) ->
let v = RuleName.Set.choose vs in
let var_str, var_info =
Format.asprintf "%a" RuleName.format_t v, RuleName.get_info v
in

View File

@ -17,7 +17,7 @@
(** Scope dependencies computations using {{:http://ocamlgraph.lri.fr/}
OCamlgraph} *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Scope variables dependency graph} *)
@ -72,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 ExceptionsDependencies :
Graph.Sig.P with type V.t = RuleSet.t and type E.label = EdgeExceptions.t
Graph.Sig.P with type V.t = RuleName.Set.t and type E.label = EdgeExceptions.t
val build_exceptions_graph :
Ast.rule RuleMap.t -> Ast.ScopeDef.t -> ExceptionsDependencies.t
Ast.rule RuleName.Map.t -> Ast.ScopeDef.t -> ExceptionsDependencies.t
val check_for_exception_cycle : ExceptionsDependencies.t -> unit

View File

@ -0,0 +1,78 @@
(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 Inria, contributor:
Louis Gesbert <louis.gesbert@inria.fr>
Licensed under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance with the License. You may obtain a copy of
the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)
open Shared_ast
open Ast
let expr ctx env e =
(* The typer takes care of disambiguating: this consists in: - ensuring
[EAbs.tys] doesn't contain any [TAny] - [EDStructAccess.name_opt] is always
[Some] *)
(* Intermediate unboxings are fine since the last [untype] will rebox in
depth *)
Typing.check_expr ctx ~env (Expr.unbox e)
let rule ctx env rule =
let env =
match rule.rule_parameter with
| None -> env
| Some (v, ty) -> Typing.Env.add_var v ty env
in
(* Note: we could use the known rule type here to direct typing. We choose not
to because it shouldn't be needed for disambiguation, and we prefer to
focus on local type errors first. *)
{
rule with
rule_just = expr ctx env rule.rule_just;
rule_cons = expr ctx env rule.rule_cons;
}
let scope ctx env scope =
let env = Typing.Env.open_scope scope.scope_uid env in
let scope_defs =
ScopeDefMap.map
(fun def ->
let scope_def_rules =
(* Note: ordering in file order might be better for error reporting ?
When we gather errors, the ordering could be done afterwards,
though *)
RuleName.Map.map (rule ctx env) def.scope_def_rules
in
{ def with scope_def_rules })
scope.scope_defs
in
let scope_assertions = List.map (expr ctx env) scope.scope_assertions in
{ scope with scope_defs; scope_assertions }
let program prg =
let env =
ScopeName.Map.fold
(fun scope_name scope env ->
let vars =
ScopeDefMap.fold
(fun var def vars ->
match var with
| Var (v, _states) -> ScopeVar.Map.add v def.scope_def_typ vars
| SubScopeVar _ -> vars)
scope.scope_defs ScopeVar.Map.empty
in
Typing.Env.add_scope scope_name ~vars env)
prg.program_scopes Typing.Env.empty
in
let program_scopes =
ScopeName.Map.map (scope prg.program_ctx env) prg.program_scopes
in
{ prg with program_scopes }

View File

@ -0,0 +1,24 @@
(* This file is part of the Catala compiler, a specification language for tax
and social benefits computation rules. Copyright (C) 2020 Inria, contributor:
Louis Gesbert <louis.gesbert@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. *)
(** This module does local typing in order to fill some missing type information
in the AST:
- it fills the types of arguments in [EAbs] nodes, (untyped ones are
inserted during desugaring, e.g. by `let-in` constructs),
- it resolves the structure names of [EDStructAccess] nodes. *)
val program : Ast.program -> Ast.program

View File

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

View File

@ -15,7 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
module SurfacePrint = Surface.Print
open Shared_ast
module Runtime = Runtime_ocaml.Runtime
@ -27,15 +27,15 @@ module Runtime = Runtime_ocaml.Runtime
(** {1 Translating expressions} *)
let translate_op_kind (k : Surface.Ast.op_kind) : op_kind =
let translate_op_kind (k : Surface.Ast.op_kind) : desugared op_kind =
match k with
| KInt -> KInt
| KDec -> KRat
| KMoney -> KMoney
| KDate -> KDate
| KDuration -> KDuration
| Surface.Ast.KInt -> KInt
| Surface.Ast.KDec -> KRat
| Surface.Ast.KMoney -> KMoney
| Surface.Ast.KDate -> KDate
| Surface.Ast.KDuration -> KDuration
let translate_binop (op : Surface.Ast.binop) : binop =
let translate_binop (op : Surface.Ast.binop) : desugared binop =
match op with
| And -> And
| Or -> Or
@ -52,7 +52,7 @@ let translate_binop (op : Surface.Ast.binop) : binop =
| Neq -> Neq
| Concat -> Concat
let translate_unop (op : Surface.Ast.unop) : unop =
let translate_unop (op : Surface.Ast.unop) : desugared unop =
match op with Not -> Not | Minus l -> Minus (translate_op_kind l)
let disambiguate_constructor
@ -67,10 +67,7 @@ let disambiguate_constructor
"The deep pattern matching syntactic sugar is not yet supported"
in
let possible_c_uids =
try
Name_resolution.IdentMap.find
(Marked.unmark constructor)
ctxt.constructor_idmap
try IdentName.Map.find (Marked.unmark constructor) ctxt.constructor_idmap
with Not_found ->
Errors.raise_spanned_error
(Marked.get_mark constructor)
@ -79,7 +76,7 @@ let disambiguate_constructor
in
match enum with
| None ->
if EnumMap.cardinal possible_c_uids > 1 then
if EnumName.Map.cardinal possible_c_uids > 1 then
Errors.raise_spanned_error
(Marked.get_mark constructor)
"This constructor name is ambiguous, it can belong to %a. Disambiguate \
@ -88,14 +85,14 @@ let disambiguate_constructor
~pp_sep:(fun fmt () -> Format.fprintf fmt " or ")
(fun fmt (s_name, _) ->
Format.fprintf fmt "%a" EnumName.format_t s_name))
(EnumMap.bindings possible_c_uids);
EnumMap.choose possible_c_uids
(EnumName.Map.bindings possible_c_uids);
EnumName.Map.choose possible_c_uids
| Some enum -> (
try
(* The path is fully qualified *)
let e_uid = Name_resolution.get_enum ctxt enum in
try
let c_uid = EnumMap.find e_uid possible_c_uids in
let c_uid = EnumName.Map.find e_uid possible_c_uids in
e_uid, c_uid
with Not_found ->
Errors.raise_spanned_error pos "Enum %s does not contain case %s"
@ -114,7 +111,7 @@ let rec translate_expr
(inside_definition_of : Ast.ScopeDef.t Marked.pos option)
(ctxt : Name_resolution.context)
(expr : Surface.Ast.expression Marked.pos) : Ast.expr boxed =
let scope_ctxt = ScopeMap.find scope ctxt.scopes in
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
let rec_helper = translate_expr scope inside_definition_of ctxt in
let pos = Marked.get_mark expr in
let emark = Untyped { pos } in
@ -130,7 +127,7 @@ let rec translate_expr
disambiguate_constructor ctxt constructors pos_pattern
in
let cases =
EnumConstructorMap.mapi
EnumConstructor.Map.mapi
(fun c_uid' tau ->
if EnumConstructor.compare c_uid c_uid' <> 0 then
let nop_var = Var.make "_" in
@ -143,7 +140,7 @@ let rec translate_expr
in
let e2 = translate_expr scope inside_definition_of ctxt e2 in
Expr.make_abs [| binding_var |] e2 [tau] pos)
(EnumMap.find enum_uid ctxt.enums)
(EnumName.Map.find enum_uid ctxt.enums)
in
Expr.ematch
(translate_expr scope inside_definition_of ctxt e1_sub)
@ -204,15 +201,15 @@ let rec translate_expr
| Ident x -> (
(* first we check whether this is a local var, then we resort to scope-wide
variables *)
match Name_resolution.IdentMap.find_opt x ctxt.local_var_idmap with
match IdentName.Map.find_opt x ctxt.local_var_idmap with
| None -> (
match Name_resolution.IdentMap.find_opt x scope_ctxt.var_idmap with
match IdentName.Map.find_opt x scope_ctxt.var_idmap with
| Some (ScopeVar uid) ->
(* If the referenced variable has states, then here are the rules to
desambiguate. In general, only the last state can be referenced.
Except if defining a state of the same variable, then it references
the previous state in the chain. *)
let x_sig = ScopeVarMap.find uid ctxt.var_typs in
let x_sig = ScopeVar.Map.find uid ctxt.var_typs in
let x_state =
match x_sig.var_sig_states_list with
| [] -> None
@ -258,7 +255,7 @@ let rec translate_expr
| Ident y when Name_resolution.is_subscope_uid scope ctxt y ->
(* In this case, y.x is a subscope variable *)
let subscope_uid, subscope_real_uid =
match Name_resolution.IdentMap.find y scope_ctxt.var_idmap with
match IdentName.Map.find y scope_ctxt.var_idmap with
| SubScope (sub, sc) -> sub, sc
| ScopeVar _ -> assert false
in
@ -269,53 +266,29 @@ let rec translate_expr
(SubScopeVar
(subscope_real_uid, (subscope_uid, pos), (subscope_var_uid, pos)))
emark
| _ -> (
| _ ->
(* 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 x_possible_structs =
try Name_resolution.IdentMap.find (Marked.unmark x) ctxt.field_idmap
with Not_found ->
Errors.raise_spanned_error (Marked.get_mark x)
"Unknown subscope or struct field name"
let str =
Option.map
(fun c ->
try Name_resolution.get_struct ctxt c
with Not_found ->
Errors.raise_spanned_error (Marked.get_mark c)
"Struct %s has not been defined before" (Marked.unmark c))
c
in
match c with
| None ->
(* No constructor name was specified *)
if StructMap.cardinal x_possible_structs > 1 then
Errors.raise_spanned_error (Marked.get_mark x)
"This struct field name is ambiguous, it can belong to %a. \
Disambiguate it by prefixing it with the struct name."
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt " or ")
(fun fmt (s_name, _) ->
Format.fprintf fmt "%a" StructName.format_t s_name))
(StructMap.bindings x_possible_structs)
else
let s_uid, f_uid = StructMap.choose x_possible_structs in
Expr.estructaccess e f_uid s_uid emark
| Some c_name -> (
try
let c_uid = Name_resolution.get_struct ctxt c_name in
try
let f_uid = StructMap.find c_uid x_possible_structs in
Expr.estructaccess e f_uid c_uid emark
with Not_found ->
Errors.raise_spanned_error pos "Struct %s does not contain field %s"
(Marked.unmark c_name) (Marked.unmark x)
with Not_found ->
Errors.raise_spanned_error (Marked.get_mark c_name)
"Struct %s has not been defined before" (Marked.unmark c_name))))
Expr.edstructaccess e (Marked.unmark x) str emark)
| FunCall (f, arg) -> Expr.eapp (rec_helper f) [rec_helper arg] emark
| ScopeCall (sc_name, fields) ->
let called_scope = Name_resolution.get_scope ctxt sc_name in
let scope_def = ScopeMap.find called_scope ctxt.scopes in
let scope_def = ScopeName.Map.find called_scope ctxt.scopes in
let in_struct =
List.fold_left
(fun acc (fld_id, e) ->
let var =
match
Name_resolution.IdentMap.find_opt (Marked.unmark fld_id)
scope_def.var_idmap
IdentName.Map.find_opt (Marked.unmark fld_id) scope_def.var_idmap
with
| Some (ScopeVar v) -> v
| Some (SubScope _) | None ->
@ -330,7 +303,7 @@ let rec translate_expr
"Scope %a has no input variable %a" ScopeName.format_t
called_scope Print.lit_style (Marked.unmark fld_id)
in
ScopeVarMap.update var
ScopeVar.Map.update var
(function
| None -> Some (rec_helper e)
| Some _ ->
@ -338,12 +311,13 @@ let rec translate_expr
"Duplicate definition of scope input variable '%a'"
ScopeVar.format_t var)
acc)
ScopeVarMap.empty fields
ScopeVar.Map.empty fields
in
Expr.escopecall called_scope in_struct emark
| LetIn (x, e1, e2) ->
let ctxt, v = Name_resolution.add_def_local_var ctxt (Marked.unmark x) in
let tau = TAny, Marked.get_mark x in
(* This type will be resolved in Scopelang.Desambiguation *)
let fn =
Expr.make_abs [| v |]
(translate_expr scope inside_definition_of ctxt e2)
@ -352,9 +326,7 @@ let rec translate_expr
Expr.eapp fn [rec_helper e1] emark
| StructLit (s_name, fields) ->
let s_uid =
match
Name_resolution.IdentMap.find_opt (Marked.unmark s_name) ctxt.typedefs
with
match IdentName.Map.find_opt (Marked.unmark s_name) ctxt.typedefs with
| Some (Name_resolution.TStruct s_uid) -> s_uid
| _ ->
Errors.raise_spanned_error (Marked.get_mark s_name)
@ -366,38 +338,36 @@ let rec translate_expr
(fun s_fields (f_name, f_e) ->
let f_uid =
try
StructMap.find s_uid
(Name_resolution.IdentMap.find (Marked.unmark f_name)
ctxt.field_idmap)
StructName.Map.find s_uid
(IdentName.Map.find (Marked.unmark f_name) ctxt.field_idmap)
with Not_found ->
Errors.raise_spanned_error (Marked.get_mark f_name)
"This identifier should refer to a field of struct %s"
(Marked.unmark s_name)
in
(match StructFieldMap.find_opt f_uid s_fields with
(match StructField.Map.find_opt f_uid s_fields with
| None -> ()
| Some e_field ->
Errors.raise_multispanned_error
[None, Marked.get_mark f_e; None, Expr.pos e_field]
"The field %a has been defined twice:" StructFieldName.format_t
f_uid);
"The field %a has been defined twice:" StructField.format_t f_uid);
let f_e = translate_expr scope inside_definition_of ctxt f_e in
StructFieldMap.add f_uid f_e s_fields)
StructFieldMap.empty fields
StructField.Map.add f_uid f_e s_fields)
StructField.Map.empty fields
in
let expected_s_fields = StructMap.find s_uid ctxt.structs in
StructFieldMap.iter
let expected_s_fields = StructName.Map.find s_uid ctxt.structs in
StructField.Map.iter
(fun expected_f _ ->
if not (StructFieldMap.mem expected_f s_fields) then
if not (StructField.Map.mem expected_f s_fields) then
Errors.raise_spanned_error pos
"Missing field for structure %a: \"%a\"" StructName.format_t s_uid
StructFieldName.format_t expected_f)
StructField.format_t expected_f)
expected_s_fields;
Expr.estruct s_uid s_fields emark
| EnumInject (enum, (constructor, pos_constructor), payload) -> (
let possible_c_uids =
try Name_resolution.IdentMap.find constructor ctxt.constructor_idmap
try IdentName.Map.find constructor ctxt.constructor_idmap
with Not_found ->
Errors.raise_spanned_error pos_constructor
"The name of this constructor has not been defined before, maybe it \
@ -409,7 +379,7 @@ let rec translate_expr
| None ->
if
(* No constructor name was specified *)
EnumMap.cardinal possible_c_uids > 1
EnumName.Map.cardinal possible_c_uids > 1
then
Errors.raise_spanned_error pos_constructor
"This constructor name is ambiguous, it can belong to %a. \
@ -418,9 +388,9 @@ let rec translate_expr
~pp_sep:(fun fmt () -> Format.fprintf fmt " or ")
(fun fmt (s_name, _) ->
Format.fprintf fmt "%a" EnumName.format_t s_name))
(EnumMap.bindings possible_c_uids)
(EnumName.Map.bindings possible_c_uids)
else
let e_uid, c_uid = EnumMap.choose possible_c_uids in
let e_uid, c_uid = EnumName.Map.choose possible_c_uids in
let payload =
Option.map (translate_expr scope inside_definition_of ctxt) payload
in
@ -434,7 +404,7 @@ let rec translate_expr
(* The path has been fully qualified *)
let e_uid = Name_resolution.get_enum ctxt enum in
try
let c_uid = EnumMap.find e_uid possible_c_uids in
let c_uid = EnumName.Map.find e_uid possible_c_uids in
let payload =
Option.map (translate_expr scope inside_definition_of ctxt) payload
in
@ -468,13 +438,13 @@ let rec translate_expr
(Marked.get_mark pattern)
in
let cases =
EnumConstructorMap.mapi
EnumConstructor.Map.mapi
(fun c_uid' tau ->
let nop_var = Var.make "_" in
Expr.make_abs [| nop_var |]
(Expr.elit (LBool (EnumConstructor.compare c_uid c_uid' = 0)) emark)
[tau] pos)
(EnumMap.find enum_uid ctxt.enums)
(EnumName.Map.find enum_uid ctxt.enums)
in
Expr.ematch
(translate_expr scope inside_definition_of ctxt e1)
@ -535,10 +505,6 @@ let rec translate_expr
[TAny, pos]
pos
in
let f_pred_var = Var.make "predicate" in
let f_pred_var_e =
Expr.make_var f_pred_var (Untyped { pos = Marked.get_mark predicate })
in
let acc_var = Var.make "acc" in
let acc_var_e = Expr.make_var acc_var emark in
let item_var = Var.make "item" in
@ -548,8 +514,8 @@ let rec translate_expr
(Expr.eapp
(Expr.eop (Binop cmp_op) (Untyped { pos = pos_op' }))
[
Expr.eapp f_pred_var_e [acc_var_e] emark;
Expr.eapp f_pred_var_e [item_var_e] emark;
Expr.eapp f_pred [acc_var_e] emark;
Expr.eapp f_pred [item_var_e] emark;
]
emark)
acc_var_e item_var_e emark
@ -557,10 +523,7 @@ let rec translate_expr
let fold_f =
Expr.make_abs [| acc_var; item_var |] fold_body [TAny, pos; TAny, pos] pos
in
let fold =
Expr.eapp (Expr.eop (Ternop Fold) emark) [fold_f; init; collection] emark
in
Expr.make_let_in f_pred_var (TAny, pos) f_pred fold pos
Expr.eapp (Expr.eop (Ternop Fold) emark) [fold_f; init; collection] emark
| CollectionOp (op', param', collection, predicate) ->
let ctxt, param =
Name_resolution.add_def_local_var ctxt (Marked.unmark param')
@ -598,12 +561,12 @@ let rec translate_expr
Expr.make_var acc_var (Untyped { pos = Marked.get_mark param' })
in
let f_body =
let make_body (op : binop) =
let make_body (op : desugared binop) =
Expr.eapp (Expr.eop (Binop op) mark)
[acc; translate_expr scope inside_definition_of ctxt predicate]
emark
in
let make_extr_body (cmp_op : binop) (t : typ) =
let make_extr_body (cmp_op : desugared binop) (t : typ) =
let tmp_var = Var.make "tmp" in
let tmp =
Expr.make_var tmp_var (Untyped { pos = Marked.get_mark param' })
@ -743,7 +706,7 @@ and disambiguate_match_and_build_expression
(inside_definition_of : Ast.ScopeDef.t Marked.pos option)
(ctxt : Name_resolution.context)
(cases : Surface.Ast.match_case Marked.pos list) :
Ast.expr boxed EnumConstructorMap.t * EnumName.t =
Ast.expr boxed EnumConstructor.Map.t * EnumName.t =
let create_var = function
| None -> ctxt, Var.make "_"
| Some param ->
@ -758,8 +721,8 @@ and disambiguate_match_and_build_expression
e_binder =
Expr.eabs e_binder
[
EnumConstructorMap.find c_uid
(EnumMap.find e_uid ctxt.Name_resolution.enums);
EnumConstructor.Map.find c_uid
(EnumName.Map.find e_uid ctxt.Name_resolution.enums);
]
(Marked.get_mark case_body)
in
@ -785,7 +748,7 @@ and disambiguate_match_and_build_expression
case were matching constructors of enumeration %a"
EnumName.format_t e_uid EnumName.format_t e_uid'
in
(match EnumConstructorMap.find_opt c_uid cases_d with
(match EnumConstructor.Map.find_opt c_uid cases_d with
| None -> ()
| Some e_case ->
Errors.raise_multispanned_error
@ -799,7 +762,9 @@ and disambiguate_match_and_build_expression
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
EnumConstructorMap.add c_uid case_expr cases_d, Some e_uid, curr_index + 1
( EnumConstructor.Map.add c_uid case_expr cases_d,
Some e_uid,
curr_index + 1 )
| Surface.Ast.WildCard match_case_expr -> (
let nb_cases = List.length cases in
let raise_wildcard_not_last_case_err () =
@ -821,13 +786,13 @@ and disambiguate_match_and_build_expression
| Some e_uid ->
if curr_index < nb_cases - 1 then raise_wildcard_not_last_case_err ();
let missing_constructors =
EnumMap.find e_uid ctxt.Name_resolution.enums
|> EnumConstructorMap.filter_map (fun c_uid _ ->
match EnumConstructorMap.find_opt c_uid cases_d with
EnumName.Map.find e_uid ctxt.Name_resolution.enums
|> EnumConstructor.Map.filter_map (fun c_uid _ ->
match EnumConstructor.Map.find_opt c_uid cases_d with
| Some _ -> None
| None -> Some c_uid)
in
if EnumConstructorMap.is_empty missing_constructors then
if EnumConstructor.Map.is_empty missing_constructors then
Errors.format_spanned_warning case_pos
"Unreachable match case, all constructors of the enumeration %a \
are already specified"
@ -851,19 +816,19 @@ and disambiguate_match_and_build_expression
let e_binder = Expr.bind [| payload_var |] case_body in
(* For each missing cases, binds the wildcard payload. *)
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun c_uid _ (cases_d, e_uid_opt, curr_index) ->
let case_expr =
bind_case_body c_uid e_uid ctxt case_body e_binder
in
( EnumConstructorMap.add c_uid case_expr cases_d,
( EnumConstructor.Map.add c_uid case_expr cases_d,
e_uid_opt,
curr_index + 1 ))
missing_constructors
(cases_d, Some e_uid, curr_index))
in
let naked_expr, e_name, _ =
List.fold_left bind_match_cases (EnumConstructorMap.empty, None, 0) cases
List.fold_left bind_match_cases (EnumConstructor.Map.empty, None, 0) cases
in
naked_expr, Option.get e_name
[@@ocamlformat "wrap-comments=false"]
@ -934,8 +899,8 @@ let process_def
(ctxt : Name_resolution.context)
(prgm : Ast.program)
(def : Surface.Ast.definition) : Ast.program =
let scope : Ast.scope = ScopeMap.find scope_uid prgm.program_scopes in
let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in
let scope : Ast.scope = ScopeName.Map.find scope_uid prgm.program_scopes in
let scope_ctxt = ScopeName.Map.find scope_uid ctxt.scopes in
let def_key =
Name_resolution.get_def_key
(Marked.unmark def.definition_name)
@ -962,8 +927,7 @@ let process_def
match def.definition_label with
| Some (label_str, label_pos) ->
Ast.ExplicitlyLabeled
( Name_resolution.IdentMap.find label_str scope_def_ctxt.label_idmap,
label_pos )
(IdentName.Map.find label_str scope_def_ctxt.label_idmap, label_pos)
| None -> Ast.Unlabeled
in
let exception_situation =
@ -980,7 +944,7 @@ let process_def
| ExceptionToLabel label_str -> (
try
let label_id =
Name_resolution.IdentMap.find (Marked.unmark label_str)
IdentName.Map.find (Marked.unmark label_str)
scope_def_ctxt.label_idmap
in
ExceptionToLabel (label_id, Marked.get_mark label_str)
@ -994,7 +958,7 @@ let process_def
{
scope_def with
scope_def_rules =
RuleMap.add rule_name
RuleName.Map.add rule_name
(process_default new_ctxt scope_uid
(def_key, Marked.get_mark def.definition_name)
rule_name param_uid precond exception_situation label_situation
@ -1009,7 +973,8 @@ let process_def
in
{
prgm with
program_scopes = ScopeMap.add scope_uid scope_updated prgm.program_scopes;
program_scopes =
ScopeName.Map.add scope_uid scope_updated prgm.program_scopes;
}
(** Translates a {!type: Surface.Ast.rule} from the surface language *)
@ -1029,7 +994,7 @@ let process_assert
(ctxt : Name_resolution.context)
(prgm : Ast.program)
(ass : Surface.Ast.assertion) : Ast.program =
let scope : Ast.scope = ScopeMap.find scope_uid prgm.program_scopes in
let scope : Ast.scope = ScopeName.Map.find scope_uid prgm.program_scopes in
let ass =
translate_expr scope_uid None ctxt
(match ass.Surface.Ast.assertion_condition with
@ -1055,7 +1020,7 @@ let process_assert
in
{
prgm with
program_scopes = ScopeMap.add scope_uid new_scope prgm.program_scopes;
program_scopes = ScopeName.Map.add scope_uid new_scope prgm.program_scopes;
}
(** Translates a surface definition, rule or assertion *)
@ -1080,7 +1045,7 @@ let check_unlabeled_exception
(scope : ScopeName.t)
(ctxt : Name_resolution.context)
(item : Surface.Ast.scope_use_item Marked.pos) : unit =
let scope_ctxt = ScopeMap.find scope ctxt.scopes in
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
match Marked.unmark item with
| Surface.Ast.Rule _ | Surface.Ast.Definition _ -> (
let def_key, exception_to =
@ -1129,7 +1094,7 @@ let process_scope_use
let scope_uid = Name_resolution.get_scope ctxt use.scope_use_name in
(* Make sure the scope exists *)
let prgm =
match ScopeMap.find_opt scope_uid prgm.program_scopes with
match ScopeName.Map.find_opt scope_uid prgm.program_scopes with
| Some _ -> prgm
| None -> assert false
(* should not happen *)
@ -1155,21 +1120,20 @@ let attribute_to_io (attr : Surface.Ast.scope_decl_context_io) : Ast.io =
let init_scope_defs
(ctxt : Name_resolution.context)
(scope_idmap :
Name_resolution.scope_var_or_subscope Name_resolution.IdentMap.t) :
(scope_idmap : Name_resolution.scope_var_or_subscope IdentName.Map.t) :
Ast.scope_def Ast.ScopeDefMap.t =
(* Initializing the definitions of all scopes and subscope vars, with no rules
yet inside *)
let add_def _ v scope_def_map =
match v with
| Name_resolution.ScopeVar v -> (
let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in
let v_sig = ScopeVar.Map.find v ctxt.Name_resolution.var_typs in
match v_sig.var_sig_states_list with
| [] ->
let def_key = Ast.ScopeDef.Var (v, None) in
Ast.ScopeDefMap.add def_key
{
Ast.scope_def_rules = RuleMap.empty;
Ast.scope_def_rules = RuleName.Map.empty;
Ast.scope_def_typ = v_sig.var_sig_typ;
Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
Ast.scope_def_io = attribute_to_io v_sig.var_sig_io;
@ -1182,7 +1146,7 @@ let init_scope_defs
let def_key = Ast.ScopeDef.Var (v, Some state) in
let def =
{
Ast.scope_def_rules = RuleMap.empty;
Ast.scope_def_rules = RuleName.Map.empty;
Ast.scope_def_typ = v_sig.var_sig_typ;
Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
Ast.scope_def_io =
@ -1209,23 +1173,23 @@ let init_scope_defs
scope_def)
| Name_resolution.SubScope (v0, subscope_uid) ->
let sub_scope_def =
ScopeMap.find subscope_uid ctxt.Name_resolution.scopes
ScopeName.Map.find subscope_uid ctxt.Name_resolution.scopes
in
Name_resolution.IdentMap.fold
IdentName.Map.fold
(fun _ v scope_def_map ->
match v with
| Name_resolution.SubScope _ -> scope_def_map
| Name_resolution.ScopeVar v ->
(* TODO: shouldn't we ignore internal variables too at this point
? *)
let v_sig = ScopeVarMap.find v ctxt.Name_resolution.var_typs in
let v_sig = ScopeVar.Map.find v ctxt.Name_resolution.var_typs in
let def_key =
Ast.ScopeDef.SubScopeVar
(v0, v, Marked.get_mark (ScopeVar.get_info v))
in
Ast.ScopeDefMap.add def_key
{
Ast.scope_def_rules = RuleMap.empty;
Ast.scope_def_rules = RuleName.Map.empty;
Ast.scope_def_typ = v_sig.var_sig_typ;
Ast.scope_def_is_condition = v_sig.var_sig_is_condition;
Ast.scope_def_io = attribute_to_io v_sig.var_sig_io;
@ -1233,7 +1197,7 @@ let init_scope_defs
scope_def_map)
sub_scope_def.Name_resolution.var_idmap scope_def_map
in
Name_resolution.IdentMap.fold add_def scope_idmap Ast.ScopeDefMap.empty
IdentName.Map.fold add_def scope_idmap Ast.ScopeDefMap.empty
(** Main function of this module *)
let translate_program
@ -1241,28 +1205,28 @@ let translate_program
(prgm : Surface.Ast.program) : Ast.program =
let empty_prgm =
let program_scopes =
ScopeMap.mapi
ScopeName.Map.mapi
(fun s_uid s_context ->
let scope_vars =
Name_resolution.IdentMap.fold
IdentName.Map.fold
(fun _ v acc ->
match v with
| Name_resolution.SubScope _ -> acc
| Name_resolution.ScopeVar v -> (
let v_sig = ScopeVarMap.find v ctxt.var_typs in
let v_sig = ScopeVar.Map.find v ctxt.var_typs in
match v_sig.var_sig_states_list with
| [] -> ScopeVarMap.add v Ast.WholeVar acc
| states -> ScopeVarMap.add v (Ast.States states) acc))
s_context.Name_resolution.var_idmap ScopeVarMap.empty
| [] -> ScopeVar.Map.add v Ast.WholeVar acc
| states -> ScopeVar.Map.add v (Ast.States states) acc))
s_context.Name_resolution.var_idmap ScopeVar.Map.empty
in
let scope_sub_scopes =
Name_resolution.IdentMap.fold
IdentName.Map.fold
(fun _ v acc ->
match v with
| Name_resolution.ScopeVar _ -> acc
| Name_resolution.SubScope (sub_var, sub_scope) ->
SubScopeMap.add sub_var sub_scope acc)
s_context.Name_resolution.var_idmap SubScopeMap.empty
SubScopeName.Map.add sub_var sub_scope acc)
s_context.Name_resolution.var_idmap SubScopeName.Map.empty
in
{
Ast.scope_vars;
@ -1280,13 +1244,14 @@ let translate_program
ctx_structs = ctxt.Name_resolution.structs;
ctx_enums = ctxt.Name_resolution.enums;
ctx_scopes =
Name_resolution.IdentMap.fold
IdentName.Map.fold
(fun _ def acc ->
match def with
| Name_resolution.TScope (scope, scope_out_struct) ->
ScopeMap.add scope scope_out_struct acc
ScopeName.Map.add scope scope_out_struct acc
| _ -> acc)
ctxt.Name_resolution.typedefs ScopeMap.empty;
ctxt.Name_resolution.typedefs ScopeName.Map.empty;
ctx_struct_fields = ctxt.Name_resolution.field_idmap;
};
Ast.program_scopes;
}

View File

@ -18,22 +18,18 @@
(** Builds a context that allows for mapping each name to a precise uid, taking
lexical scopes into account *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Name resolution context} *)
type ident = string
module IdentMap : Map.S with type key = String.t = Map.Make (String)
type unique_rulename =
| Ambiguous of Pos.t list
| Unique of RuleName.t Marked.pos
type scope_def_context = {
default_exception_rulename : unique_rulename option;
label_idmap : LabelName.t IdentMap.t;
label_idmap : LabelName.t IdentName.Map.t;
}
type scope_var_or_subscope =
@ -41,26 +37,26 @@ type scope_var_or_subscope =
| SubScope of SubScopeName.t * ScopeName.t
type scope_context = {
var_idmap : scope_var_or_subscope IdentMap.t;
var_idmap : scope_var_or_subscope IdentName.Map.t;
(** All variables, including scope variables and subscopes *)
scope_defs_contexts : scope_def_context Ast.ScopeDefMap.t;
(** What is the default rule to refer to for unnamed exceptions, if any *)
sub_scopes : ScopeSet.t;
sub_scopes : ScopeName.Set.t;
(** Other scopes referred to by this scope. Used for dependency analysis *)
}
(** Inside a scope, we distinguish between the variables and the subscopes. *)
type struct_context = typ StructFieldMap.t
type struct_context = typ StructField.Map.t
(** Types of the fields of a struct *)
type enum_context = typ EnumConstructorMap.t
type enum_context = typ EnumConstructor.Map.t
(** Types of the payloads of the cases of an enum *)
type var_sig = {
var_sig_typ : typ;
var_sig_is_condition : bool;
var_sig_io : Surface.Ast.scope_decl_context_io;
var_sig_states_idmap : StateName.t IdentMap.t;
var_sig_states_idmap : StateName.t IdentName.Map.t;
var_sig_states_list : StateName.t list;
}
@ -73,21 +69,22 @@ type typedef =
(** Implicitly defined output struct *)
type context = {
local_var_idmap : Ast.expr Var.t IdentMap.t;
local_var_idmap : Ast.expr Var.t IdentName.Map.t;
(** Inside a definition, local variables can be introduced by functions
arguments or pattern matching *)
typedefs : typedef IdentMap.t;
typedefs : typedef IdentName.Map.t;
(** Gathers the names of the scopes, structs and enums *)
field_idmap : StructFieldName.t StructMap.t IdentMap.t;
field_idmap : StructField.t StructName.Map.t IdentName.Map.t;
(** The names of the struct fields. Names of fields can be shared between
different structs *)
constructor_idmap : EnumConstructor.t EnumMap.t IdentMap.t;
constructor_idmap : EnumConstructor.t EnumName.Map.t IdentName.Map.t;
(** The names of the enum constructors. Constructor names can be shared
between different enums *)
scopes : scope_context ScopeMap.t; (** For each scope, its context *)
structs : struct_context StructMap.t; (** For each struct, its context *)
enums : enum_context EnumMap.t; (** For each enum, its context *)
var_typs : var_sig ScopeVarMap.t;
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
structs : struct_context StructName.Map.t;
(** For each struct, its context *)
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
var_typs : var_sig ScopeVar.Map.t;
(** The signatures of each scope variable declared *)
}
(** Main context used throughout {!module: Surface.Desugaring} *)
@ -101,30 +98,30 @@ let raise_unsupported_feature (msg : string) (pos : Pos.t) =
(** Function to call whenever an identifier used somewhere has not been declared
in the program previously *)
let raise_unknown_identifier (msg : string) (ident : ident Marked.pos) =
let raise_unknown_identifier (msg : string) (ident : IdentName.t Marked.pos) =
Errors.raise_spanned_error (Marked.get_mark ident)
"\"%s\": unknown identifier %s"
(Utils.Cli.with_style [ANSITerminal.yellow] "%s" (Marked.unmark ident))
(Cli.with_style [ANSITerminal.yellow] "%s" (Marked.unmark ident))
msg
(** Gets the type associated to an uid *)
let get_var_typ (ctxt : context) (uid : ScopeVar.t) : typ =
(ScopeVarMap.find uid ctxt.var_typs).var_sig_typ
(ScopeVar.Map.find uid ctxt.var_typs).var_sig_typ
let is_var_cond (ctxt : context) (uid : ScopeVar.t) : bool =
(ScopeVarMap.find uid ctxt.var_typs).var_sig_is_condition
(ScopeVar.Map.find uid ctxt.var_typs).var_sig_is_condition
let get_var_io (ctxt : context) (uid : ScopeVar.t) :
Surface.Ast.scope_decl_context_io =
(ScopeVarMap.find uid ctxt.var_typs).var_sig_io
(ScopeVar.Map.find uid ctxt.var_typs).var_sig_io
(** Get the variable uid inside the scope given in argument *)
let get_var_uid
(scope_uid : ScopeName.t)
(ctxt : context)
((x, pos) : ident Marked.pos) : ScopeVar.t =
let scope = ScopeMap.find scope_uid ctxt.scopes in
match IdentMap.find_opt x scope.var_idmap with
((x, pos) : IdentName.t Marked.pos) : ScopeVar.t =
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
match IdentName.Map.find_opt x scope.var_idmap with
| Some (ScopeVar uid) -> uid
| _ ->
raise_unknown_identifier
@ -135,26 +132,26 @@ let get_var_uid
let get_subscope_uid
(scope_uid : ScopeName.t)
(ctxt : context)
((y, pos) : ident Marked.pos) : SubScopeName.t =
let scope = ScopeMap.find scope_uid ctxt.scopes in
match IdentMap.find_opt y scope.var_idmap with
((y, pos) : IdentName.t Marked.pos) : SubScopeName.t =
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
match IdentName.Map.find_opt y scope.var_idmap with
| Some (SubScope (sub_uid, _sub_id)) -> sub_uid
| _ -> raise_unknown_identifier "for a subscope of this scope" (y, pos)
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
subscopes of [scope_uid]. *)
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : ident) :
bool =
let scope = ScopeMap.find scope_uid ctxt.scopes in
match IdentMap.find_opt y scope.var_idmap with
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : IdentName.t)
: bool =
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
match IdentName.Map.find_opt y scope.var_idmap with
| Some (SubScope _) -> true
| _ -> false
(** Checks if the var_uid belongs to the scope scope_uid *)
let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) :
bool =
let scope = ScopeMap.find scope_uid ctxt.scopes in
IdentMap.exists
let scope = ScopeName.Map.find scope_uid ctxt.scopes in
IdentName.Map.exists
(fun _ -> function
| ScopeVar var_uid -> ScopeVar.equal uid var_uid
| _ -> false)
@ -178,7 +175,7 @@ let is_def_cond (ctxt : context) (def : Ast.ScopeDef.t) : bool =
is_var_cond ctxt x
let get_enum ctxt id =
match IdentMap.find (Marked.unmark id) ctxt.typedefs with
match IdentName.Map.find (Marked.unmark id) ctxt.typedefs with
| TEnum id -> id
| TStruct sid ->
Errors.raise_multispanned_error
@ -199,7 +196,7 @@ let get_enum ctxt id =
(Marked.unmark id)
let get_struct ctxt id =
match IdentMap.find (Marked.unmark id) ctxt.typedefs with
match IdentName.Map.find (Marked.unmark id) ctxt.typedefs with
| TStruct id | TScope (_, { out_struct_name = id; _ }) -> id
| TEnum eid ->
Errors.raise_multispanned_error
@ -213,7 +210,7 @@ let get_struct ctxt id =
(Marked.unmark id)
let get_scope ctxt id =
match IdentMap.find (Marked.unmark id) ctxt.typedefs with
match IdentName.Map.find (Marked.unmark id) ctxt.typedefs with
| TScope (id, _) -> id
| TEnum eid ->
Errors.raise_multispanned_error
@ -242,8 +239,8 @@ let process_subscope_decl
(decl : Surface.Ast.scope_decl_context_scope) : context =
let name, name_pos = decl.scope_decl_context_scope_name in
let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in
let scope_ctxt = ScopeMap.find scope ctxt.scopes in
match IdentMap.find_opt subscope scope_ctxt.var_idmap with
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
match IdentName.Map.find_opt subscope scope_ctxt.var_idmap with
| Some use ->
let info =
match use with
@ -253,7 +250,7 @@ let process_subscope_decl
Errors.raise_multispanned_error
[Some "first use", Marked.get_mark info; Some "second use", s_pos]
"Subscope name \"%a\" already used"
(Utils.Cli.format_with_style [ANSITerminal.yellow])
(Cli.format_with_style [ANSITerminal.yellow])
subscope
| None ->
let sub_scope_uid = SubScopeName.fresh (name, name_pos) in
@ -264,13 +261,14 @@ let process_subscope_decl
{
scope_ctxt with
var_idmap =
IdentMap.add name
IdentName.Map.add name
(SubScope (sub_scope_uid, original_subscope_uid))
scope_ctxt.var_idmap;
sub_scopes = ScopeSet.add original_subscope_uid scope_ctxt.sub_scopes;
sub_scopes =
ScopeName.Set.add original_subscope_uid scope_ctxt.sub_scopes;
}
in
{ ctxt with scopes = ScopeMap.add scope scope_ctxt ctxt.scopes }
{ ctxt with scopes = ScopeName.Map.add scope scope_ctxt ctxt.scopes }
let is_type_cond ((typ, _) : Surface.Ast.typ) =
match typ with
@ -300,7 +298,7 @@ let rec process_base_typ
| Surface.Ast.Boolean -> TLit TBool, typ_pos
| Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos
| Surface.Ast.Named ident -> (
match IdentMap.find_opt ident ctxt.typedefs with
match IdentName.Map.find_opt ident ctxt.typedefs with
| Some (TStruct s_uid) -> TStruct s_uid, typ_pos
| Some (TEnum e_uid) -> TEnum e_uid, typ_pos
| Some (TScope (_, scope_str)) ->
@ -308,7 +306,7 @@ let rec process_base_typ
| None ->
Errors.raise_spanned_error typ_pos
"Unknown type \"%a\", not a struct or enum previously declared"
(Utils.Cli.format_with_style [ANSITerminal.yellow])
(Cli.format_with_style [ANSITerminal.yellow])
ident))
(** Process a type (function or not) *)
@ -329,8 +327,8 @@ let process_data_decl
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 name, pos = decl.scope_decl_context_item_name in
let scope_ctxt = ScopeMap.find scope ctxt.scopes in
match IdentMap.find_opt name scope_ctxt.var_idmap with
let scope_ctxt = ScopeName.Map.find scope ctxt.scopes in
match IdentName.Map.find_opt name scope_ctxt.var_idmap with
| Some use ->
let info =
match use with
@ -340,29 +338,29 @@ let process_data_decl
Errors.raise_multispanned_error
[Some "First use:", Marked.get_mark info; Some "Second use:", pos]
"Variable name \"%a\" already used"
(Utils.Cli.format_with_style [ANSITerminal.yellow])
(Cli.format_with_style [ANSITerminal.yellow])
name
| None ->
let uid = ScopeVar.fresh (name, pos) in
let scope_ctxt =
{
scope_ctxt with
var_idmap = IdentMap.add name (ScopeVar uid) scope_ctxt.var_idmap;
var_idmap = IdentName.Map.add name (ScopeVar uid) scope_ctxt.var_idmap;
}
in
let states_idmap, states_list =
List.fold_right
(fun state_id (states_idmap, states_list) ->
let state_uid = StateName.fresh state_id in
( IdentMap.add (Marked.unmark state_id) state_uid states_idmap,
( IdentName.Map.add (Marked.unmark state_id) state_uid states_idmap,
state_uid :: states_list ))
decl.scope_decl_context_item_states (IdentMap.empty, [])
decl.scope_decl_context_item_states (IdentName.Map.empty, [])
in
{
ctxt with
scopes = ScopeMap.add scope scope_ctxt ctxt.scopes;
scopes = ScopeName.Map.add scope scope_ctxt ctxt.scopes;
var_typs =
ScopeVarMap.add uid
ScopeVar.Map.add uid
{
var_sig_typ = data_typ;
var_sig_is_condition = is_cond;
@ -374,13 +372,14 @@ let process_data_decl
}
(** Adds a binding to the context *)
let add_def_local_var (ctxt : context) (name : ident) : context * Ast.expr Var.t
=
let add_def_local_var (ctxt : context) (name : IdentName.t) :
context * Ast.expr Var.t =
let local_var_uid = Var.make name in
let ctxt =
{
ctxt with
local_var_idmap = IdentMap.add name local_var_uid ctxt.local_var_idmap;
local_var_idmap =
IdentName.Map.add name local_var_uid ctxt.local_var_idmap;
}
in
ctxt, local_var_uid
@ -397,35 +396,33 @@ let process_struct_decl (ctxt : context) (sdecl : Surface.Ast.struct_decl) :
(Marked.unmark sdecl.struct_decl_name);
List.fold_left
(fun ctxt (fdecl, _) ->
let f_uid =
StructFieldName.fresh fdecl.Surface.Ast.struct_decl_field_name
in
let f_uid = StructField.fresh fdecl.Surface.Ast.struct_decl_field_name in
let ctxt =
{
ctxt with
field_idmap =
IdentMap.update
IdentName.Map.update
(Marked.unmark fdecl.Surface.Ast.struct_decl_field_name)
(fun uids ->
match uids with
| None -> Some (StructMap.singleton s_uid f_uid)
| Some uids -> Some (StructMap.add s_uid f_uid uids))
| None -> Some (StructName.Map.singleton s_uid f_uid)
| Some uids -> Some (StructName.Map.add s_uid f_uid uids))
ctxt.field_idmap;
}
in
{
ctxt with
structs =
StructMap.update s_uid
StructName.Map.update s_uid
(fun fields ->
match fields with
| None ->
Some
(StructFieldMap.singleton f_uid
(StructField.Map.singleton f_uid
(process_type ctxt fdecl.Surface.Ast.struct_decl_field_typ))
| Some fields ->
Some
(StructFieldMap.add f_uid
(StructField.Map.add f_uid
(process_type ctxt fdecl.Surface.Ast.struct_decl_field_typ)
fields))
ctxt.structs;
@ -449,19 +446,19 @@ let process_enum_decl (ctxt : context) (edecl : Surface.Ast.enum_decl) : context
{
ctxt with
constructor_idmap =
IdentMap.update
IdentName.Map.update
(Marked.unmark cdecl.Surface.Ast.enum_decl_case_name)
(fun uids ->
match uids with
| None -> Some (EnumMap.singleton e_uid c_uid)
| Some uids -> Some (EnumMap.add e_uid c_uid uids))
| None -> Some (EnumName.Map.singleton e_uid c_uid)
| Some uids -> Some (EnumName.Map.add e_uid c_uid uids))
ctxt.constructor_idmap;
}
in
{
ctxt with
enums =
EnumMap.update e_uid
EnumName.Map.update e_uid
(fun cases ->
let typ =
match cdecl.Surface.Ast.enum_decl_case_typ with
@ -469,8 +466,8 @@ let process_enum_decl (ctxt : context) (edecl : Surface.Ast.enum_decl) : context
| Some typ -> process_type ctxt typ
in
match cases with
| None -> Some (EnumConstructorMap.singleton c_uid typ)
| Some fields -> Some (EnumConstructorMap.add c_uid typ fields))
| None -> Some (EnumConstructor.Map.singleton c_uid typ)
| Some fields -> Some (EnumConstructor.Map.add c_uid typ fields))
ctxt.enums;
})
ctxt edecl.enum_decl_cases
@ -522,9 +519,9 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) :
{
ctxt with
structs =
StructMap.add
StructName.Map.add
(get_struct ctxt decl.scope_decl_name)
StructFieldMap.empty ctxt.structs;
StructField.Map.empty ctxt.structs;
}
else
let ctxt =
@ -535,23 +532,23 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) :
}
in
let out_struct_fields =
let sco = ScopeMap.find scope_uid ctxt.scopes in
let sco = ScopeName.Map.find scope_uid ctxt.scopes in
let str = get_struct ctxt decl.scope_decl_name in
IdentMap.fold
IdentName.Map.fold
(fun id var svmap ->
match var with
| SubScope _ -> svmap
| ScopeVar v -> (
try
let field =
StructMap.find str (IdentMap.find id ctxt.field_idmap)
StructName.Map.find str (IdentName.Map.find id ctxt.field_idmap)
in
ScopeVarMap.add v field svmap
ScopeVar.Map.add v field svmap
with Not_found -> svmap))
sco.var_idmap ScopeVarMap.empty
sco.var_idmap ScopeVar.Map.empty
in
let typedefs =
IdentMap.update
IdentName.Map.update
(Marked.unmark decl.scope_decl_name)
(function
| Some (TScope (scope, { out_struct_name; _ })) ->
@ -576,7 +573,7 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
Some "Second definition:", pos;
]
"%s name \"%a\" already defined" msg
(Utils.Cli.format_with_style [ANSITerminal.yellow])
(Cli.format_with_style [ANSITerminal.yellow])
name
in
match Marked.unmark item with
@ -586,26 +583,26 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
Option.iter
(fun use ->
raise_already_defined_error (typedef_info use) name pos "scope")
(IdentMap.find_opt name ctxt.typedefs);
(IdentName.Map.find_opt name ctxt.typedefs);
let scope_uid = ScopeName.fresh (name, pos) in
let out_struct_uid = StructName.fresh (name, pos) in
{
ctxt with
typedefs =
IdentMap.add name
IdentName.Map.add name
(TScope
( scope_uid,
{
out_struct_name = out_struct_uid;
out_struct_fields = ScopeVarMap.empty;
out_struct_fields = ScopeVar.Map.empty;
} ))
ctxt.typedefs;
scopes =
ScopeMap.add scope_uid
ScopeName.Map.add scope_uid
{
var_idmap = IdentMap.empty;
var_idmap = IdentName.Map.empty;
scope_defs_contexts = Ast.ScopeDefMap.empty;
sub_scopes = ScopeSet.empty;
sub_scopes = ScopeName.Set.empty;
}
ctxt.scopes;
}
@ -614,12 +611,12 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
Option.iter
(fun use ->
raise_already_defined_error (typedef_info use) name pos "struct")
(IdentMap.find_opt name ctxt.typedefs);
(IdentName.Map.find_opt name ctxt.typedefs);
let s_uid = StructName.fresh sdecl.struct_decl_name in
{
ctxt with
typedefs =
IdentMap.add
IdentName.Map.add
(Marked.unmark sdecl.struct_decl_name)
(TStruct s_uid) ctxt.typedefs;
}
@ -628,12 +625,12 @@ let process_name_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
Option.iter
(fun use ->
raise_already_defined_error (typedef_info use) name pos "enum")
(IdentMap.find_opt name ctxt.typedefs);
(IdentName.Map.find_opt name ctxt.typedefs);
let e_uid = EnumName.fresh edecl.enum_decl_name in
{
ctxt with
typedefs =
IdentMap.add
IdentName.Map.add
(Marked.unmark edecl.enum_decl_name)
(TEnum e_uid) ctxt.typedefs;
}
@ -679,18 +676,19 @@ let get_def_key
(scope_uid : ScopeName.t)
(ctxt : context)
(pos : Pos.t) : Ast.ScopeDef.t =
let scope_ctxt = ScopeMap.find scope_uid ctxt.scopes in
let scope_ctxt = ScopeName.Map.find scope_uid ctxt.scopes in
match name with
| [x] ->
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 = ScopeVar.Map.find x_uid ctxt.var_typs in
Ast.ScopeDef.Var
( x_uid,
match state with
| Some state -> (
try
Some
(IdentMap.find (Marked.unmark state) var_sig.var_sig_states_idmap)
(IdentName.Map.find (Marked.unmark state)
var_sig.var_sig_states_idmap)
with Not_found ->
Errors.raise_multispanned_error
[
@ -701,7 +699,7 @@ let get_def_key
"This identifier is not a state declared for variable %a."
ScopeVar.format_t x_uid)
| None ->
if not (IdentMap.is_empty var_sig.var_sig_states_idmap) then
if not (IdentName.Map.is_empty var_sig.var_sig_states_idmap) then
Errors.raise_multispanned_error
[
None, Marked.get_mark x;
@ -714,7 +712,7 @@ let get_def_key
else None )
| [y; x] ->
let (subscope_uid, subscope_real_uid) : SubScopeName.t * ScopeName.t =
match IdentMap.find_opt (Marked.unmark y) scope_ctxt.var_idmap with
match IdentName.Map.find_opt (Marked.unmark y) scope_ctxt.var_idmap with
| Some (SubScope (v, u)) -> v, u
| Some _ ->
Errors.raise_spanned_error pos
@ -732,6 +730,73 @@ let get_def_key
subscope variable. In particular, it is not possible to define struct \
fields individually in Catala."
let update_def_key_ctx
(d : Surface.Ast.definition)
(def_key_ctx : scope_def_context) : scope_def_context =
(* First, we update the def key context with information about the
definition's label*)
let def_key_ctx =
match d.Surface.Ast.definition_label with
| None -> def_key_ctx
| Some label ->
let new_label_idmap =
IdentName.Map.update (Marked.unmark label)
(fun existing_label ->
match existing_label with
| Some existing_label -> Some existing_label
| None -> Some (LabelName.fresh label))
def_key_ctx.label_idmap
in
{ def_key_ctx with label_idmap = new_label_idmap }
in
(* And second, we update the map of default rulenames for unlabeled
exceptions *)
match d.Surface.Ast.definition_exception_to with
(* If this definition is an exception, it cannot be a default definition *)
| UnlabeledException | ExceptionToLabel _ -> def_key_ctx
(* If it is not an exception, we need to distinguish between several cases *)
| NotAnException -> (
match def_key_ctx.default_exception_rulename with
(* There was already a default definition for this key. If we need it, it is
ambiguous *)
| Some old ->
{
def_key_ctx with
default_exception_rulename =
Some
(Ambiguous
([Marked.get_mark d.definition_name]
@
match old with Ambiguous old -> old | Unique (_, pos) -> [pos]));
}
(* No definition has been set yet for this key *)
| None -> (
match d.Surface.Ast.definition_label with
(* This default definition has a label. This is not allowed for unlabeled
exceptions *)
| Some _ ->
{
def_key_ctx with
default_exception_rulename =
Some (Ambiguous [Marked.get_mark d.definition_name]);
}
(* This is a possible default definition for this key. We create and store
a fresh rulename *)
| None ->
{
def_key_ctx with
default_exception_rulename =
Some (Unique (d.definition_id, Marked.get_mark d.definition_name));
}))
let empty_def_key_ctx =
{
(* Here, this is the first time we encounter a definition for this
definition key *)
default_exception_rulename = None;
label_idmap = IdentName.Map.empty;
}
let process_definition
(ctxt : context)
(s_name : ScopeName.t)
@ -740,7 +805,7 @@ let process_definition
{
ctxt with
scopes =
ScopeMap.update s_name
ScopeName.Map.update s_name
(fun (s_ctxt : scope_context option) ->
let def_key =
get_def_key
@ -757,85 +822,9 @@ let process_definition
scope_defs_contexts =
Ast.ScopeDefMap.update def_key
(fun def_key_ctx ->
let def_key_ctx : scope_def_context =
Option.fold
~none:
{
(* Here, this is the first time we encounter a
definition for this definition key *)
default_exception_rulename = None;
label_idmap = IdentMap.empty;
}
~some:(fun x -> x)
def_key_ctx
in
(* First, we update the def key context with information
about the definition's label*)
let def_key_ctx =
match d.Surface.Ast.definition_label with
| None -> def_key_ctx
| Some label ->
let new_label_idmap =
IdentMap.update (Marked.unmark label)
(fun existing_label ->
match existing_label with
| Some existing_label -> Some existing_label
| None -> Some (LabelName.fresh label))
def_key_ctx.label_idmap
in
{ def_key_ctx with label_idmap = new_label_idmap }
in
(* And second, we update the map of default rulenames for
unlabeled exceptions *)
let def_key_ctx =
match d.Surface.Ast.definition_exception_to with
(* If this definition is an exception, it cannot be a
default definition *)
| UnlabeledException | ExceptionToLabel _ -> def_key_ctx
(* If it is not an exception, we need to distinguish
between several cases *)
| NotAnException -> (
match def_key_ctx.default_exception_rulename with
(* There was already a default definition for this
key. If we need it, it is ambiguous *)
| Some old ->
{
def_key_ctx with
default_exception_rulename =
Some
(Ambiguous
([Marked.get_mark d.definition_name]
@
match old with
| Ambiguous old -> old
| Unique (_, pos) -> [pos]));
}
(* No definition has been set yet for this key *)
| None -> (
match d.Surface.Ast.definition_label with
(* This default definition has a label. This is not
allowed for unlabeled exceptions *)
| Some _ ->
{
def_key_ctx with
default_exception_rulename =
Some
(Ambiguous
[Marked.get_mark d.definition_name]);
}
(* This is a possible default definition for this
key. We create and store a fresh rulename *)
| None ->
{
def_key_ctx with
default_exception_rulename =
Some
(Unique
( d.definition_id,
Marked.get_mark d.definition_name ));
}))
in
Some def_key_ctx)
Some
(update_def_key_ctx d
(Option.value ~default:empty_def_key_ctx def_key_ctx)))
s_ctxt.scope_defs_contexts;
})
ctxt.scopes;
@ -854,7 +843,7 @@ let process_scope_use (ctxt : context) (suse : Surface.Ast.scope_use) : context
=
let s_name =
match
IdentMap.find_opt
IdentName.Map.find_opt
(Marked.unmark suse.Surface.Ast.scope_use_name)
ctxt.typedefs
with
@ -863,7 +852,7 @@ let process_scope_use (ctxt : context) (suse : Surface.Ast.scope_use) : context
Errors.raise_spanned_error
(Marked.get_mark suse.Surface.Ast.scope_use_name)
"\"%a\": this scope has not been declared anywhere, is it a typo?"
(Utils.Cli.format_with_style [ANSITerminal.yellow])
(Cli.format_with_style [ANSITerminal.yellow])
(Marked.unmark suse.Surface.Ast.scope_use_name)
in
List.fold_left
@ -882,14 +871,14 @@ let process_use_item (ctxt : context) (item : Surface.Ast.code_item Marked.pos)
let form_context (prgm : Surface.Ast.program) : context =
let empty_ctxt =
{
local_var_idmap = IdentMap.empty;
typedefs = IdentMap.empty;
scopes = ScopeMap.empty;
var_typs = ScopeVarMap.empty;
structs = StructMap.empty;
field_idmap = IdentMap.empty;
enums = EnumMap.empty;
constructor_idmap = IdentMap.empty;
local_var_idmap = IdentName.Map.empty;
typedefs = IdentName.Map.empty;
scopes = ScopeName.Map.empty;
var_typs = ScopeVar.Map.empty;
structs = StructName.Map.empty;
field_idmap = IdentName.Map.empty;
enums = EnumName.Map.empty;
constructor_idmap = IdentName.Map.empty;
}
in
let ctxt =

View File

@ -18,22 +18,18 @@
(** Builds a context that allows for mapping each name to a precise uid, taking
lexical scopes into account *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Name resolution context} *)
type ident = string
module IdentMap : Map.S with type key = String.t
type unique_rulename =
| Ambiguous of Pos.t list
| Unique of RuleName.t Marked.pos
type scope_def_context = {
default_exception_rulename : unique_rulename option;
label_idmap : LabelName.t IdentMap.t;
label_idmap : LabelName.t IdentName.Map.t;
}
type scope_var_or_subscope =
@ -41,26 +37,26 @@ type scope_var_or_subscope =
| SubScope of SubScopeName.t * ScopeName.t
type scope_context = {
var_idmap : scope_var_or_subscope IdentMap.t;
var_idmap : scope_var_or_subscope IdentName.Map.t;
(** All variables, including scope variables and subscopes *)
scope_defs_contexts : scope_def_context Ast.ScopeDefMap.t;
(** What is the default rule to refer to for unnamed exceptions, if any *)
sub_scopes : ScopeSet.t;
sub_scopes : ScopeName.Set.t;
(** Other scopes referred to by this scope. Used for dependency analysis *)
}
(** Inside a scope, we distinguish between the variables and the subscopes. *)
type struct_context = typ StructFieldMap.t
type struct_context = typ StructField.Map.t
(** Types of the fields of a struct *)
type enum_context = typ EnumConstructorMap.t
type enum_context = typ EnumConstructor.Map.t
(** Types of the payloads of the cases of an enum *)
type var_sig = {
var_sig_typ : typ;
var_sig_is_condition : bool;
var_sig_io : Surface.Ast.scope_decl_context_io;
var_sig_states_idmap : StateName.t IdentMap.t;
var_sig_states_idmap : StateName.t IdentName.Map.t;
var_sig_states_list : StateName.t list;
}
@ -73,21 +69,22 @@ type typedef =
(** Implicitly defined output struct *)
type context = {
local_var_idmap : Ast.expr Var.t IdentMap.t;
local_var_idmap : Ast.expr Var.t IdentName.Map.t;
(** Inside a definition, local variables can be introduced by functions
arguments or pattern matching *)
typedefs : typedef IdentMap.t;
typedefs : typedef IdentName.Map.t;
(** Gathers the names of the scopes, structs and enums *)
field_idmap : StructFieldName.t StructMap.t IdentMap.t;
field_idmap : StructField.t StructName.Map.t IdentName.Map.t;
(** The names of the struct fields. Names of fields can be shared between
different structs *)
constructor_idmap : EnumConstructor.t EnumMap.t IdentMap.t;
constructor_idmap : EnumConstructor.t EnumName.Map.t IdentName.Map.t;
(** The names of the enum constructors. Constructor names can be shared
between different enums *)
scopes : scope_context ScopeMap.t; (** For each scope, its context *)
structs : struct_context StructMap.t; (** For each struct, its context *)
enums : enum_context EnumMap.t; (** For each enum, its context *)
var_typs : var_sig ScopeVarMap.t;
scopes : scope_context ScopeName.Map.t; (** For each scope, its context *)
structs : struct_context StructName.Map.t;
(** For each struct, its context *)
enums : enum_context EnumName.Map.t; (** For each enum, its context *)
var_typs : var_sig ScopeVar.Map.t;
(** The signatures of each scope variable declared *)
}
(** Main context used throughout {!module: Surface.Desugaring} *)
@ -98,7 +95,7 @@ val raise_unsupported_feature : string -> Pos.t -> 'a
(** Temporary function raising an error message saying that a feature is not
supported yet *)
val raise_unknown_identifier : string -> ident Marked.pos -> 'a
val raise_unknown_identifier : string -> IdentName.t Marked.pos -> 'a
(** Function to call whenever an identifier used somewhere has not been declared
in the program previously *)
@ -108,14 +105,14 @@ val get_var_typ : context -> ScopeVar.t -> typ
val is_var_cond : context -> ScopeVar.t -> bool
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 -> IdentName.t Marked.pos -> ScopeVar.t
(** Get the variable uid inside the scope given in argument *)
val get_subscope_uid :
ScopeName.t -> context -> ident Marked.pos -> SubScopeName.t
ScopeName.t -> context -> IdentName.t Marked.pos -> SubScopeName.t
(** Get the subscope uid inside the scope given in argument *)
val is_subscope_uid : ScopeName.t -> context -> ident -> bool
val is_subscope_uid : ScopeName.t -> context -> IdentName.t -> bool
(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the
subscopes of [scope_uid]. *)
@ -128,7 +125,7 @@ val get_def_typ : context -> Ast.ScopeDef.t -> typ
val is_def_cond : context -> Ast.ScopeDef.t -> bool
val is_type_cond : Surface.Ast.typ -> bool
val add_def_local_var : context -> ident -> context * Ast.expr Var.t
val add_def_local_var : context -> IdentName.t -> context * Ast.expr Var.t
(** Adds a binding to the context *)
val get_def_key :
@ -140,15 +137,15 @@ val get_def_key :
Ast.ScopeDef.t
(** 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 -> IdentName.t Marked.pos -> EnumName.t
(** Find an enum definition from the typedefs, failing if there is none or it
has a different kind *)
val get_struct : context -> ident Marked.pos -> StructName.t
val get_struct : context -> IdentName.t Marked.pos -> StructName.t
(** Find a struct definition from the typedefs (possibly an implicit output
struct from a scope), failing if there is none or it has a different kind *)
val get_scope : context -> ident Marked.pos -> ScopeName.t
val get_scope : context -> IdentName.t Marked.pos -> ScopeName.t
(** Find a scope definition from the typedefs, failing if there is none or it
has a different kind *)

View File

@ -15,10 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
module Cli = Utils.Cli
module File = Utils.File
module Errors = Utils.Errors
module Pos = Utils.Pos
open Catala_utils
(** Associates a {!type: Cli.backend_lang} with its string represtation. *)
let languages = ["en", Cli.En; "fr", Cli.Fr; "pl", Cli.Pl]
@ -151,20 +148,18 @@ let driver source_file (options : Cli.options) : int =
| None, _ ->
let _, scope =
try
Desugared.Name_resolution.IdentMap.filter_map
Shared_ast.IdentName.Map.filter_map
(fun _ -> function
| Desugared.Name_resolution.TScope (uid, _) -> Some uid
| _ -> None)
ctxt.typedefs
|> Desugared.Name_resolution.IdentMap.choose
|> Shared_ast.IdentName.Map.choose
with Not_found ->
Errors.raise_error "There isn't any scope inside the program."
in
scope
| Some name, _ -> (
match
Desugared.Name_resolution.IdentMap.find_opt name ctxt.typedefs
with
match Shared_ast.IdentName.Map.find_opt name ctxt.typedefs with
| Some (Desugared.Name_resolution.TScope (uid, _)) -> uid
| _ ->
Errors.raise_error "There is no scope \"%s\" inside the program."
@ -172,6 +167,8 @@ let driver source_file (options : Cli.options) : int =
in
Cli.debug_print "Desugaring...";
let prgm = Desugared.From_surface.translate_program ctxt prgm in
Cli.debug_print "Disambiguating...";
let prgm = Desugared.Disambiguate.program prgm in
Cli.debug_print "Collecting rules...";
let prgm = Scopelang.From_desugared.translate_program prgm in
match backend with
@ -182,7 +179,8 @@ let driver source_file (options : Cli.options) : int =
if Option.is_some options.ex_scope then
Format.fprintf fmt "%a\n"
(Scopelang.Print.scope prgm.program_ctx ~debug:options.debug)
(scope_uid, Shared_ast.ScopeMap.find scope_uid prgm.program_scopes)
( scope_uid,
Shared_ast.ScopeName.Map.find scope_uid prgm.program_scopes )
else
Format.fprintf fmt "%a\n"
(Scopelang.Print.program ~debug:options.debug)

View File

@ -15,9 +15,10 @@
License for the specific language governing permissions and limitations under
the License. *)
open Catala_utils
module Plugin = Plugin.PluginAPI
val driver : Utils.Pos.input_file -> Utils.Cli.options -> int
val driver : Pos.input_file -> Cli.options -> int
(** Entry function for the executable. Returns a negative number in case of
error. *)

View File

@ -3,7 +3,7 @@
(public_name catala.driver)
(libraries
dynlink
utils
catala_utils
surface
desugared
literate

View File

@ -103,7 +103,7 @@ Two more modules contain additional features for the compiler:
{ul
{li {{: literate.html} Literate programming}}
{li {{: utils.html} Compiler utilities}}
{li {{: catala_utils.html} Compiler utilities}}
}
The Catala runtimes documentation is available here:

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
include Shared_ast
type lit = lcalc glit
@ -28,10 +28,10 @@ let option_enum : EnumName.t = EnumName.fresh ("eoption", Pos.no_pos)
let none_constr : EnumConstructor.t = EnumConstructor.fresh ("ENone", Pos.no_pos)
let some_constr : EnumConstructor.t = EnumConstructor.fresh ("ESome", Pos.no_pos)
let option_enum_config : typ EnumConstructorMap.t =
EnumConstructorMap.empty
|> EnumConstructorMap.add none_constr (TLit TUnit, Pos.no_pos)
|> EnumConstructorMap.add some_constr (TAny, Pos.no_pos)
let option_enum_config : typ EnumConstructor.Map.t =
EnumConstructor.Map.empty
|> EnumConstructor.Map.add none_constr (TLit TUnit, Pos.no_pos)
|> EnumConstructor.Map.add some_constr (TAny, Pos.no_pos)
(* FIXME: proper typing in all the constructors below *)
@ -49,9 +49,9 @@ let make_some e =
let make_matchopt_with_abs_arms arg e_none e_some =
let m = Marked.get_mark arg in
let cases =
EnumConstructorMap.empty
|> EnumConstructorMap.add none_constr e_none
|> EnumConstructorMap.add some_constr e_some
EnumConstructor.Map.empty
|> EnumConstructor.Map.add none_constr e_none
|> EnumConstructor.Map.add some_constr e_some
in
Expr.ematch arg option_enum cases m

View File

@ -14,6 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Catala_utils
open Shared_ast
(** Abstract syntax tree for the lambda calculus *)
@ -32,7 +33,7 @@ type 'm program = 'm expr Shared_ast.program
val option_enum : EnumName.t
val none_constr : EnumConstructor.t
val some_constr : EnumConstructor.t
val option_enum_config : typ EnumConstructorMap.t
val option_enum_config : typ EnumConstructor.Map.t
val make_none : 'm mark -> 'm expr boxed
val make_some : 'm expr boxed -> 'm expr boxed
@ -40,7 +41,7 @@ val make_matchopt_with_abs_arms :
'm expr boxed -> 'm expr boxed -> 'm expr boxed -> 'm expr boxed
val make_matchopt :
Utils.Pos.t ->
Pos.t ->
'm expr Var.t ->
typ ->
'm expr boxed ->

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
module D = Dcalc.Ast
@ -44,7 +44,7 @@ let closure_conversion_expr (type m) (ctx : m ctx) (e : m expr) : m expr boxed =
(* We do not close the clotures inside the arms of the match expression,
since they get a special treatment at compilation to Scalc. *)
let free_vars, new_cases =
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun cons e1 (free_vars, new_cases) ->
match Marked.unmark e1 with
| EAbs { binder; tys } ->
@ -52,12 +52,12 @@ let closure_conversion_expr (type m) (ctx : m ctx) (e : m expr) : m expr boxed =
let new_free_vars, new_body = aux body in
let new_binder = Expr.bind vars new_body in
( Var.Set.union free_vars new_free_vars,
EnumConstructorMap.add cons
EnumConstructor.Map.add cons
(Expr.eabs new_binder tys (Marked.get_mark e1))
new_cases )
| _ -> failwith "should not happen")
cases
(free_vars, EnumConstructorMap.empty)
(free_vars, EnumConstructor.Map.empty)
in
free_vars, Expr.ematch new_e name new_cases m
| EApp { f = EAbs { binder; tys }, e1_pos; args } ->

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
module D = Dcalc.Ast
module A = Ast
@ -43,7 +43,7 @@ let rec translate_default
Expr.make_app
(Expr.make_var
(Var.translate A.handle_default)
(Expr.with_ty mark_default (Utils.Marked.mark pos TAny)))
(Expr.with_ty mark_default (Marked.mark pos TAny)))
[
Expr.earray exceptions mark_default;
thunk_expr (translate_expr ctx just);
@ -58,13 +58,13 @@ and translate_expr (ctx : 'm ctx) (e : 'm D.expr) : 'm A.expr boxed =
match Marked.unmark e with
| EVar v -> Expr.make_var (Var.Map.find v ctx) m
| EStruct { name; fields } ->
Expr.estruct name (StructFieldMap.map (translate_expr ctx) fields) m
Expr.estruct name (StructField.Map.map (translate_expr ctx) fields) m
| EStructAccess { name; e; field } ->
Expr.estructaccess (translate_expr ctx e) field name m
| EInj { name; e; cons } -> Expr.einj (translate_expr ctx e) cons name m
| EMatch { name; e; cases } ->
Expr.ematch (translate_expr ctx e) name
(EnumConstructorMap.map (translate_expr ctx) cases)
(EnumConstructor.Map.map (translate_expr ctx) cases)
m
| EArray es -> Expr.earray (List.map (translate_expr ctx) es) m
| ELit
@ -72,7 +72,7 @@ and translate_expr (ctx : 'm ctx) (e : 'm D.expr) : 'm A.expr boxed =
l) ->
Expr.elit l m
| ELit LEmptyError -> Expr.eraise EmptyError m
| EOp op -> Expr.eop op m
| EOp op -> Expr.eop (Expr.translate_op op) m
| EIfThenElse { cond; etrue; efalse } ->
Expr.eifthenelse (translate_expr ctx cond) (translate_expr ctx etrue)
(translate_expr ctx efalse)

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
module D = Dcalc.Ast
module A = Ast
@ -255,11 +255,12 @@ let rec translate_and_hoist (ctx : 'm ctx) (e : 'm D.expr) :
e', hoists
| EStruct { name; fields } ->
let fields', h_fields =
StructFieldMap.fold
StructField.Map.fold
(fun field e (fields, hoists) ->
let e, h = translate_and_hoist ctx e in
StructFieldMap.add field e fields, h :: hoists)
fields (StructFieldMap.empty, [])
StructField.Map.add field e fields, h :: hoists)
fields
(StructField.Map.empty, [])
in
let hoists = disjoint_union_maps (Expr.pos e) h_fields in
Expr.estruct name fields' mark, hoists
@ -274,12 +275,12 @@ let rec translate_and_hoist (ctx : 'm ctx) (e : 'm D.expr) :
| EMatch { name; e = e1; cases } ->
let e1', h1 = translate_and_hoist ctx e1 in
let cases', h_cases =
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun cons e (cases, hoists) ->
let e', h = translate_and_hoist ctx e in
EnumConstructorMap.add cons e' cases, h :: hoists)
EnumConstructor.Map.add cons e' cases, h :: hoists)
cases
(EnumConstructorMap.empty, [])
(EnumConstructor.Map.empty, [])
in
let hoists = disjoint_union_maps (Expr.pos e) (h1 :: h_cases) in
let e' = Expr.ematch e1' name cases' mark in
@ -288,7 +289,7 @@ let rec translate_and_hoist (ctx : 'm ctx) (e : 'm D.expr) :
let es', hoists = es |> List.map (translate_and_hoist ctx) |> List.split in
Expr.earray es' mark, disjoint_union_maps (Expr.pos e) hoists
| EOp op -> Expr.eop op mark, Var.Map.empty
| EOp op -> Expr.eop (Expr.translate_op op) mark, Var.Map.empty
and translate_expr ?(append_esome = true) (ctx : 'm ctx) (e : 'm D.expr) :
'm A.expr boxed =
@ -537,7 +538,7 @@ let translate_program (prgm : 'm D.program) : 'm A.program =
prgm.decl_ctx with
ctx_enums =
prgm.decl_ctx.ctx_enums
|> EnumMap.add A.option_enum A.option_enum_config;
|> EnumName.Map.add A.option_enum A.option_enum_config;
}
in
let decl_ctx =
@ -545,9 +546,9 @@ let translate_program (prgm : 'm D.program) : 'm A.program =
decl_ctx with
ctx_structs =
prgm.decl_ctx.ctx_structs
|> StructMap.mapi (fun n str ->
|> StructName.Map.mapi (fun n str ->
if List.mem n inputs_structs then
StructFieldMap.map translate_typ str
StructField.Map.map translate_typ str
(* Cli.debug_print @@ Format.asprintf "Input type: %a"
(Print.typ decl_ctx) tau; Cli.debug_print @@ Format.asprintf
"Output type: %a" (Print.typ decl_ctx) (translate_typ

View File

@ -13,7 +13,7 @@
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
module D = Dcalc.Ast
@ -27,16 +27,16 @@ let rec iota_expr (e : 'm expr) : 'm expr boxed =
| EMatch { e = EInj { e = e'; cons; name = n' }, _; cases; name = n }
when EnumName.equal n n' ->
let e1 = visitor_map iota_expr e' in
let case = visitor_map iota_expr (EnumConstructorMap.find cons cases) in
let case = visitor_map iota_expr (EnumConstructor.Map.find cons cases) in
Expr.eapp case [e1] m
| EMatch { e = e'; cases; name = n }
when cases
|> EnumConstructorMap.mapi (fun i case ->
|> EnumConstructor.Map.mapi (fun i case ->
match Marked.unmark case with
| EInj { cons = i'; name = n'; _ } ->
EnumConstructor.equal i i' && EnumName.equal n n'
| _ -> false)
|> EnumConstructorMap.for_all (fun _ b -> b) ->
|> EnumConstructor.Map.for_all (fun _ b -> b) ->
visitor_map iota_expr e'
| _ -> visitor_map iota_expr e

View File

@ -14,22 +14,21 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
open String_common
module D = Dcalc.Ast
let find_struct (s : StructName.t) (ctx : decl_ctx) : typ StructFieldMap.t =
try StructMap.find s ctx.ctx_structs
let find_struct (s : StructName.t) (ctx : decl_ctx) : typ StructField.Map.t =
try StructName.Map.find s ctx.ctx_structs
with Not_found ->
let s_name, pos = StructName.get_info s in
Errors.raise_spanned_error pos
"Internal Error: Structure %s was not found in the current environment."
s_name
let find_enum (en : EnumName.t) (ctx : decl_ctx) : typ EnumConstructorMap.t =
try EnumMap.find en ctx.ctx_enums
let find_enum (en : EnumName.t) (ctx : decl_ctx) : typ EnumConstructor.Map.t =
try EnumName.Map.find en ctx.ctx_enums
with Not_found ->
let en_name, pos = EnumName.get_info en in
Errors.raise_spanned_error pos
@ -55,7 +54,7 @@ let format_lit (fmt : Format.formatter) (l : lit Marked.pos) : unit =
let years, months, days = Runtime.duration_to_years_months_days d in
Format.fprintf fmt "duration_of_numbers (%d) (%d) (%d)" years months days
let format_op_kind (fmt : Format.formatter) (k : op_kind) =
let format_op_kind (fmt : Format.formatter) (k : 'a op_kind) =
Format.fprintf fmt "%s"
(match k with
| KInt -> "!"
@ -64,7 +63,7 @@ let format_op_kind (fmt : Format.formatter) (k : op_kind) =
| KDate -> "@"
| KDuration -> "^")
let format_binop (fmt : Format.formatter) (op : binop Marked.pos) : unit =
let format_binop (fmt : Format.formatter) (op : 'a binop Marked.pos) : unit =
match Marked.unmark op with
| Add k -> Format.fprintf fmt "+%a" format_op_kind k
| Sub k -> Format.fprintf fmt "-%a" format_op_kind k
@ -91,7 +90,7 @@ let format_uid_list (fmt : Format.formatter) (uids : Uid.MarkedString.info list)
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ")
(fun fmt info ->
Format.fprintf fmt "\"%a\"" Utils.Uid.MarkedString.format_info info))
Format.fprintf fmt "\"%a\"" Uid.MarkedString.format info))
uids
let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
@ -104,7 +103,7 @@ let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
(Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info)))
uids
let format_unop (fmt : Format.formatter) (op : unop Marked.pos) : unit =
let format_unop (fmt : Format.formatter) (op : lcalc unop Marked.pos) : unit =
match Marked.unmark op with
| Minus k -> Format.fprintf fmt "~-%a" format_op_kind k
| Not -> Format.fprintf fmt "%s" "not"
@ -141,8 +140,8 @@ let avoid_keywords (s : string) : string =
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
Format.asprintf "%a" StructName.format_t v
|> to_ascii
|> to_snake_case
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords
|> Format.fprintf fmt "%s"
@ -152,8 +151,8 @@ let format_to_module_name
(match name with
| `Ename v -> Format.asprintf "%a" EnumName.format_t v
| `Sname v -> Format.asprintf "%a" StructName.format_t v)
|> to_ascii
|> to_snake_case
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords
|> String.split_on_char '_'
|> List.map String.capitalize_ascii
@ -162,24 +161,25 @@ let format_to_module_name
let format_struct_field_name
(fmt : Format.formatter)
((sname_opt, v) : StructName.t option * StructFieldName.t) : unit =
((sname_opt, v) : StructName.t option * StructField.t) : unit =
(match sname_opt with
| Some sname ->
Format.fprintf fmt "%a.%s" format_to_module_name (`Sname sname)
| None -> Format.fprintf fmt "%s")
(avoid_keywords
(to_ascii (Format.asprintf "%a" StructFieldName.format_t v)))
(String.to_ascii (Format.asprintf "%a" StructField.format_t v)))
let format_enum_name (fmt : Format.formatter) (v : EnumName.t) : unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_snake_case (to_ascii (Format.asprintf "%a" EnumName.format_t v))))
(String.to_snake_case
(String.to_ascii (Format.asprintf "%a" EnumName.format_t v))))
let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) :
unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_ascii (Format.asprintf "%a" EnumConstructor.format_t v)))
(String.to_ascii (Format.asprintf "%a" EnumConstructor.format_t v)))
let rec typ_embedding_name (fmt : Format.formatter) (ty : typ) : unit =
match Marked.unmark ty with
@ -223,16 +223,18 @@ let rec format_typ (fmt : Format.formatter) (typ : typ) : unit =
| TAny -> Format.fprintf fmt "_"
let format_var (fmt : Format.formatter) (v : 'm Var.t) : unit =
let lowercase_name = to_snake_case (to_ascii (Bindlib.name_of v)) in
let lowercase_name =
String.to_snake_case (String.to_ascii (Bindlib.name_of v))
in
let lowercase_name =
Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.")
~subst:(fun _ -> "_dot_")
lowercase_name
in
let lowercase_name = avoid_keywords (to_ascii lowercase_name) in
let lowercase_name = avoid_keywords (String.to_ascii lowercase_name) in
if
List.mem lowercase_name ["handle_default"; "handle_default_opt"]
|| begins_with_uppercase (Bindlib.name_of v)
|| String.begins_with_uppercase (Bindlib.name_of v)
then Format.fprintf fmt "%s" lowercase_name
else if lowercase_name = "_" then Format.fprintf fmt "%s" lowercase_name
else (
@ -284,7 +286,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
(fun fmt e -> Format.fprintf fmt "%a" format_with_parens e))
es
| EStruct { name = s; fields = es } ->
if StructFieldMap.is_empty es then Format.fprintf fmt "()"
if StructField.Map.is_empty es then Format.fprintf fmt "()"
else
Format.fprintf fmt "{@[<hov 2>%a@]}"
(Format.pp_print_list
@ -292,7 +294,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
(fun fmt (struct_field, e) ->
Format.fprintf fmt "@[<hov 2>%a =@ %a@]" format_struct_field_name
(Some s, struct_field) format_with_parens e))
(StructFieldMap.bindings es)
(StructField.Map.bindings es)
| EArray es ->
Format.fprintf fmt "@[<hov 2>[|%a|]@]"
(Format.pp_print_list
@ -331,7 +333,7 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
| _ -> assert false
(* should not happen *))
e))
(EnumConstructorMap.bindings cases)
(EnumConstructor.Map.bindings cases)
| ELit l -> Format.fprintf fmt "%a" format_lit (Marked.mark (Expr.pos e) l)
| EApp { f = EAbs { binder; tys }, _; args } ->
let xs, body = Bindlib.unmbind binder in
@ -444,8 +446,8 @@ let rec format_expr (ctx : decl_ctx) (fmt : Format.formatter) (e : 'm expr) :
let format_struct_embedding
(fmt : Format.formatter)
((struct_name, struct_fields) : StructName.t * typ StructFieldMap.t) =
if StructFieldMap.is_empty struct_fields then
((struct_name, struct_fields) : StructName.t * typ StructField.Map.t) =
if StructField.Map.is_empty struct_fields then
Format.fprintf fmt "let embed_%a (_: %a.t) : runtime_value = Unit@\n@\n"
format_struct_name struct_name format_to_module_name (`Sname struct_name)
else
@ -458,16 +460,16 @@ let format_struct_embedding
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ";@\n")
(fun _fmt (struct_field, struct_field_type) ->
Format.fprintf fmt "(\"%a\",@ %a@ x.%a)" StructFieldName.format_t
Format.fprintf fmt "(\"%a\",@ %a@ x.%a)" StructField.format_t
struct_field typ_embedding_name struct_field_type
format_struct_field_name
(Some struct_name, struct_field)))
(StructFieldMap.bindings struct_fields)
(StructField.Map.bindings struct_fields)
let format_enum_embedding
(fmt : Format.formatter)
((enum_name, enum_cases) : EnumName.t * typ EnumConstructorMap.t) =
if EnumConstructorMap.is_empty enum_cases then
((enum_name, enum_cases) : EnumName.t * typ EnumConstructor.Map.t) =
if EnumConstructor.Map.is_empty enum_cases then
Format.fprintf fmt "let embed_%a (_: %a.t) : runtime_value = Unit@\n@\n"
format_to_module_name (`Ename enum_name) format_enum_name enum_name
else
@ -483,14 +485,14 @@ let format_enum_embedding
Format.fprintf fmt "@[<hov 2>| %a x ->@ (\"%a\", %a x)@]"
format_enum_cons_name enum_cons EnumConstructor.format_t enum_cons
typ_embedding_name enum_cons_type))
(EnumConstructorMap.bindings enum_cases)
(EnumConstructor.Map.bindings enum_cases)
let format_ctx
(type_ordering : Scopelang.Dependency.TVertex.t list)
(fmt : Format.formatter)
(ctx : decl_ctx) : unit =
let format_struct_decl fmt (struct_name, struct_fields) =
if StructFieldMap.is_empty struct_fields then
if StructField.Map.is_empty struct_fields then
Format.fprintf fmt
"@[<v 2>module %a = struct@\n@[<hov 2>type t = unit@]@]@\nend@\n"
format_to_module_name (`Sname struct_name)
@ -505,7 +507,7 @@ let format_ctx
(fun _fmt (struct_field, struct_field_type) ->
Format.fprintf fmt "@[<hov 2>%a:@ %a@]" format_struct_field_name
(None, struct_field) format_typ struct_field_type))
(StructFieldMap.bindings struct_fields);
(StructField.Map.bindings struct_fields);
if !Cli.trace_flag then
format_struct_embedding fmt (struct_name, struct_fields)
in
@ -518,7 +520,7 @@ let format_ctx
(fun _fmt (enum_cons, enum_cons_type) ->
Format.fprintf fmt "@[<hov 2>| %a@ of@ %a@]" format_enum_cons_name
enum_cons format_typ enum_cons_type))
(EnumConstructorMap.bindings enum_cons);
(EnumConstructor.Map.bindings enum_cons);
if !Cli.trace_flag then format_enum_embedding fmt (enum_name, enum_cons)
in
let is_in_type_ordering s =
@ -532,8 +534,8 @@ let format_ctx
let scope_structs =
List.map
(fun (s, _) -> Scopelang.Dependency.TVertex.Struct s)
(StructMap.bindings
(StructMap.filter
(StructName.Map.bindings
(StructName.Map.filter
(fun s _ -> not (is_in_type_ordering s))
ctx.ctx_structs))
in

View File

@ -19,8 +19,8 @@ open Shared_ast
(** Formats a lambda calculus program into a valid OCaml program *)
val avoid_keywords : string -> string
val find_struct : StructName.t -> decl_ctx -> typ StructFieldMap.t
val find_enum : EnumName.t -> decl_ctx -> typ EnumConstructorMap.t
val find_struct : StructName.t -> decl_ctx -> typ StructField.Map.t
val find_enum : EnumName.t -> decl_ctx -> typ EnumConstructor.Map.t
val typ_needs_parens : typ -> bool
(* val needs_parens : 'm expr -> bool *)
@ -29,7 +29,7 @@ val format_enum_cons_name : Format.formatter -> EnumConstructor.t -> unit
val format_struct_name : Format.formatter -> StructName.t -> unit
val format_struct_field_name :
Format.formatter -> StructName.t option * StructFieldName.t -> unit
Format.formatter -> StructName.t option * StructField.t -> unit
val format_to_module_name :
Format.formatter -> [< `Ename of EnumName.t | `Sname of StructName.t ] -> unit

View File

@ -1,7 +1,7 @@
(library
(name literate)
(public_name catala.literate)
(libraries re utils surface ubase))
(libraries re catala_utils surface ubase))
(documentation
(package catala)

View File

@ -18,7 +18,7 @@
(** This modules weaves the source code and the legislative text together into a
document that law professionals can understand. *)
open Utils
open Catala_utils
open Literate_common
module A = Surface.Ast
module P = Printf
@ -91,7 +91,7 @@ let wrap_html
</ul>\n"
css_as_string (literal_title language)
(literal_generated_by language)
Utils.Cli.version
Cli.version
(pre_html (literal_disclaimer_and_link language))
(literal_source_files language)
(String.concat "\n"
@ -133,7 +133,7 @@ let pygmentize_code (c : string Marked.pos) (language : C.backend_lang) : string
"html";
"-O";
"style=colorful,anchorlinenos=True,lineanchors=\""
^ String_common.to_ascii (Pos.get_file (Marked.get_mark c))
^ String.to_ascii (Pos.get_file (Marked.get_mark c))
^ "\",linenos=table,linenostart="
^ string_of_int (Pos.get_start_line (Marked.get_mark c));
"-o";
@ -160,7 +160,7 @@ let pygmentize_code (c : string Marked.pos) (language : C.backend_lang) : string
let sanitize_html_href str =
str
|> String_common.to_ascii
|> String.to_ascii
|> R.substitute ~rex:(R.regexp "[' '°\"]") ~subst:(function _ -> "%20")
let rec law_structure_to_html

View File

@ -17,7 +17,7 @@
(** This modules weaves the source code and the legislative text together into a
document that law professionals can understand. *)
open Utils
open Catala_utils
(** {1 Helpers} *)

View File

@ -18,7 +18,7 @@
(** This modules weaves the source code and the legislative text together into a
document that law professionals can understand. *)
open Utils
open Catala_utils
open Literate_common
module A = Surface.Ast
module R = Re.Pcre
@ -158,7 +158,7 @@ codes={\catcode`\$=3\catcode`\^=7}
https://gouvfr.atlassian.net/wiki/spaces/DB/pages/223019527/Typographie+-+Typography *)
(literal_title language)
(literal_generated_by language)
Utils.Cli.version
Cli.version
(pre_latexify (literal_disclaimer_and_link language))
(literal_source_files language)
(String.concat

View File

@ -17,7 +17,7 @@
(** This modules weaves the source code and the legislative text together into a
document that law professionals can understand. *)
open Utils
open Catala_utils
(** {1 Helpers} *)

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Cli
let literal_title = function

View File

@ -14,32 +14,30 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
val literal_title : Cli.backend_lang -> string
(** Return the title traduction according the given
{!type:Utils.Cli.backend_lang}. *)
(** Return the title traduction according the given {!type:Cli.backend_lang}. *)
val literal_generated_by : Cli.backend_lang -> string
(** Return the 'generated by' traduction according the given
{!type:Utils.Cli.backend_lang}. *)
{!type:Cli.backend_lang}. *)
val literal_source_files : Cli.backend_lang -> string
(** Return the 'source files weaved' traduction according the given
{!type:Utils.Cli.backend_lang}. *)
{!type:Cli.backend_lang}. *)
val literal_disclaimer_and_link : Cli.backend_lang -> string
(** Return the traduction of a paragraph giving a basic disclaimer about Catala
and a link to the website according the given {!type:
Utils.Cli.backend_lang}. *)
and a link to the website according the given {!type: Cli.backend_lang}. *)
val literal_last_modification : Cli.backend_lang -> string
(** Return the 'last modification' traduction according the given
{!type:Utils.Cli.backend_lang}. *)
{!type:Cli.backend_lang}. *)
val get_language_extension : Cli.backend_lang -> string
(** Return the file extension corresponding to the given
{!type:Utils.Cli.backend_lang}. *)
{!type:Cli.backend_lang}. *)
val run_pandoc : string -> [ `Html | `Latex ] -> string
(** Runs the [pandoc] on a string to pretty-print markdown features into the

View File

@ -14,8 +14,10 @@
License for the specific language governing permissions and limitations under
the License. *)
open Catala_utils
type 'ast plugin_apply_fun_typ =
source_file:Utils.Pos.input_file ->
source_file:Pos.input_file ->
output_file:string option ->
scope:string option ->
'ast ->
@ -51,9 +53,9 @@ let find name = Hashtbl.find backend_plugins (String.lowercase_ascii name)
let load_file f =
try
Dynlink.loadfile f;
Utils.Cli.debug_print "Plugin %S loaded" f
Cli.debug_print "Plugin %S loaded" f
with e ->
Utils.Errors.format_warning "Could not load plugin %S: %s" f
Errors.format_warning "Could not load plugin %S: %s" f
(Printexc.to_string e)
let load_dir d =

View File

@ -16,8 +16,10 @@
(** {2 catala-facing API} *)
open Catala_utils
type 'ast plugin_apply_fun_typ =
source_file:Utils.Pos.input_file ->
source_file:Pos.input_file ->
output_file:string option ->
scope:string option ->
'ast ->

View File

@ -18,9 +18,8 @@
(** Catala plugin for generating web APIs. It generates OCaml code before the
the associated [js_of_ocaml] wrapper. *)
open Utils
open Catala_utils
open Shared_ast
open String_common
open Lcalc
open Lcalc.Ast
open Lcalc.To_ocaml
@ -40,11 +39,11 @@ module To_jsoo = struct
let format_struct_field_name_camel_case
(fmt : Format.formatter)
(v : StructFieldName.t) : unit =
(v : StructField.t) : unit =
let s =
Format.asprintf "%a" StructFieldName.format_t v
|> to_ascii
|> to_snake_case
Format.asprintf "%a" StructField.format_t v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords
|> to_camel_case
in
@ -118,17 +117,17 @@ module To_jsoo = struct
let format_var_camel_case (fmt : Format.formatter) (v : 'm Var.t) : unit =
let lowercase_name =
Bindlib.name_of v
|> to_ascii
|> to_snake_case
|> String.to_ascii
|> String.to_snake_case
|> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ ->
"_dot_")
|> to_ascii
|> String.to_ascii
|> avoid_keywords
|> to_camel_case
in
if
List.mem lowercase_name ["handle_default"; "handle_default_opt"]
|| begins_with_uppercase (Bindlib.name_of v)
|| String.begins_with_uppercase (Bindlib.name_of v)
then Format.fprintf fmt "%s" lowercase_name
else if lowercase_name = "_" then Format.fprintf fmt "%s" lowercase_name
else Format.fprintf fmt "%s_" lowercase_name
@ -166,7 +165,7 @@ module To_jsoo = struct
format_struct_field_name_camel_case struct_field
format_typ_to_jsoo struct_field_type fmt_struct_name ()
format_struct_field_name (None, struct_field)))
(StructFieldMap.bindings struct_fields)
(StructField.Map.bindings struct_fields)
in
let fmt_of_jsoo fmt _ =
Format.fprintf fmt "%a"
@ -186,7 +185,7 @@ module To_jsoo = struct
format_struct_field_name (None, struct_field)
format_typ_of_jsoo struct_field_type fmt_struct_name ()
format_struct_field_name_camel_case struct_field))
(StructFieldMap.bindings struct_fields)
(StructField.Map.bindings struct_fields)
in
let fmt_conv_funs fmt _ =
Format.fprintf fmt
@ -203,7 +202,7 @@ module To_jsoo = struct
() fmt_struct_name () fmt_module_struct_name () fmt_of_jsoo ()
in
if StructFieldMap.is_empty struct_fields then
if StructField.Map.is_empty struct_fields then
Format.fprintf fmt
"class type %a =@ object end@\n\
let %a_to_jsoo (_ : %a.t) : %a Js.t = object%%js end@\n\
@ -220,10 +219,10 @@ module To_jsoo = struct
Format.fprintf fmt "@[<hov 2>method %a:@ %a %a@]"
format_struct_field_name_camel_case struct_field format_typ
struct_field_type format_prop_or_meth struct_field_type))
(StructFieldMap.bindings struct_fields)
(StructField.Map.bindings struct_fields)
fmt_conv_funs ()
in
let format_enum_decl fmt (enum_name, (enum_cons : typ EnumConstructorMap.t))
let format_enum_decl fmt (enum_name, (enum_cons : typ EnumConstructor.Map.t))
=
let fmt_enum_name fmt _ = format_enum_name fmt enum_name in
let fmt_module_enum_name fmt _ =
@ -247,7 +246,7 @@ module To_jsoo = struct
end@]"
format_enum_cons_name cname format_enum_cons_name cname
format_typ_to_jsoo typ))
(EnumConstructorMap.bindings enum_cons)
(EnumConstructor.Map.bindings enum_cons)
in
let fmt_of_jsoo fmt _ =
Format.fprintf fmt
@ -273,7 +272,7 @@ module To_jsoo = struct
format_enum_cons_name cname fmt_module_enum_name ()
format_enum_cons_name cname format_typ_of_jsoo typ
fmt_enum_name ()))
(EnumConstructorMap.bindings enum_cons)
(EnumConstructor.Map.bindings enum_cons)
fmt_module_enum_name ()
in
@ -302,7 +301,7 @@ module To_jsoo = struct
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun fmt (enum_cons, _) ->
Format.fprintf fmt "- \"%a\"" format_enum_cons_name enum_cons))
(EnumConstructorMap.bindings enum_cons)
(EnumConstructor.Map.bindings enum_cons)
fmt_conv_funs ()
in
let is_in_type_ordering s =
@ -316,8 +315,8 @@ module To_jsoo = struct
let scope_structs =
List.map
(fun (s, _) -> Scopelang.Dependency.TVertex.Struct s)
(StructMap.bindings
(StructMap.filter
(StructName.Map.bindings
(StructName.Map.filter
(fun s _ -> not (is_in_type_ordering s))
ctx.ctx_structs))
in

View File

@ -20,8 +20,7 @@
let name = "json_schema"
let extension = "_schema.json"
open Utils
open String_common
open Catala_utils
open Shared_ast
open Lcalc.Ast
open Lcalc.To_ocaml
@ -38,11 +37,11 @@ module To_json = struct
let format_struct_field_name_camel_case
(fmt : Format.formatter)
(v : StructFieldName.t) : unit =
(v : StructField.t) : unit =
let s =
Format.asprintf "%a" StructFieldName.format_t v
|> to_ascii
|> to_snake_case
Format.asprintf "%a" StructField.format_t v
|> String.to_ascii
|> String.to_snake_case
|> avoid_keywords
|> to_camel_case
in
@ -97,7 +96,7 @@ module To_json = struct
(fun fmt (field_name, field_type) ->
Format.fprintf fmt "@[<hov 2>\"%a\": {@\n%a@]@\n}"
format_struct_field_name_camel_case field_name fmt_type field_type))
(StructFieldMap.bindings (find_struct sname ctx))
(StructField.Map.bindings (find_struct sname ctx))
let fmt_definitions
(ctx : decl_ctx)
@ -119,12 +118,13 @@ module To_json = struct
| TEnum e ->
List.fold_left collect (t :: acc)
(List.map snd
(EnumConstructorMap.bindings (EnumMap.find e ctx.ctx_enums)))
(EnumConstructor.Map.bindings
(EnumName.Map.find e ctx.ctx_enums)))
| TArray t -> collect acc t
| _ -> acc
in
find_struct input_struct ctx
|> StructFieldMap.bindings
|> StructField.Map.bindings
|> List.fold_left (fun acc (_, field_typ) -> collect acc field_typ) []
|> List.sort_uniq (fun t t' -> String.compare (get_name t) (get_name t'))
in
@ -148,7 +148,7 @@ module To_json = struct
Format.fprintf fmt
"@[<hov 2>{@\n\"type\": \"string\",@\n\"enum\": [\"%a\"]@]@\n}"
format_enum_cons_name enum_cons))
(EnumConstructorMap.bindings enum_def)
(EnumConstructor.Map.bindings enum_def)
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@\n")
(fun fmt (enum_cons, payload_type) ->
@ -170,7 +170,7 @@ module To_json = struct
}@]@\n\
}"
format_enum_cons_name enum_cons fmt_type payload_type))
(EnumConstructorMap.bindings enum_def)
(EnumConstructor.Map.bindings enum_def)
in
Format.fprintf fmt "@\n%a"

View File

@ -20,13 +20,15 @@
The code for the Python backend already has first-class support, so there
would be no reason to use this plugin instead *)
open Catala_utils
let name = "python-plugin"
let extension = ".py"
let apply ~source_file ~output_file ~scope prgm type_ordering =
ignore source_file;
ignore scope;
Utils.File.with_formatter_of_opt_file output_file
File.with_formatter_of_opt_file output_file
@@ fun fmt -> Scalc.To_python.format_program fmt prgm type_ordering
let () = Driver.Plugin.register_scalc ~name ~extension apply

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
module D = Dcalc.Ast
module L = Lcalc.Ast
@ -31,12 +31,12 @@ and naked_expr =
| EVar of LocalName.t
| EFunc of TopLevelName.t
| EStruct of expr list * StructName.t
| EStructFieldAccess of expr * StructFieldName.t * StructName.t
| EStructFieldAccess of expr * StructField.t * StructName.t
| EInj of expr * EnumConstructor.t * EnumName.t
| EArray of expr list
| ELit of L.lit
| EApp of expr * expr list
| EOp of operator
| EOp of lcalc operator
type stmt =
| SInnerFuncDef of LocalName.t Marked.pos * func

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
module A = Ast
module L = Lcalc.Ast
@ -48,7 +48,7 @@ let rec translate_expr (ctxt : 'm ctxt) (expr : 'm L.expr) : A.block * A.expr =
[], (local_var, Expr.pos expr)
| EStruct { fields; name } ->
let args_stmts, new_args =
StructFieldMap.fold
StructField.Map.fold
(fun _ arg (args_stmts, new_args) ->
let arg_stmts, new_arg = translate_expr ctxt arg in
arg_stmts @ args_stmts, new_arg :: new_args)
@ -207,7 +207,7 @@ and translate_statements (ctxt : 'm ctxt) (block_expr : 'm L.expr) : A.block =
| EMatch { e = e1; cases; name } ->
let e1_stmts, new_e1 = translate_expr ctxt e1 in
let new_cases =
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun _ arg new_args ->
match Marked.unmark arg with
| EAbs { binder; _ } ->

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
@ -46,10 +46,10 @@ let rec format_expr
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt (e, (struct_field, _)) ->
Format.fprintf fmt "%a%a%a%a %a" Print.punctuation "\""
StructFieldName.format_t struct_field Print.punctuation "\""
StructField.format_t struct_field Print.punctuation "\""
Print.punctuation ":" format_expr e))
(List.combine es
(StructFieldMap.bindings (StructMap.find s decl_ctx.ctx_structs)))
(StructField.Map.bindings (StructName.Map.find s decl_ctx.ctx_structs)))
Print.punctuation "}"
| EArray es ->
Format.fprintf fmt "@[<hov 2>%a%a%a@]" Print.punctuation "["
@ -59,8 +59,7 @@ let rec format_expr
es Print.punctuation "]"
| EStructFieldAccess (e1, field, _) ->
Format.fprintf fmt "%a%a%a%a%a" format_expr e1 Print.punctuation "."
Print.punctuation "\"" StructFieldName.format_t field Print.punctuation
"\""
Print.punctuation "\"" StructField.format_t field Print.punctuation "\""
| EInj (e, cons, _) ->
Format.fprintf fmt "@[<hov 2>%a@ %a@]" Print.enum_constructor cons
format_expr e
@ -153,7 +152,8 @@ let rec format_statement
(format_block decl_ctx ~debug)
arm_block))
(List.combine
(EnumConstructorMap.bindings (EnumMap.find enum decl_ctx.ctx_enums))
(EnumConstructor.Map.bindings
(EnumName.Map.find enum decl_ctx.ctx_enums))
arms)
and format_block

View File

@ -15,10 +15,9 @@
the License. *)
[@@@warning "-32-27"]
open Utils
open Catala_utils
open Shared_ast
open Ast
open String_common
module Runtime = Runtime_ocaml.Runtime
module D = Dcalc.Ast
module L = Lcalc.Ast
@ -50,7 +49,7 @@ let format_log_entry (fmt : Format.formatter) (entry : log_entry) : unit =
| EndCall -> Format.fprintf fmt "%s" ""
| PosRecordIfTrueBool -> Format.fprintf fmt ""
let format_binop (fmt : Format.formatter) (op : binop Marked.pos) : unit =
let format_binop (fmt : Format.formatter) (op : lcalc binop Marked.pos) : unit =
match Marked.unmark op with
| Add _ | Concat -> Format.fprintf fmt "+"
| Sub _ -> Format.fprintf fmt "-"
@ -77,7 +76,7 @@ let format_uid_list (fmt : Format.formatter) (uids : Uid.MarkedString.info list)
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ")
(fun fmt info ->
Format.fprintf fmt "\"%a\"" Utils.Uid.MarkedString.format_info info))
Format.fprintf fmt "\"%a\"" Uid.MarkedString.format info))
uids
let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
@ -90,7 +89,7 @@ let format_string_list (fmt : Format.formatter) (uids : string list) : unit =
(Re.replace sanitize_quotes ~f:(fun _ -> "\\\"") info)))
uids
let format_unop (fmt : Format.formatter) (op : unop Marked.pos) : unit =
let format_unop (fmt : Format.formatter) (op : lcalc unop Marked.pos) : unit =
match Marked.unmark op with
| Minus _ -> Format.fprintf fmt "-"
| Not -> Format.fprintf fmt "not"
@ -125,24 +124,26 @@ let avoid_keywords (s : string) : string =
let format_struct_name (fmt : Format.formatter) (v : StructName.t) : unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_camel_case (to_ascii (Format.asprintf "%a" StructName.format_t v))))
(String.to_camel_case
(String.to_ascii (Format.asprintf "%a" StructName.format_t v))))
let format_struct_field_name (fmt : Format.formatter) (v : StructFieldName.t) :
unit =
let format_struct_field_name (fmt : Format.formatter) (v : StructField.t) : unit
=
Format.fprintf fmt "%s"
(avoid_keywords
(to_ascii (Format.asprintf "%a" StructFieldName.format_t v)))
(String.to_ascii (Format.asprintf "%a" StructField.format_t v)))
let format_enum_name (fmt : Format.formatter) (v : EnumName.t) : unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_camel_case (to_ascii (Format.asprintf "%a" EnumName.format_t v))))
(String.to_camel_case
(String.to_ascii (Format.asprintf "%a" EnumName.format_t v))))
let format_enum_cons_name (fmt : Format.formatter) (v : EnumConstructor.t) :
unit =
Format.fprintf fmt "%s"
(avoid_keywords
(to_ascii (Format.asprintf "%a" EnumConstructor.format_t v)))
(String.to_ascii (Format.asprintf "%a" EnumConstructor.format_t v)))
let typ_needs_parens (e : typ) : bool =
match Marked.unmark e with TArrow _ | TArray _ -> true | _ -> false
@ -180,10 +181,10 @@ let rec format_typ (fmt : Format.formatter) (typ : typ) : unit =
let format_name_cleaned (fmt : Format.formatter) (s : string) : unit =
s
|> to_ascii
|> to_snake_case
|> String.to_ascii
|> String.to_snake_case
|> Re.Pcre.substitute ~rex:(Re.Pcre.regexp "\\.") ~subst:(fun _ -> "_dot_")
|> to_ascii
|> String.to_ascii
|> avoid_keywords
|> Format.fprintf fmt "%s"
@ -272,7 +273,7 @@ let rec format_expression (ctx : decl_ctx) (fmt : Format.formatter) (e : expr) :
Format.fprintf fmt "%a = %a" format_struct_field_name struct_field
(format_expression ctx) e))
(List.combine es
(StructFieldMap.bindings (StructMap.find s ctx.ctx_structs)))
(StructField.Map.bindings (StructName.Map.find s ctx.ctx_structs)))
| EStructFieldAccess (e1, field, _) ->
Format.fprintf fmt "%a.%a" (format_expression ctx) e1
format_struct_field_name field
@ -401,7 +402,7 @@ let rec format_statement
List.map2
(fun (x, y) (cons, _) -> x, y, cons)
cases
(EnumConstructorMap.bindings (EnumMap.find e_name ctx.ctx_enums))
(EnumConstructor.Map.bindings (EnumName.Map.find e_name ctx.ctx_enums))
in
let tmp_var = LocalName.fresh ("match_arg", Pos.no_pos) in
Format.fprintf fmt "%a = %a@\n@[<hov 4>if %a@]" format_var tmp_var
@ -443,7 +444,7 @@ let format_ctx
(fmt : Format.formatter)
(ctx : decl_ctx) : unit =
let format_struct_decl fmt (struct_name, struct_fields) =
let fields = StructFieldMap.bindings struct_fields in
let fields = StructField.Map.bindings struct_fields in
Format.fprintf fmt
"class %a:@\n\
\ def __init__(self, %a) -> None:@\n\
@ -467,7 +468,7 @@ let format_ctx
Format.fprintf fmt "%a: %a" format_struct_field_name struct_field
format_typ struct_field_type))
fields
(if StructFieldMap.is_empty struct_fields then fun fmt _ ->
(if StructField.Map.is_empty struct_fields then fun fmt _ ->
Format.fprintf fmt " pass"
else
Format.pp_print_list
@ -476,7 +477,7 @@ let format_ctx
Format.fprintf fmt " self.%a = %a" format_struct_field_name
struct_field format_struct_field_name struct_field))
fields format_struct_name struct_name
(if not (StructFieldMap.is_empty struct_fields) then
(if not (StructField.Map.is_empty struct_fields) then
Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt " and@ ")
(fun fmt (struct_field, _) ->
@ -496,7 +497,7 @@ let format_ctx
fields
in
let format_enum_decl fmt (enum_name, enum_cons) =
if EnumConstructorMap.is_empty enum_cons then
if EnumConstructor.Map.is_empty enum_cons then
failwith "no constructors in the enum"
else
Format.fprintf fmt
@ -529,7 +530,7 @@ let format_ctx
Format.fprintf fmt "%a = %d" format_enum_cons_name enum_cons i))
(List.mapi
(fun i (x, y) -> i, x, y)
(EnumConstructorMap.bindings enum_cons))
(EnumConstructor.Map.bindings enum_cons))
format_enum_name enum_name format_enum_name enum_name format_enum_name
enum_name
in
@ -545,8 +546,8 @@ let format_ctx
let scope_structs =
List.map
(fun (s, _) -> Scopelang.Dependency.TVertex.Struct s)
(StructMap.bindings
(StructMap.filter
(StructName.Map.bindings
(StructName.Map.filter
(fun s _ -> not (is_in_type_ordering s))
ctx.ctx_structs))
in
@ -555,10 +556,10 @@ let format_ctx
match struct_or_enum with
| Scopelang.Dependency.TVertex.Struct s ->
Format.fprintf fmt "%a@\n@\n" format_struct_decl
(s, StructMap.find s ctx.ctx_structs)
(s, StructName.Map.find s ctx.ctx_structs)
| Scopelang.Dependency.TVertex.Enum e ->
Format.fprintf fmt "%a@\n@\n" format_enum_decl
(e, EnumMap.find e ctx.ctx_enums))
(e, EnumName.Map.find e ctx.ctx_enums))
(type_ordering @ scope_structs)
let format_program

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
type location = scopelang glocation
@ -46,13 +46,13 @@ type 'm rule =
type 'm scope_decl = {
scope_decl_name : ScopeName.t;
scope_sig : (typ * Desugared.Ast.io) ScopeVarMap.t;
scope_sig : (typ * Desugared.Ast.io) ScopeVar.Map.t;
scope_decl_rules : 'm rule list;
scope_mark : 'm mark;
}
type 'm program = {
program_scopes : 'm scope_decl ScopeMap.t;
program_scopes : 'm scope_decl ScopeName.Map.t;
program_ctx : decl_ctx;
}
@ -70,17 +70,17 @@ let type_rule decl_ctx env = function
let type_program (prg : 'm program) : typed program =
let typing_env =
ScopeMap.fold
ScopeName.Map.fold
(fun scope_name scope_decl ->
let vars = ScopeVarMap.map fst scope_decl.scope_sig in
let vars = ScopeVar.Map.map fst scope_decl.scope_sig in
Typing.Env.add_scope scope_name ~vars)
prg.program_scopes Typing.Env.empty
in
let program_scopes =
ScopeMap.map
ScopeName.Map.map
(fun scope_decl ->
let typing_env =
ScopeVarMap.fold
ScopeVar.Map.fold
(fun svar (typ, _) env -> Typing.Env.add_scope_var svar typ env)
scope_decl.scope_sig typing_env
in

View File

@ -16,7 +16,7 @@
(** Abstract syntax tree of the scope language *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Identifiers} *)
@ -38,13 +38,13 @@ type 'm rule =
type 'm scope_decl = {
scope_decl_name : ScopeName.t;
scope_sig : (typ * Desugared.Ast.io) ScopeVarMap.t;
scope_sig : (typ * Desugared.Ast.io) ScopeVar.Map.t;
scope_decl_rules : 'm rule list;
scope_mark : 'm mark;
}
type 'm program = {
program_scopes : 'm scope_decl ScopeMap.t;
program_scopes : 'm scope_decl ScopeName.Map.t;
program_ctx : decl_ctx;
}

View File

@ -17,7 +17,7 @@
(** Graph representation of the dependencies between scopes in the Catala
program. Vertices are functions, x -> y if x is used in the definition of y. *)
open Utils
open Catala_utils
open Shared_ast
module SVertex = ScopeName
@ -41,12 +41,12 @@ module SSCC = Graph.Components.Make (SDependencies)
let rec expr_used_scopes e =
let recurse_subterms e =
Expr.shallow_fold
(fun e -> ScopeMap.union (fun _ x _ -> Some x) (expr_used_scopes e))
e ScopeMap.empty
(fun e -> ScopeName.Map.union (fun _ x _ -> Some x) (expr_used_scopes e))
e ScopeName.Map.empty
in
match e with
| (EScopeCall { scope; _ }, m) as e ->
ScopeMap.add scope (Expr.mark_pos m) (recurse_subterms e)
ScopeName.Map.add scope (Expr.mark_pos m) (recurse_subterms e)
| EAbs { binder; _ }, _ ->
let _, body = Bindlib.unmbind binder in
expr_used_scopes body
@ -58,28 +58,28 @@ let rule_used_scopes = function
walking through all exprs again *)
expr_used_scopes e
| Ast.Call (subscope, subindex, _) ->
ScopeMap.singleton subscope
ScopeName.Map.singleton subscope
(Marked.get_mark (SubScopeName.get_info subindex))
let build_program_dep_graph (prgm : 'm Ast.program) : SDependencies.t =
let g = SDependencies.empty in
let g =
ScopeMap.fold
ScopeName.Map.fold
(fun v _ g -> SDependencies.add_vertex g v)
prgm.program_scopes g
in
ScopeMap.fold
ScopeName.Map.fold
(fun scope_name scope g ->
List.fold_left
(fun g rule ->
let used_scopes = rule_used_scopes rule in
if ScopeMap.mem scope_name used_scopes then
if ScopeName.Map.mem scope_name used_scopes then
Errors.raise_spanned_error
(Marked.get_mark (ScopeName.get_info scope.Ast.scope_decl_name))
"The scope %a is calling into itself as a subscope, which is \
forbidden since Catala does not provide recursion"
ScopeName.format_t scope.Ast.scope_decl_name;
ScopeMap.fold
ScopeName.Map.fold
(fun used_scope pos g ->
let edge = SDependencies.E.create used_scope pos scope_name in
SDependencies.add_edge_e g edge)
@ -190,9 +190,9 @@ let build_type_graph (structs : struct_ctx) (enums : enum_ctx) : TDependencies.t
=
let g = TDependencies.empty in
let g =
StructMap.fold
StructName.Map.fold
(fun s fields g ->
StructFieldMap.fold
StructField.Map.fold
(fun _ typ g ->
let def = TVertex.Struct s in
let g = TDependencies.add_vertex g def in
@ -214,9 +214,9 @@ let build_type_graph (structs : struct_ctx) (enums : enum_ctx) : TDependencies.t
structs g
in
let g =
EnumMap.fold
EnumName.Map.fold
(fun e cases g ->
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun _ typ g ->
let def = TVertex.Enum e in
let g = TDependencies.add_vertex g def in

View File

@ -17,7 +17,7 @@
(** Graph representation of the dependencies between scopes in the Catala
program. Vertices are functions, x -> y if x is used in the definition of y. *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Scope dependencies} *)

View File

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

View File

@ -16,7 +16,7 @@
(** Translation from {!module: Desugared.Ast} to {!module: Scopelang.Ast} *)
open Utils
open Catala_utils
open Shared_ast
(** {1 Expression translation}*)
@ -26,14 +26,15 @@ type target_scope_vars =
| States of (StateName.t * ScopeVar.t) list
type ctx = {
scope_var_mapping : target_scope_vars ScopeVarMap.t;
decl_ctx : decl_ctx;
scope_var_mapping : target_scope_vars ScopeVar.Map.t;
var_mapping : (Desugared.Ast.expr, untyped Ast.expr Var.t) Var.Map.t;
}
let tag_with_log_entry
(e : untyped Ast.expr boxed)
(l : log_entry)
(markings : Utils.Uid.MarkedString.info list) : untyped Ast.expr boxed =
(markings : Uid.MarkedString.info list) : untyped Ast.expr boxed =
Expr.eapp
(Expr.eop (Unop (Log (l, markings))) (Marked.get_mark e))
[e] (Marked.get_mark e)
@ -46,7 +47,7 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
(* When referring to a subscope variable in an expression, we are referring
to the output, hence we take the last state. *)
let new_s_var =
match ScopeVarMap.find (Marked.unmark s_var) ctx.scope_var_mapping with
match ScopeVar.Map.find (Marked.unmark s_var) ctx.scope_var_mapping with
| WholeVar new_s_var -> Marked.same_mark_as new_s_var s_var
| States states ->
Marked.same_mark_as (snd (List.hd (List.rev states))) s_var
@ -56,7 +57,7 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
Expr.elocation
(ScopelangScopeVar
(match
ScopeVarMap.find (Marked.unmark s_var) ctx.scope_var_mapping
ScopeVar.Map.find (Marked.unmark s_var) ctx.scope_var_mapping
with
| WholeVar new_s_var -> Marked.same_mark_as new_s_var s_var
| States _ -> failwith "should not happen"))
@ -65,27 +66,44 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
Expr.elocation
(ScopelangScopeVar
(match
ScopeVarMap.find (Marked.unmark s_var) ctx.scope_var_mapping
ScopeVar.Map.find (Marked.unmark s_var) ctx.scope_var_mapping
with
| WholeVar _ -> failwith "should not happen"
| States states -> Marked.same_mark_as (List.assoc state states) s_var))
m
| EVar v -> Expr.evar (Var.Map.find v ctx.var_mapping) m
| EStruct { name; fields } ->
Expr.estruct name (StructFieldMap.map (translate_expr ctx) fields) m
| EStructAccess { e; field; name } ->
Expr.estructaccess (translate_expr ctx e) field name m
Expr.estruct name (StructField.Map.map (translate_expr ctx) fields) m
| EDStructAccess { name_opt = None; _ } ->
(* Note: this could only happen if disambiguation was disabled. If we want
to support it, we should still allow this case when the field has only
one possible matching structure *)
Errors.raise_spanned_error (Expr.mark_pos m)
"Ambiguous structure field access"
| EDStructAccess { e; field; name_opt = Some name } ->
let e' = translate_expr ctx e in
let field =
try
StructName.Map.find name
(IdentName.Map.find field ctx.decl_ctx.ctx_struct_fields)
with Not_found ->
(* Should not happen after disambiguation *)
Errors.raise_spanned_error (Expr.mark_pos m)
"Field %s does not belong to structure %a" field StructName.format_t
name
in
Expr.estructaccess e' field name m
| EInj { e; cons; name } -> Expr.einj (translate_expr ctx e) cons name m
| EMatch { e; name; cases } ->
Expr.ematch (translate_expr ctx e) name
(EnumConstructorMap.map (translate_expr ctx) cases)
(EnumConstructor.Map.map (translate_expr ctx) cases)
m
| EScopeCall { scope; args } ->
Expr.escopecall scope
(ScopeVarMap.fold
(ScopeVar.Map.fold
(fun v e args' ->
let v' =
match ScopeVarMap.find v ctx.scope_var_mapping with
match ScopeVar.Map.find v ctx.scope_var_mapping with
| WholeVar v' -> v'
| States ((_, v') :: _) ->
(* When there are multiple states, the input is always the first
@ -93,8 +111,8 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
v'
| States [] -> assert false
in
ScopeVarMap.add v' (translate_expr ctx e) args')
args ScopeVarMap.empty)
ScopeVar.Map.add v' (translate_expr ctx e) args')
args ScopeVar.Map.empty)
m
| ELit
(( LBool _ | LEmptyError | LInt _ | LRat _ | LMoney _ | LUnit | LDate _
@ -112,7 +130,7 @@ let rec translate_expr (ctx : ctx) (e : Desugared.Ast.expr) :
Expr.eabs (Expr.bind new_vars (translate_expr ctx body)) tys m
| EApp { f; args } ->
Expr.eapp (translate_expr ctx f) (List.map (translate_expr ctx) args) m
| EOp op -> Expr.eop op m
| EOp op -> Expr.eop (Expr.translate_op op) m
| EDefault { excepts; just; cons } ->
Expr.edefault
(List.map (translate_expr ctx) excepts)
@ -139,7 +157,7 @@ type rule_tree =
priorities declared between rules *)
let def_map_to_tree
(def_info : Desugared.Ast.ScopeDef.t)
(def : Desugared.Ast.rule RuleMap.t) : rule_tree list =
(def : Desugared.Ast.rule RuleName.Map.t) : rule_tree list =
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
@ -153,12 +171,14 @@ let def_map_to_tree
else base_cases)
exc_graph []
in
let rec build_tree (base_cases : RuleSet.t) : rule_tree =
let rec build_tree (base_cases : RuleName.Set.t) : rule_tree =
let exceptions =
Desugared.Dependency.ExceptionsDependencies.pred exc_graph base_cases
in
let base_case_as_rule_list =
List.map (fun r -> RuleMap.find r def) (RuleSet.elements base_cases)
List.map
(fun r -> RuleName.Map.find r def)
(RuleName.Set.elements base_cases)
in
match exceptions with
| [] -> Leaf base_case_as_rule_list
@ -286,7 +306,7 @@ let rec rule_tree_to_expr
let translate_def
(ctx : ctx)
(def_info : Desugared.Ast.ScopeDef.t)
(def : Desugared.Ast.rule RuleMap.t)
(def : Desugared.Ast.rule RuleName.Map.t)
(typ : typ)
(io : Desugared.Ast.io)
~(is_cond : bool)
@ -298,9 +318,9 @@ let translate_def
let is_rule_func _ (r : Desugared.Ast.rule) : bool =
Option.is_some r.Desugared.Ast.rule_parameter
in
let all_rules_func = RuleMap.for_all is_rule_func def in
let all_rules_func = RuleName.Map.for_all is_rule_func def in
let all_rules_not_func =
RuleMap.for_all (fun n r -> not (is_rule_func n r)) def
RuleName.Map.for_all (fun n r -> not (is_rule_func n r)) def
in
let is_def_func_param_typ : typ option =
if is_def_func && all_rules_func then
@ -318,13 +338,13 @@ let translate_def
(fun (_, r) ->
( Some "This definition is a function:",
Expr.pos r.Desugared.Ast.rule_cons ))
(RuleMap.bindings (RuleMap.filter is_rule_func def))
(RuleName.Map.bindings (RuleName.Map.filter is_rule_func def))
@ List.map
(fun (_, r) ->
( Some "This definition is not a function:",
Expr.pos r.Desugared.Ast.rule_cons ))
(RuleMap.bindings
(RuleMap.filter (fun n r -> not (is_rule_func n r)) def))
(RuleName.Map.bindings
(RuleName.Map.filter (fun n r -> not (is_rule_func n r)) def))
in
Errors.raise_multispanned_error spans
"some definitions of the same variable are functions while others \
@ -353,7 +373,7 @@ let translate_def
else None
in
if
RuleMap.cardinal def = 0
RuleName.Map.cardinal def = 0
&& is_subscope_var
(* 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
@ -411,6 +431,158 @@ let translate_def
is_def_func_param_typ;
] ))
let translate_rule ctx (scope : Desugared.Ast.scope) = function
| Desugared.Dependency.Vertex.Var (var, state) -> (
let scope_def =
Desugared.Ast.ScopeDefMap.find
(Desugared.Ast.ScopeDef.Var (var, state))
scope.scope_defs
in
let var_def = scope_def.scope_def_rules in
let var_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in
match Marked.unmark scope_def.Desugared.Ast.scope_def_io.io_input with
| OnlyInput when not (RuleName.Map.is_empty var_def) ->
(* If the variable is tagged as input, then it shall not be redefined. *)
Errors.raise_multispanned_error
((Some "Incriminated variable:", Marked.get_mark (ScopeVar.get_info var))
:: List.map
(fun (rule, _) ->
( Some "Incriminated variable definition:",
Marked.get_mark (RuleName.get_info rule) ))
(RuleName.Map.bindings var_def))
"It is impossible to give a definition to a scope variable tagged as \
input."
| OnlyInput -> []
(* we do not provide any definition for an input-only variable *)
| _ ->
let expr_def =
translate_def ctx
(Desugared.Ast.ScopeDef.Var (var, state))
var_def var_typ scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:false
in
let scope_var =
match ScopeVar.Map.find var ctx.scope_var_mapping, state with
| WholeVar v, None -> v
| States states, Some state -> List.assoc state states
| _ -> failwith "should not happen"
in
[
Ast.Definition
( ( ScopelangScopeVar
(scope_var, Marked.get_mark (ScopeVar.get_info scope_var)),
Marked.get_mark (ScopeVar.get_info scope_var) ),
var_typ,
scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def );
])
| Desugared.Dependency.Vertex.SubScope sub_scope_index ->
(* Before calling the sub_scope, we need to include all the re-definitions
of subscope parameters*)
let sub_scope =
SubScopeName.Map.find sub_scope_index scope.scope_sub_scopes
in
let sub_scope_vars_redefs_candidates =
Desugared.Ast.ScopeDefMap.filter
(fun def_key scope_def ->
match def_key with
| Desugared.Ast.ScopeDef.Var _ -> false
| Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_index', _, _) ->
sub_scope_index = sub_scope_index'
(* We exclude subscope variables that have 0 re-definitions and are
not visible in the input of the subscope *)
&& not
((match
Marked.unmark scope_def.Desugared.Ast.scope_def_io.io_input
with
| Desugared.Ast.NoInput -> true
| _ -> false)
&& RuleName.Map.is_empty scope_def.scope_def_rules))
scope.scope_defs
in
let sub_scope_vars_redefs =
Desugared.Ast.ScopeDefMap.mapi
(fun def_key scope_def ->
let def = scope_def.Desugared.Ast.scope_def_rules in
let def_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in
match def_key with
| Desugared.Ast.ScopeDef.Var _ -> assert false (* should not happen *)
| Desugared.Ast.ScopeDef.SubScopeVar (sscope, sub_scope_var, pos) ->
(* This definition redefines a variable of the correct subscope. But
we have to check that this redefinition is allowed with respect
to the io parameters of that subscope variable. *)
(match
Marked.unmark scope_def.Desugared.Ast.scope_def_io.io_input
with
| Desugared.Ast.NoInput ->
Errors.raise_multispanned_error
(( Some "Incriminated subscope:",
Marked.get_mark (SubScopeName.get_info sscope) )
:: ( Some "Incriminated variable:",
Marked.get_mark (ScopeVar.get_info sub_scope_var) )
:: List.map
(fun (rule, _) ->
( Some "Incriminated subscope variable definition:",
Marked.get_mark (RuleName.get_info rule) ))
(RuleName.Map.bindings def))
"It is impossible to give a definition to a subscope variable \
not tagged as input or context."
| OnlyInput when RuleName.Map.is_empty def && not is_cond ->
(* If the subscope variable is tagged as input, then it shall be
defined. *)
Errors.raise_multispanned_error
[
( Some "Incriminated subscope:",
Marked.get_mark (SubScopeName.get_info sscope) );
Some "Incriminated variable:", pos;
]
"This subscope variable is a mandatory input but no definition \
was provided."
| _ -> ());
(* Now that all is good, we can proceed with translating this
redefinition to a proper Scopelang term. *)
let expr_def =
translate_def ctx def_key def def_typ
scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:true
in
let subscop_real_name =
SubScopeName.Map.find sub_scope_index scope.scope_sub_scopes
in
let var_pos = Desugared.Ast.ScopeDef.get_position def_key in
Ast.Definition
( ( SubScopeVar
( subscop_real_name,
(sub_scope_index, var_pos),
match
ScopeVar.Map.find sub_scope_var ctx.scope_var_mapping
with
| WholeVar v -> v, var_pos
| States states ->
(* When defining a sub-scope variable, we always define
its first state in the sub-scope. *)
snd (List.hd states), var_pos ),
var_pos ),
def_typ,
scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def ))
sub_scope_vars_redefs_candidates
in
let sub_scope_vars_redefs =
List.map snd (Desugared.Ast.ScopeDefMap.bindings sub_scope_vars_redefs)
in
sub_scope_vars_redefs
@ [
Ast.Call
( sub_scope,
sub_scope_index,
Untyped
{ pos = Marked.get_mark (SubScopeName.get_info sub_scope_index) }
);
]
(** Translates a scope *)
let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
untyped Ast.scope_decl =
@ -422,183 +594,7 @@ let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
Desugared.Dependency.correct_computation_ordering scope_dependencies
in
let scope_decl_rules =
List.flatten
(List.map
(fun vertex ->
match vertex with
| Desugared.Dependency.Vertex.Var (var, state) -> (
let scope_def =
Desugared.Ast.ScopeDefMap.find
(Desugared.Ast.ScopeDef.Var (var, state))
scope.scope_defs
in
let var_def = scope_def.scope_def_rules in
let var_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in
match
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
redefined. *)
Errors.raise_multispanned_error
(( Some "Incriminated variable:",
Marked.get_mark (ScopeVar.get_info var) )
:: List.map
(fun (rule, _) ->
( Some "Incriminated variable definition:",
Marked.get_mark (RuleName.get_info rule) ))
(RuleMap.bindings var_def))
"It is impossible to give a definition to a scope variable \
tagged as input."
| OnlyInput ->
[]
(* we do not provide any definition for an input-only variable *)
| _ ->
let expr_def =
translate_def ctx
(Desugared.Ast.ScopeDef.Var (var, state))
var_def var_typ scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:false
in
let scope_var =
match ScopeVarMap.find var ctx.scope_var_mapping, state with
| WholeVar v, None -> v
| States states, Some state -> List.assoc state states
| _ -> failwith "should not happen"
in
[
Ast.Definition
( ( ScopelangScopeVar
( scope_var,
Marked.get_mark (ScopeVar.get_info scope_var) ),
Marked.get_mark (ScopeVar.get_info scope_var) ),
var_typ,
scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def );
])
| Desugared.Dependency.Vertex.SubScope sub_scope_index ->
(* Before calling the sub_scope, we need to include all the
re-definitions of subscope parameters*)
let sub_scope =
SubScopeMap.find sub_scope_index scope.scope_sub_scopes
in
let sub_scope_vars_redefs_candidates =
Desugared.Ast.ScopeDefMap.filter
(fun def_key scope_def ->
match def_key with
| Desugared.Ast.ScopeDef.Var _ -> false
| Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_index', _, _)
->
sub_scope_index = sub_scope_index'
(* We exclude subscope variables that have 0 re-definitions
and are not visible in the input of the subscope *)
&& not
((match
Marked.unmark
scope_def.Desugared.Ast.scope_def_io.io_input
with
| Desugared.Ast.NoInput -> true
| _ -> false)
&& RuleMap.is_empty scope_def.scope_def_rules))
scope.scope_defs
in
let sub_scope_vars_redefs =
Desugared.Ast.ScopeDefMap.mapi
(fun def_key scope_def ->
let def = scope_def.Desugared.Ast.scope_def_rules in
let def_typ = scope_def.scope_def_typ in
let is_cond = scope_def.scope_def_is_condition in
match def_key with
| Desugared.Ast.ScopeDef.Var _ ->
assert false (* should not happen *)
| Desugared.Ast.ScopeDef.SubScopeVar
(sscope, sub_scope_var, pos) ->
(* This definition redefines a variable of the correct
subscope. But we have to check that this redefinition is
allowed with respect to the io parameters of that
subscope variable. *)
(match
Marked.unmark
scope_def.Desugared.Ast.scope_def_io.io_input
with
| Desugared.Ast.NoInput ->
Errors.raise_multispanned_error
(( Some "Incriminated subscope:",
Marked.get_mark (SubScopeName.get_info sscope) )
:: ( Some "Incriminated variable:",
Marked.get_mark (ScopeVar.get_info sub_scope_var)
)
:: List.map
(fun (rule, _) ->
( Some
"Incriminated subscope variable definition:",
Marked.get_mark (RuleName.get_info rule) ))
(RuleMap.bindings def))
"It is impossible to give a definition to a subscope \
variable not tagged as input or context."
| OnlyInput when RuleMap.is_empty def && not is_cond ->
(* If the subscope variable is tagged as input, then it
shall be defined. *)
Errors.raise_multispanned_error
[
( Some "Incriminated subscope:",
Marked.get_mark (SubScopeName.get_info sscope) );
Some "Incriminated variable:", pos;
]
"This subscope variable is a mandatory input but no \
definition was provided."
| _ -> ());
(* Now that all is good, we can proceed with translating
this redefinition to a proper Scopelang term. *)
let expr_def =
translate_def ctx def_key def def_typ
scope_def.Desugared.Ast.scope_def_io ~is_cond
~is_subscope_var:true
in
let subscop_real_name =
SubScopeMap.find sub_scope_index scope.scope_sub_scopes
in
let var_pos =
Desugared.Ast.ScopeDef.get_position def_key
in
Ast.Definition
( ( SubScopeVar
( subscop_real_name,
(sub_scope_index, var_pos),
match
ScopeVarMap.find sub_scope_var
ctx.scope_var_mapping
with
| WholeVar v -> v, var_pos
| States states ->
(* When defining a sub-scope variable, we
always define its first state in the
sub-scope. *)
snd (List.hd states), var_pos ),
var_pos ),
def_typ,
scope_def.Desugared.Ast.scope_def_io,
Expr.unbox expr_def ))
sub_scope_vars_redefs_candidates
in
let sub_scope_vars_redefs =
List.map snd
(Desugared.Ast.ScopeDefMap.bindings sub_scope_vars_redefs)
in
sub_scope_vars_redefs
@ [
Ast.Call
( sub_scope,
sub_scope_index,
Untyped
{
pos =
Marked.get_mark
(SubScopeName.get_info sub_scope_index);
} );
])
scope_ordering)
List.flatten (List.map (translate_rule ctx scope) scope_ordering)
in
(* Then, after having computed all the scopes variables, we add the
assertions. TODO: the assertions should be interleaved with the
@ -612,7 +608,7 @@ let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
scope.Desugared.Ast.scope_assertions
in
let scope_sig =
ScopeVarMap.fold
ScopeVar.Map.fold
(fun var (states : Desugared.Ast.var_or_states) acc ->
match states with
| WholeVar ->
@ -622,8 +618,8 @@ let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
scope.scope_defs
in
let typ = scope_def.scope_def_typ in
ScopeVarMap.add
(match ScopeVarMap.find var ctx.scope_var_mapping with
ScopeVar.Map.add
(match ScopeVar.Map.find var ctx.scope_var_mapping with
| WholeVar v -> v
| States _ -> failwith "should not happen")
(typ, scope_def.scope_def_io)
@ -639,14 +635,14 @@ let translate_scope (ctx : ctx) (scope : Desugared.Ast.scope) :
(Desugared.Ast.ScopeDef.Var (var, Some state))
scope.scope_defs
in
ScopeVarMap.add
(match ScopeVarMap.find var ctx.scope_var_mapping with
ScopeVar.Map.add
(match ScopeVar.Map.find var ctx.scope_var_mapping with
| WholeVar _ -> failwith "should not happen"
| States states' -> List.assoc state states')
(scope_def.scope_def_typ, scope_def.scope_def_io)
acc)
acc states)
scope.scope_vars ScopeVarMap.empty
scope.scope_vars ScopeVar.Map.empty
in
let pos = Marked.get_mark (ScopeName.get_info scope.scope_uid) in
{
@ -665,61 +661,56 @@ let translate_program (pgrm : Desugared.Ast.program) : untyped Ast.program =
let ctx =
(* 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 *)
ScopeMap.fold
ScopeName.Map.fold
(fun _scope scope_decl ctx ->
ScopeVarMap.fold
ScopeVar.Map.fold
(fun scope_var (states : Desugared.Ast.var_or_states) ctx ->
match states with
| Desugared.Ast.WholeVar ->
{
ctx with
scope_var_mapping =
ScopeVarMap.add scope_var
(WholeVar (ScopeVar.fresh (ScopeVar.get_info scope_var)))
ctx.scope_var_mapping;
}
| States states ->
{
ctx with
scope_var_mapping =
ScopeVarMap.add scope_var
(States
(List.map
(fun state ->
( state,
ScopeVar.fresh
(let state_name, state_pos =
StateName.get_info state
in
( Marked.unmark (ScopeVar.get_info scope_var)
^ "_"
^ state_name,
state_pos )) ))
states))
ctx.scope_var_mapping;
})
let var_name, var_pos = ScopeVar.get_info scope_var in
let new_var =
match states with
| Desugared.Ast.WholeVar ->
WholeVar (ScopeVar.fresh (var_name, var_pos))
| States states ->
let var_prefix = var_name ^ "_" in
let state_var state =
ScopeVar.fresh
(Marked.map_under_mark (( ^ ) var_prefix)
(StateName.get_info state))
in
States (List.map (fun state -> state, state_var state) states)
in
{
ctx with
scope_var_mapping =
ScopeVar.Map.add scope_var new_var ctx.scope_var_mapping;
})
scope_decl.Desugared.Ast.scope_vars ctx)
pgrm.Desugared.Ast.program_scopes
{ scope_var_mapping = ScopeVarMap.empty; var_mapping = Var.Map.empty }
{
scope_var_mapping = ScopeVar.Map.empty;
var_mapping = Var.Map.empty;
decl_ctx = pgrm.program_ctx;
}
in
let ctx_scopes =
ScopeMap.map
ScopeName.Map.map
(fun out_str ->
let out_struct_fields =
ScopeVarMap.fold
ScopeVar.Map.fold
(fun var fld out_map ->
let var' =
match ScopeVarMap.find var ctx.scope_var_mapping with
match ScopeVar.Map.find var ctx.scope_var_mapping with
| WholeVar v -> v
| States l -> snd (List.hd (List.rev l))
in
ScopeVarMap.add var' fld out_map)
out_str.out_struct_fields ScopeVarMap.empty
ScopeVar.Map.add var' fld out_map)
out_str.out_struct_fields ScopeVar.Map.empty
in
{ out_str with out_struct_fields })
pgrm.Desugared.Ast.program_ctx.ctx_scopes
in
{
Ast.program_scopes = ScopeMap.map (translate_scope ctx) pgrm.program_scopes;
Ast.program_scopes =
ScopeName.Map.map (translate_scope ctx) pgrm.program_scopes;
program_ctx = { pgrm.program_ctx with ctx_scopes };
}

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Ast
@ -22,22 +22,22 @@ let struc
ctx
(fmt : Format.formatter)
(name : StructName.t)
(fields : typ StructFieldMap.t) : unit =
(fields : typ StructField.Map.t) : unit =
Format.fprintf fmt "%a %a %a %a@\n@[<hov 2> %a@]@\n%a" Print.keyword "struct"
StructName.format_t name Print.punctuation "=" Print.punctuation "{"
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "@\n")
(fun fmt (field_name, typ) ->
Format.fprintf fmt "%a%a %a" StructFieldName.format_t field_name
Format.fprintf fmt "%a%a %a" StructField.format_t field_name
Print.punctuation ":" (Print.typ ctx) typ))
(StructFieldMap.bindings fields)
(StructField.Map.bindings fields)
Print.punctuation "}"
let enum
ctx
(fmt : Format.formatter)
(name : EnumName.t)
(cases : typ EnumConstructorMap.t) : unit =
(cases : typ EnumConstructor.Map.t) : unit =
Format.fprintf fmt "%a %a %a @\n@[<hov 2> %a@]" Print.keyword "enum"
EnumName.format_t name Print.punctuation "="
(Format.pp_print_list
@ -46,7 +46,7 @@ let enum
Format.fprintf fmt "%a %a%a %a" Print.punctuation "|"
EnumConstructor.format_t field_name Print.punctuation ":"
(Print.typ ctx) typ))
(EnumConstructorMap.bindings cases)
(EnumConstructor.Map.bindings cases)
let scope ?(debug = false) ctx fmt (name, decl) =
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@ %a@ %a@]@\n@[<v 2> %a@]"
@ -65,7 +65,7 @@ let scope ?(debug = false) ctx fmt (name, decl) =
"output"
else fun fmt () -> Format.fprintf fmt "@<0>")
() Print.punctuation ")"))
(ScopeVarMap.bindings decl.scope_sig)
(ScopeVar.Map.bindings decl.scope_sig)
Print.punctuation "="
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt "%a@ " Print.punctuation ";")
@ -81,7 +81,7 @@ let scope ?(debug = false) ctx fmt (name, decl) =
| ScopelangScopeVar v -> (
match
Marked.unmark
(snd (ScopeVarMap.find (Marked.unmark v) decl.scope_sig))
(snd (ScopeVar.Map.find (Marked.unmark v) decl.scope_sig))
.io_input
with
| Reentrant ->
@ -106,16 +106,16 @@ let program ?(debug : bool = false) (fmt : Format.formatter) (p : 'm program) :
Format.pp_print_cut fmt ()
in
Format.pp_open_vbox fmt 0;
StructMap.iter
StructName.Map.iter
(fun n s ->
struc ctx fmt n s;
pp_sep fmt ())
ctx.ctx_structs;
EnumMap.iter
EnumName.Map.iter
(fun n e ->
enum ctx fmt n e;
pp_sep fmt ())
ctx.ctx_enums;
Format.pp_print_list ~pp_sep (scope ~debug ctx) fmt
(ScopeMap.bindings p.program_scopes);
(ScopeName.Map.bindings p.program_scopes);
Format.pp_close_box fmt ()

View File

@ -20,73 +20,47 @@
(* Doesn't define values, so OK to have without an mli *)
open Utils
open Catala_utils
module Runtime = Runtime_ocaml.Runtime
module ScopeName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module ScopeSet : Set.S with type elt = ScopeName.t = Set.Make (ScopeName)
module ScopeMap : Map.S with type key = ScopeName.t = Map.Make (ScopeName)
module StructName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module StructFieldName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module StructMap : Map.S with type key = StructName.t = Map.Make (StructName)
module EnumName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module EnumConstructor : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module EnumMap : Map.S with type key = EnumName.t = Map.Make (EnumName)
module ScopeName = Uid.Gen ()
module StructName = Uid.Gen ()
module StructField = Uid.Gen ()
module EnumName = Uid.Gen ()
module EnumConstructor = Uid.Gen ()
(** Only used by surface *)
module RuleName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module RuleName = Uid.Gen ()
module LabelName = Uid.Gen ()
module RuleMap : Map.S with type key = RuleName.t = Map.Make (RuleName)
module RuleSet : Set.S with type elt = RuleName.t = Set.Make (RuleName)
(** Used for unresolved structs/maps in desugared *)
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)
module IdentName = String
(** Only used by desugared/scopelang *)
module ScopeVar : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module ScopeVarSet : Set.S with type elt = ScopeVar.t = Set.Make (ScopeVar)
module ScopeVarMap : Map.S with type key = ScopeVar.t = Map.Make (ScopeVar)
module SubScopeName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module SubScopeNameSet : Set.S with type elt = SubScopeName.t =
Set.Make (SubScopeName)
module SubScopeMap : Map.S with type key = SubScopeName.t =
Map.Make (SubScopeName)
module StructFieldMap : Map.S with type key = StructFieldName.t =
Map.Make (StructFieldName)
module EnumConstructorMap : Map.S with type key = EnumConstructor.t =
Map.Make (EnumConstructor)
module StateName : Uid.Id with type info = Uid.MarkedString.info =
Uid.Make (Uid.MarkedString) ()
module ScopeVar = Uid.Gen ()
module SubScopeName = Uid.Gen ()
module StateName = Uid.Gen ()
(** {1 Abstract syntax tree} *)
(** Define a common base type for the expressions in most passes of the compiler *)
type desugared = [ `Desugared ]
(** {2 Phantom types used to select relevant cases on the generic AST}
we instantiate them with a polymorphic variant to take advantage of
sub-typing. The values aren't actually used. *)
type scopelang = [ `Scopelang ]
type dcalc = [ `Dcalc ]
type lcalc = [ `Lcalc ]
type 'a any = [< desugared | scopelang | dcalc | lcalc ] as 'a
(** ['a any] is 'a, but adds the constraint that it should be restricted to
valid AST kinds *)
(** {2 Types} *)
type typ_lit = TBool | TUnit | TInt | TRat | TMoney | TDate | TDuration
@ -108,27 +82,28 @@ and naked_typ =
type date = Runtime.date
type duration = Runtime.duration
type op_kind =
| KInt
| KRat
| KMoney
| KDate
| KDuration (** All ops don't have a KDate and KDuration. *)
type 'a op_kind =
(* | Kpoly: desugared op_kind -- Coming soon ! *)
| KInt : 'a any op_kind
| KRat : 'a any op_kind
| KMoney : 'a any op_kind
| KDate : 'a any op_kind
| KDuration : 'a any op_kind (** All ops don't have a KDate and KDuration. *)
type ternop = Fold
type binop =
type 'a binop =
| And
| Or
| Xor
| Add of op_kind
| Sub of op_kind
| Mult of op_kind
| Div of op_kind
| Lt of op_kind
| Lte of op_kind
| Gt of op_kind
| Gte of op_kind
| Add of 'a op_kind
| Sub of 'a op_kind
| Mult of 'a op_kind
| Div of 'a op_kind
| Lt of 'a op_kind
| Lte of 'a op_kind
| Gt of 'a op_kind
| Gte of 'a op_kind
| Eq
| Neq
| Map
@ -143,9 +118,9 @@ type log_entry =
| EndCall
| PosRecordIfTrueBool
type unop =
type 'a unop =
| Not
| Minus of op_kind
| Minus of 'a op_kind
| Log of log_entry * Uid.MarkedString.info list
| Length
| IntToRat
@ -159,19 +134,13 @@ type unop =
| RoundMoney
| RoundDecimal
type operator = Ternop of ternop | Binop of binop | Unop of unop
type 'a operator = Ternop of ternop | Binop of 'a binop | Unop of 'a unop
type except = ConflictError | EmptyError | NoValueProvided | Crash
(** {2 Generic expressions} *)
(** Define a common base type for the expressions in most passes of the compiler *)
type desugared = [ `Desugared ]
type scopelang = [ `Scopelang ]
type dcalc = [ `Dcalc ]
type lcalc = [ `Lcalc ]
type 'a any = [< desugared | scopelang | dcalc | lcalc ] as 'a
(** Literals are the same throughout compilation except for the [LEmptyError]
case which is eliminated midway through. *)
type 'a glit =
@ -216,7 +185,7 @@ and ('a, 't) naked_gexpr =
args : ('a, 't) gexpr list;
}
-> ('a any, 't) naked_gexpr
| EOp : operator -> ('a any, 't) naked_gexpr
| EOp : 'a operator -> ('a any, 't) naked_gexpr
| EArray : ('a, 't) gexpr list -> ('a any, 't) naked_gexpr
| EVar : ('a, 't) naked_gexpr Bindlib.var -> ('a any, 't) naked_gexpr
| EAbs : {
@ -232,13 +201,7 @@ and ('a, 't) naked_gexpr =
-> ('a any, 't) naked_gexpr
| EStruct : {
name : StructName.t;
fields : ('a, 't) gexpr StructFieldMap.t;
}
-> ('a any, 't) naked_gexpr
| EStructAccess : {
name : StructName.t;
e : ('a, 't) gexpr;
field : StructFieldName.t;
fields : ('a, 't) gexpr StructField.Map.t;
}
-> ('a any, 't) naked_gexpr
| EInj : {
@ -250,7 +213,7 @@ and ('a, 't) naked_gexpr =
| EMatch : {
name : EnumName.t;
e : ('a, 't) gexpr;
cases : ('a, 't) gexpr EnumConstructorMap.t;
cases : ('a, 't) gexpr EnumConstructor.Map.t;
}
-> ('a any, 't) naked_gexpr
(* Early stages *)
@ -259,9 +222,23 @@ and ('a, 't) naked_gexpr =
-> (([< desugared | scopelang ] as 'a), 't) naked_gexpr
| EScopeCall : {
scope : ScopeName.t;
args : ('a, 't) gexpr ScopeVarMap.t;
args : ('a, 't) gexpr ScopeVar.Map.t;
}
-> (([< desugared | scopelang ] as 'a), 't) naked_gexpr
(* [desugared] has ambiguous struct fields *)
| EDStructAccess : {
name_opt : StructName.t option;
e : ('a, 't) gexpr;
field : IdentName.t;
}
-> ((desugared as 'a), 't) naked_gexpr
(* Resolved struct/enums, after [desugared] *)
| EStructAccess : {
name : StructName.t;
e : ('a, 't) gexpr;
field : StructField.t;
}
-> (([< scopelang | dcalc | lcalc ] as 'a), 't) naked_gexpr
(* Lambda-like *)
| EAssert : ('a, 't) gexpr -> (([< dcalc | lcalc ] as 'a), 't) naked_gexpr
(* Default terms *)
@ -386,18 +363,20 @@ and 'e scopes =
| ScopeDef of 'e scope_def
constraint 'e = (_ any, _ mark) gexpr
type struct_ctx = typ StructFieldMap.t StructMap.t
type enum_ctx = typ EnumConstructorMap.t EnumMap.t
type struct_ctx = typ StructField.Map.t StructName.Map.t
type enum_ctx = typ EnumConstructor.Map.t EnumName.Map.t
type scope_out_struct = {
out_struct_name : StructName.t;
out_struct_fields : StructFieldName.t ScopeVarMap.t;
out_struct_fields : StructField.t ScopeVar.Map.t;
}
type decl_ctx = {
ctx_enums : enum_ctx;
ctx_structs : struct_ctx;
ctx_scopes : scope_out_struct ScopeMap.t;
ctx_struct_fields : StructField.t StructName.Map.t IdentName.Map.t;
(** needed for disambiguation (desugared -> scope) *)
ctx_scopes : scope_out_struct ScopeName.Map.t;
}
type 'e program = { decl_ctx : decl_ctx; scopes : 'e scopes }

View File

@ -3,4 +3,4 @@
(public_name catala.shared_ast)
(flags
(:standard -short-paths))
(libraries bindlib unionFind utils catala.runtime_ocaml))
(libraries bindlib unionFind catala_utils catala.runtime_ocaml))

View File

@ -15,7 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Definitions
(** Functions handling the types of [shared_ast] *)
@ -57,15 +57,15 @@ module Box = struct
fun em ->
B.box_apply (fun e -> Marked.mark (Marked.get_mark em) e) (Marked.unmark em)
module LiftStruct = Bindlib.Lift (StructFieldMap)
module LiftStruct = Bindlib.Lift (StructField.Map)
let lift_struct = LiftStruct.lift_box
module LiftEnum = Bindlib.Lift (EnumConstructorMap)
module LiftEnum = Bindlib.Lift (EnumConstructor.Map)
let lift_enum = LiftEnum.lift_box
module LiftScopeVars = Bindlib.Lift (ScopeVarMap)
module LiftScopeVars = Bindlib.Lift (ScopeVar.Map)
let lift_scope_vars = LiftScopeVars.lift_box
end
@ -108,11 +108,14 @@ let ecatch body exn handler =
let elocation loc = Box.app0 @@ ELocation loc
let estruct name (fields : ('a, 't) boxed_gexpr StructFieldMap.t) mark =
let estruct name (fields : ('a, 't) boxed_gexpr StructField.Map.t) mark =
Marked.mark mark
@@ Bindlib.box_apply
(fun fields -> EStruct { name; fields })
(Box.lift_struct (StructFieldMap.map Box.lift fields))
(Box.lift_struct (StructField.Map.map Box.lift fields))
let edstructaccess e field name_opt =
Box.app1 e @@ fun e -> EDStructAccess { name_opt; e; field }
let estructaccess e field name =
Box.app1 e @@ fun e -> EStructAccess { name; e; field }
@ -124,13 +127,13 @@ let ematch e name cases mark =
@@ Bindlib.box_apply2
(fun e cases -> EMatch { name; e; cases })
(Box.lift e)
(Box.lift_enum (EnumConstructorMap.map Box.lift cases))
(Box.lift_enum (EnumConstructor.Map.map Box.lift cases))
let escopecall scope args mark =
Marked.mark mark
@@ Bindlib.box_apply
(fun args -> EScopeCall { scope; args })
(Box.lift_scope_vars (ScopeVarMap.map Box.lift args))
(Box.lift_scope_vars (ScopeVar.Map.map Box.lift args))
(* - Manipulation of marks - *)
@ -230,14 +233,16 @@ let map
| ERaise exn -> eraise exn m
| ELocation loc -> elocation loc m
| EStruct { name; fields } ->
let fields = StructFieldMap.map f fields in
let fields = StructField.Map.map f fields in
estruct name fields m
| EDStructAccess { e; field; name_opt } ->
edstructaccess (f e) field name_opt m
| EStructAccess { e; field; name } -> estructaccess (f e) field name m
| EMatch { e; name; cases } ->
let cases = EnumConstructorMap.map f cases in
let cases = EnumConstructor.Map.map f cases in
ematch (f e) name cases m
| EScopeCall { scope; args } ->
let fields = ScopeVarMap.map f args in
let fields = ScopeVar.Map.map f args in
escopecall scope fields m
let rec map_top_down ~f e = map ~f:(map_top_down ~f) (f e)
@ -266,11 +271,12 @@ let shallow_fold
| EDefault { excepts; just; cons } -> acc |> lfold excepts |> f just |> f cons
| EErrorOnEmpty e -> acc |> f e
| ECatch { body; handler; _ } -> acc |> f body |> f handler
| EStruct { fields; _ } -> acc |> StructFieldMap.fold (fun _ -> f) fields
| EStruct { fields; _ } -> acc |> StructField.Map.fold (fun _ -> f) fields
| EDStructAccess { e; _ } -> acc |> f e
| EStructAccess { e; _ } -> acc |> f e
| EMatch { e; cases; _ } ->
acc |> f e |> EnumConstructorMap.fold (fun _ -> f) cases
| EScopeCall { args; _ } -> acc |> ScopeVarMap.fold (fun _ -> f) args
acc |> f e |> EnumConstructor.Map.fold (fun _ -> f) cases
| EScopeCall { args; _ } -> acc |> ScopeVar.Map.fold (fun _ -> f) args
(* Like [map], but also allows to gather a result bottom-up. *)
let map_gather
@ -339,35 +345,38 @@ let map_gather
| ELocation loc -> acc, elocation loc m
| EStruct { name; fields } ->
let acc, fields =
StructFieldMap.fold
StructField.Map.fold
(fun cons e (acc, fields) ->
let acc1, e = f e in
join acc acc1, StructFieldMap.add cons e fields)
join acc acc1, StructField.Map.add cons e fields)
fields
(acc, StructFieldMap.empty)
(acc, StructField.Map.empty)
in
acc, estruct name fields m
| EDStructAccess { e; field; name_opt } ->
let acc, e = f e in
acc, edstructaccess e field name_opt m
| EStructAccess { e; field; name } ->
let acc, e = f e in
acc, estructaccess e field name m
| EMatch { e; name; cases } ->
let acc, e = f e in
let acc, cases =
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun cons e (acc, cases) ->
let acc1, e = f e in
join acc acc1, EnumConstructorMap.add cons e cases)
join acc acc1, EnumConstructor.Map.add cons e cases)
cases
(acc, EnumConstructorMap.empty)
(acc, EnumConstructor.Map.empty)
in
acc, ematch e name cases m
| EScopeCall { scope; args } ->
let acc, args =
ScopeVarMap.fold
ScopeVar.Map.fold
(fun var e (acc, args) ->
let acc1, e = f e in
join acc acc1, ScopeVarMap.add var e args)
args (acc, ScopeVarMap.empty)
join acc acc1, ScopeVar.Map.add var e args)
args (acc, ScopeVar.Map.empty)
in
acc, escopecall scope args m
@ -688,10 +697,13 @@ and equal : type a. (a, 't) gexpr -> (a, 't) gexpr -> bool =
equal_location (Marked.mark Pos.no_pos l1) (Marked.mark Pos.no_pos l2)
| ( EStruct { name = s1; fields = fields1 },
EStruct { name = s2; fields = fields2 } ) ->
StructName.equal s1 s2 && StructFieldMap.equal equal fields1 fields2
StructName.equal s1 s2 && StructField.Map.equal equal fields1 fields2
| ( EDStructAccess { e = e1; field = f1; name_opt = s1 },
EDStructAccess { e = e2; field = f2; name_opt = s2 } ) ->
Option.equal StructName.equal s1 s2 && IdentName.equal f1 f2 && equal e1 e2
| ( EStructAccess { e = e1; field = f1; name = s1 },
EStructAccess { e = e2; field = f2; name = s2 } ) ->
StructName.equal s1 s2 && StructFieldName.equal f1 f2 && equal e1 e2
StructName.equal s1 s2 && StructField.equal f1 f2 && equal e1 e2
| EInj { e = e1; cons = c1; name = n1 }, EInj { e = e2; cons = c2; name = n2 }
->
EnumName.equal n1 n2 && EnumConstructor.equal c1 c2 && equal e1 e2
@ -699,14 +711,14 @@ and equal : type a. (a, 't) gexpr -> (a, 't) gexpr -> bool =
EMatch { e = e2; name = n2; cases = cases2 } ) ->
EnumName.equal n1 n2
&& equal e1 e2
&& EnumConstructorMap.equal equal cases1 cases2
&& EnumConstructor.Map.equal equal cases1 cases2
| ( EScopeCall { scope = s1; args = fields1 },
EScopeCall { scope = s2; args = fields2 } ) ->
ScopeName.equal s1 s2 && ScopeVarMap.equal equal fields1 fields2
ScopeName.equal s1 s2 && ScopeVar.Map.equal equal fields1 fields2
| ( ( EVar _ | ETuple _ | ETupleAccess _ | EArray _ | ELit _ | EAbs _ | EApp _
| EAssert _ | EOp _ | EDefault _ | EIfThenElse _ | EErrorOnEmpty _
| ERaise _ | ECatch _ | ELocation _ | EStruct _ | EStructAccess _ | EInj _
| EMatch _ | EScopeCall _ ),
| ERaise _ | ECatch _ | ELocation _ | EStruct _ | EDStructAccess _
| EStructAccess _ | EInj _ | EMatch _ | EScopeCall _ ),
_ ) ->
false
@ -719,7 +731,7 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
match[@ocamlformat "disable"] Marked.unmark e1, Marked.unmark e2 with
| ELit l1, ELit l2 ->
compare_lit l1 l2
| EApp {f=f1; args= args1}, EApp {f=f2; args= args2} ->
| EApp {f=f1; args=args1}, EApp {f=f2; args=args2} ->
compare f1 f2 @@< fun () ->
List.compare compare args1 args2
| EOp op1, EOp op2 ->
@ -728,44 +740,57 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
List.compare compare a1 a2
| EVar v1, EVar v2 ->
Bindlib.compare_vars v1 v2
| EAbs {binder=binder1; tys= typs1}, EAbs {binder=binder2; tys= typs2} ->
| EAbs {binder=binder1; tys=typs1},
EAbs {binder=binder2; tys=typs2} ->
List.compare compare_typ typs1 typs2 @@< fun () ->
let _, e1, e2 = Bindlib.unmbind2 binder1 binder2 in
compare e1 e2
| EIfThenElse {cond=i1; etrue= t1; efalse= e1}, EIfThenElse {cond=i2; etrue= t2; efalse= e2} ->
| EIfThenElse {cond=i1; etrue=t1; efalse=e1},
EIfThenElse {cond=i2; etrue=t2; efalse=e2} ->
compare i1 i2 @@< fun () ->
compare t1 t2 @@< fun () ->
compare e1 e2
| ELocation l1, ELocation l2 ->
compare_location (Marked.mark Pos.no_pos l1) (Marked.mark Pos.no_pos l2)
| EStruct {name=name1; fields= field_map1}, EStruct {name=name2; fields= field_map2} ->
| EStruct {name=name1; fields=field_map1},
EStruct {name=name2; fields=field_map2} ->
StructName.compare name1 name2 @@< fun () ->
StructFieldMap.compare compare field_map1 field_map2
| EStructAccess {e=e1; field= field_name1; name= struct_name1},
EStructAccess {e=e2; field= field_name2; name= struct_name2} ->
StructField.Map.compare compare field_map1 field_map2
| EDStructAccess {e=e1; field=field_name1; name_opt=struct_name1},
EDStructAccess {e=e2; field=field_name2; name_opt=struct_name2} ->
compare e1 e2 @@< fun () ->
StructFieldName.compare field_name1 field_name2 @@< fun () ->
IdentName.compare field_name1 field_name2 @@< fun () ->
Option.compare StructName.compare struct_name1 struct_name2
| EStructAccess {e=e1; field=field_name1; name=struct_name1},
EStructAccess {e=e2; field=field_name2; name=struct_name2} ->
compare e1 e2 @@< fun () ->
StructField.compare field_name1 field_name2 @@< fun () ->
StructName.compare struct_name1 struct_name2
| EMatch {e=e1; name= name1;cases= emap1}, EMatch {e=e2; name= name2;cases= emap2} ->
| EMatch {e=e1; name=name1; cases=emap1},
EMatch {e=e2; name=name2; cases=emap2} ->
EnumName.compare name1 name2 @@< fun () ->
compare e1 e2 @@< fun () ->
EnumConstructorMap.compare compare emap1 emap2
| EScopeCall {scope=name1; args= field_map1}, EScopeCall {scope=name2; args= field_map2} ->
EnumConstructor.Map.compare compare emap1 emap2
| EScopeCall {scope=name1; args=field_map1},
EScopeCall {scope=name2; args=field_map2} ->
ScopeName.compare name1 name2 @@< fun () ->
ScopeVarMap.compare compare field_map1 field_map2
ScopeVar.Map.compare compare field_map1 field_map2
| ETuple es1, ETuple es2 ->
List.compare compare es1 es2
| ETupleAccess {e=e1; index= n1; size=s1}, ETupleAccess {e=e2; index= n2; size=s2} ->
| ETupleAccess {e=e1; index=n1; size=s1},
ETupleAccess {e=e2; index=n2; size=s2} ->
Int.compare s1 s2 @@< fun () ->
Int.compare n1 n2 @@< fun () ->
compare e1 e2
| EInj {e=e1; name= name1; cons= cons1}, EInj {e=e2; name= name2; cons= cons2} ->
| EInj {e=e1; name=name1; cons=cons1},
EInj {e=e2; name=name2; cons=cons2} ->
EnumName.compare name1 name2 @@< fun () ->
EnumConstructor.compare cons1 cons2 @@< fun () ->
compare e1 e2
| EAssert e1, EAssert e2 ->
compare e1 e2
| EDefault {excepts=exs1; just= just1; cons=cons1}, EDefault {excepts=exs2; just= just2; cons=cons2} ->
| EDefault {excepts=exs1; just=just1; cons=cons1},
EDefault {excepts=exs2; just=just2; cons=cons2} ->
compare just1 just2 @@< fun () ->
compare cons1 cons2 @@< fun () ->
List.compare compare exs1 exs2
@ -773,7 +798,8 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
compare e1 e2
| ERaise ex1, ERaise ex2 ->
compare_except ex1 ex2
| ECatch {body=etry1; exn= ex1; handler=ewith1}, ECatch {body=etry2; exn= ex2; handler=ewith2} ->
| ECatch {body=etry1; exn=ex1; handler=ewith1},
ECatch {body=etry2; exn=ex2; handler=ewith2} ->
compare_except ex1 ex2 @@< fun () ->
compare etry1 etry2 @@< fun () ->
compare ewith1 ewith2
@ -786,6 +812,7 @@ let rec compare : type a. (a, _) gexpr -> (a, _) gexpr -> int =
| EIfThenElse _, _ -> -1 | _, EIfThenElse _ -> 1
| ELocation _, _ -> -1 | _, ELocation _ -> 1
| EStruct _, _ -> -1 | _, EStruct _ -> 1
| EDStructAccess _, _ -> -1 | _, EDStructAccess _ -> 1
| EStructAccess _, _ -> -1 | _, EStructAccess _ -> 1
| EMatch _, _ -> -1 | _, EMatch _ -> 1
| EScopeCall _, _ -> -1 | _, EScopeCall _ -> 1
@ -841,12 +868,13 @@ let rec size : type a. (a, 't) gexpr -> int =
| ECatch { body; handler; _ } -> 1 + size body + size handler
| ELocation _ -> 1
| EStruct { fields; _ } ->
StructFieldMap.fold (fun _ e acc -> acc + 1 + size e) fields 0
StructField.Map.fold (fun _ e acc -> acc + 1 + size e) fields 0
| EDStructAccess { e; _ } -> 1 + size e
| EStructAccess { e; _ } -> 1 + size e
| EMatch { e; cases; _ } ->
EnumConstructorMap.fold (fun _ e acc -> acc + 1 + size e) cases (size e)
EnumConstructor.Map.fold (fun _ e acc -> acc + 1 + size e) cases (size e)
| EScopeCall { args; _ } ->
ScopeVarMap.fold (fun _ e acc -> acc + 1 + size e) args 1
ScopeVar.Map.fold (fun _ e acc -> acc + 1 + size e) args 1
(* - Expression building helpers - *)
@ -931,3 +959,33 @@ let make_tuple el m0 =
(List.map (fun e -> Marked.get_mark e) el)
in
etuple el m
let translate_op_kind : type a. a op_kind -> 'b op_kind = function
| KInt -> KInt
| KRat -> KRat
| KMoney -> KMoney
| KDate -> KDate
| KDuration -> KDuration
let translate_op : type a. a operator -> 'b operator = function
| Ternop o -> Ternop o
| Binop o ->
Binop
(match o with
| Add k -> Add (translate_op_kind k)
| Sub k -> Sub (translate_op_kind k)
| Mult k -> Mult (translate_op_kind k)
| Div k -> Div (translate_op_kind k)
| Lt k -> Lt (translate_op_kind k)
| Lte k -> Lte (translate_op_kind k)
| Gt k -> Gt (translate_op_kind k)
| Gte k -> Gte (translate_op_kind k)
| (And | Or | Xor | Eq | Neq | Map | Concat | Filter) as o -> o)
| Unop o ->
Unop
(match o with
| Minus k -> Minus (translate_op_kind k)
| ( Not | Log _ | Length | IntToRat | MoneyToRat | RatToMoney | GetDay
| GetMonth | GetYear | FirstDayOfMonth | LastDayOfMonth | RoundMoney
| RoundDecimal ) as o ->
o)

View File

@ -17,7 +17,7 @@
(** Functions handling the expressions of [shared_ast] *)
open Utils
open Catala_utils
open Definitions
(** {2 Boxed constructors} *)
@ -66,7 +66,7 @@ val eapp :
val eassert :
(([< dcalc | lcalc ] as 'a), 't) boxed_gexpr -> 't -> ('a, 't) boxed_gexpr
val eop : operator -> 't -> (_ any, 't) boxed_gexpr
val eop : 'a any operator -> 't -> ('a, 't) boxed_gexpr
val edefault :
(([< desugared | scopelang | dcalc ] as 'a), 't) boxed_gexpr list ->
@ -101,13 +101,20 @@ val elocation :
val estruct :
StructName.t ->
('a any, 't) boxed_gexpr StructFieldMap.t ->
('a any, 't) boxed_gexpr StructField.Map.t ->
't ->
('a, 't) boxed_gexpr
val edstructaccess :
(desugared, 't) boxed_gexpr ->
IdentName.t ->
StructName.t option ->
't ->
(desugared, 't) boxed_gexpr
val estructaccess :
('a any, 't) boxed_gexpr ->
StructFieldName.t ->
(([< scopelang | dcalc | lcalc ] as 'a), 't) boxed_gexpr ->
StructField.t ->
StructName.t ->
't ->
('a, 't) boxed_gexpr
@ -122,13 +129,13 @@ val einj :
val ematch :
('a any, 't) boxed_gexpr ->
EnumName.t ->
('a, 't) boxed_gexpr EnumConstructorMap.t ->
('a, 't) boxed_gexpr EnumConstructor.Map.t ->
't ->
('a, 't) boxed_gexpr
val escopecall :
ScopeName.t ->
(([< desugared | scopelang ] as 'a), 't) boxed_gexpr ScopeVarMap.t ->
(([< desugared | scopelang ] as 'a), 't) boxed_gexpr ScopeVar.Map.t ->
't ->
('a, 't) boxed_gexpr
@ -303,6 +310,11 @@ val make_tuple :
(** {2 Transformations} *)
val translate_op :
[< desugared | scopelang | dcalc | lcalc ] operator -> 'b any operator
(** Operators are actually all the same after initial desambiguation, so this
function allows converting their types ; otherwise, this is the identity *)
val remove_logging_calls : ('a any, 't) gexpr -> ('a, 't) boxed_gexpr
(** Removes all calls to [Log] unary operators in the AST, replacing them by
their argument. *)
@ -360,10 +372,10 @@ module Box : sig
a separate argument. *)
val app1 :
('a, 't) boxed_gexpr ->
(('a, 't) gexpr -> ('a, 't) naked_gexpr) ->
't ->
('a, 't) boxed_gexpr
('a, 't1) boxed_gexpr ->
(('a, 't1) gexpr -> ('a, 't2) naked_gexpr) ->
't2 ->
('a, 't2) boxed_gexpr
val app2 :
('a, 't) boxed_gexpr ->

View File

@ -14,8 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open String_common
open Catala_utils
open Definitions
let typ_needs_parens (ty : typ) : bool =
@ -26,27 +25,28 @@ let uid_list (fmt : Format.formatter) (infos : Uid.MarkedString.info list) :
Format.pp_print_list
~pp_sep:(fun fmt () -> Format.pp_print_char fmt '.')
(fun fmt info ->
Utils.Cli.format_with_style
(if begins_with_uppercase (Marked.unmark info) then [ANSITerminal.red]
Cli.format_with_style
(if String.begins_with_uppercase (Marked.unmark info) then
[ANSITerminal.red]
else [])
fmt
(Utils.Uid.MarkedString.to_string info))
(Uid.MarkedString.to_string info))
fmt infos
let keyword (fmt : Format.formatter) (s : string) : unit =
Utils.Cli.format_with_style [ANSITerminal.red] fmt s
Cli.format_with_style [ANSITerminal.red] fmt s
let base_type (fmt : Format.formatter) (s : string) : unit =
Utils.Cli.format_with_style [ANSITerminal.yellow] fmt s
Cli.format_with_style [ANSITerminal.yellow] fmt s
let punctuation (fmt : Format.formatter) (s : string) : unit =
Utils.Cli.format_with_style [ANSITerminal.cyan] fmt s
Cli.format_with_style [ANSITerminal.cyan] fmt s
let operator (fmt : Format.formatter) (s : string) : unit =
Utils.Cli.format_with_style [ANSITerminal.green] fmt s
Cli.format_with_style [ANSITerminal.green] fmt s
let lit_style (fmt : Format.formatter) (s : string) : unit =
Utils.Cli.format_with_style [ANSITerminal.yellow] fmt s
Cli.format_with_style [ANSITerminal.yellow] fmt s
let tlit (fmt : Format.formatter) (l : typ_lit) : unit =
base_type fmt
@ -68,7 +68,7 @@ let location (type a) (fmt : Format.formatter) (l : a glocation) : unit =
ScopeVar.format_t (Marked.unmark subvar)
let enum_constructor (fmt : Format.formatter) (c : EnumConstructor.t) : unit =
Utils.Cli.format_with_style [ANSITerminal.magenta] fmt
Cli.format_with_style [ANSITerminal.magenta] fmt
(Format.asprintf "%a" EnumConstructor.format_t c)
let rec typ (ctx : decl_ctx option) (fmt : Format.formatter) (ty : typ) : unit =
@ -94,9 +94,9 @@ let rec typ (ctx : decl_ctx option) (fmt : Format.formatter) (ty : typ) : unit =
~pp_sep:(fun fmt () -> Format.fprintf fmt "%a@ " punctuation ";")
(fun fmt (field, mty) ->
Format.fprintf fmt "%a%a%a%a@ %a" punctuation "\""
StructFieldName.format_t field punctuation "\"" punctuation ":"
typ mty))
(StructFieldMap.bindings (StructMap.find s ctx.ctx_structs))
StructField.format_t field punctuation "\"" punctuation ":" typ
mty))
(StructField.Map.bindings (StructName.Map.find s ctx.ctx_structs))
punctuation "}")
| TEnum e -> (
match ctx with
@ -109,7 +109,7 @@ let rec typ (ctx : decl_ctx option) (fmt : Format.formatter) (ty : typ) : unit =
(fun fmt (case, mty) ->
Format.fprintf fmt "%a%a@ %a" enum_constructor case punctuation ":"
typ mty))
(EnumConstructorMap.bindings (EnumMap.find e ctx.ctx_enums))
(EnumConstructor.Map.bindings (EnumName.Map.find e ctx.ctx_enums))
punctuation "]")
| TOption t -> Format.fprintf fmt "@[<hov 2>%a@ %a@]" base_type "option" typ t
| TArrow (t1, t2) ->
@ -127,9 +127,9 @@ let lit (type a) (fmt : Format.formatter) (l : a glit) : unit =
| LUnit -> lit_style fmt "()"
| LRat i ->
lit_style fmt
(Runtime.decimal_to_string ~max_prec_digits:!Utils.Cli.max_prec_digits i)
(Runtime.decimal_to_string ~max_prec_digits:!Cli.max_prec_digits i)
| LMoney e -> (
match !Utils.Cli.locale_lang with
match !Cli.locale_lang with
| En -> lit_style fmt (Format.asprintf "$%s" (Runtime.money_to_string e))
| Fr -> lit_style fmt (Format.asprintf "%s €" (Runtime.money_to_string e))
| Pl -> lit_style fmt (Format.asprintf "%s PLN" (Runtime.money_to_string e))
@ -137,7 +137,7 @@ let lit (type a) (fmt : Format.formatter) (l : a glit) : unit =
| LDate d -> lit_style fmt (Runtime.date_to_string d)
| LDuration d -> lit_style fmt (Runtime.duration_to_string d)
let op_kind (fmt : Format.formatter) (k : op_kind) =
let op_kind (fmt : Format.formatter) (k : 'a op_kind) =
Format.fprintf fmt "%s"
(match k with
| KInt -> ""
@ -146,7 +146,7 @@ let op_kind (fmt : Format.formatter) (k : op_kind) =
| KDate -> "@"
| KDuration -> "^")
let binop (fmt : Format.formatter) (op : binop) : unit =
let binop (fmt : Format.formatter) (op : 'a binop) : unit =
operator fmt
(match op with
| Add k -> Format.asprintf "+%a" op_kind k
@ -172,14 +172,14 @@ let ternop (fmt : Format.formatter) (op : ternop) : unit =
let log_entry (fmt : Format.formatter) (entry : log_entry) : unit =
Format.fprintf fmt "@<2>%a"
(fun fmt -> function
| VarDef _ -> Utils.Cli.format_with_style [ANSITerminal.blue] fmt ""
| BeginCall -> Utils.Cli.format_with_style [ANSITerminal.yellow] fmt ""
| EndCall -> Utils.Cli.format_with_style [ANSITerminal.yellow] fmt ""
| VarDef _ -> Cli.format_with_style [ANSITerminal.blue] fmt ""
| BeginCall -> Cli.format_with_style [ANSITerminal.yellow] fmt ""
| EndCall -> Cli.format_with_style [ANSITerminal.yellow] fmt ""
| PosRecordIfTrueBool ->
Utils.Cli.format_with_style [ANSITerminal.green] fmt "")
Cli.format_with_style [ANSITerminal.green] fmt "")
entry
let unop (fmt : Format.formatter) (op : unop) : unit =
let unop (fmt : Format.formatter) (op : 'a unop) : unit =
match op with
| Minus _ -> Format.pp_print_string fmt "-"
| Not -> Format.pp_print_string fmt "~"
@ -187,7 +187,7 @@ let unop (fmt : Format.formatter) (op : unop) : unit =
Format.fprintf fmt "log@[<hov 2>[%a|%a]@]" log_entry entry
(Format.pp_print_list
~pp_sep:(fun fmt () -> Format.fprintf fmt ".")
(fun fmt info -> Utils.Uid.MarkedString.format_info fmt info))
(fun fmt info -> Uid.MarkedString.format fmt info))
infos
| Length -> Format.pp_print_string fmt "length"
| IntToRat -> Format.pp_print_string fmt "int_to_rat"
@ -323,6 +323,9 @@ let rec expr_aux :
| ERaise exn ->
Format.fprintf fmt "@[<hov 2>%a@ %a@]" keyword "raise" except exn
| ELocation loc -> location fmt loc
| EDStructAccess { e; field; _ } ->
Format.fprintf fmt "%a%a%a%a%a" expr e punctuation "." punctuation "\""
IdentName.format_t field punctuation "\""
| EStruct { name; fields } ->
Format.fprintf fmt "@[<hov 2>%a@ %a@ %a@ %a@]" StructName.format_t name
punctuation "{"
@ -330,13 +333,13 @@ let rec expr_aux :
~pp_sep:(fun fmt () -> Format.fprintf fmt "%a@ " punctuation ";")
(fun fmt (field_name, field_expr) ->
Format.fprintf fmt "%a%a%a%a@ %a" punctuation "\""
StructFieldName.format_t field_name punctuation "\"" punctuation
"=" expr field_expr))
(StructFieldMap.bindings fields)
StructField.format_t field_name punctuation "\"" punctuation "="
expr field_expr))
(StructField.Map.bindings fields)
punctuation "}"
| EStructAccess { e; field; _ } ->
Format.fprintf fmt "%a%a%a%a%a" expr e punctuation "." punctuation "\""
StructFieldName.format_t field punctuation "\""
StructField.format_t field punctuation "\""
| EInj { e; cons; _ } ->
Format.fprintf fmt "%a@ %a" EnumConstructor.format_t cons expr e
| EMatch { e; cases; _ } ->
@ -347,7 +350,7 @@ let rec expr_aux :
(fun fmt (cons_name, case_expr) ->
Format.fprintf fmt "@[<hov 2>%a %a@ %a@ %a@]" punctuation "|"
enum_constructor cons_name punctuation "" expr case_expr))
(EnumConstructorMap.bindings cases)
(EnumConstructor.Map.bindings cases)
| EScopeCall { scope; args } ->
Format.pp_open_hovbox fmt 2;
ScopeName.format_t fmt scope;
@ -362,7 +365,7 @@ let rec expr_aux :
Format.fprintf fmt "%a%a%a%a@ %a" punctuation "\"" ScopeVar.format_t
field_name punctuation "\"" punctuation "=" expr field_expr)
fmt
(ScopeVarMap.bindings args);
(ScopeVar.Map.bindings args);
Format.pp_close_box fmt ();
punctuation fmt "}";
Format.pp_close_box fmt ()

View File

@ -16,7 +16,7 @@
(** Printing functions for the default calculus AST *)
open Utils
open Catala_utils
open Definitions
(** {1 Common syntax highlighting helpers}*)
@ -35,11 +35,11 @@ val tlit : Format.formatter -> typ_lit -> unit
val location : Format.formatter -> 'a glocation -> unit
val typ : decl_ctx -> Format.formatter -> typ -> unit
val lit : Format.formatter -> 'a glit -> unit
val op_kind : Format.formatter -> op_kind -> unit
val binop : Format.formatter -> binop -> unit
val op_kind : Format.formatter -> 'a any op_kind -> unit
val binop : Format.formatter -> 'a any binop -> unit
val ternop : Format.formatter -> ternop -> unit
val log_entry : Format.formatter -> log_entry -> unit
val unop : Format.formatter -> unop -> unit
val unop : Format.formatter -> 'a any unop -> unit
val except : Format.formatter -> except -> unit
val var : Format.formatter -> 'e Var.t -> unit
val var_debug : Format.formatter -> 'e Var.t -> unit

View File

@ -15,7 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Definitions
let rec fold_left_lets ~f ~init scope_body_expr =
@ -106,7 +106,7 @@ let rec get_body_expr_mark = function
get_body_expr_mark e
| Result e ->
let m = Marked.get_mark e in
Expr.with_ty m (Utils.Marked.mark (Expr.mark_pos m) TAny)
Expr.with_ty m (Marked.mark (Expr.mark_pos m) TAny)
let get_body_mark scope_body =
let _, e = Bindlib.unbind scope_body.scope_body_expr in

View File

@ -17,7 +17,7 @@
(** Functions handling the scope structures of [shared_ast] *)
open Utils
open Catala_utils
open Definitions
(** {2 Traversal functions} *)

View File

@ -17,16 +17,16 @@
(** Typing for the default calculus. Because of the error terms, we perform type
inference using the classical W algorithm with union-find unification. *)
open Utils
open Catala_utils
module A = Definitions
module Any =
Utils.Uid.Make
Uid.Make
(struct
type info = unit
let to_string _ = "any"
let format_info fmt () = Format.fprintf fmt "any"
let format fmt () = Format.fprintf fmt "any"
let equal _ _ = true
let compare _ _ = 0
end)
@ -47,7 +47,8 @@ and naked_typ =
| TArray of unionfind_typ
| TAny of Any.t
let rec typ_to_ast (ty : unionfind_typ) : A.typ =
let rec typ_to_ast ?(unsafe = false) (ty : unionfind_typ) : A.typ =
let typ_to_ast = typ_to_ast ~unsafe in
let ty, pos = UnionFind.get (UnionFind.find ty) in
match ty with
| TLit l -> A.TLit l, pos
@ -58,11 +59,22 @@ let rec typ_to_ast (ty : unionfind_typ) : A.typ =
| TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2), pos
| TArray t1 -> A.TArray (typ_to_ast t1), pos
| TAny _ ->
(* No polymorphism in Catala: type inference should return full types
without wildcards, and this function is used to recover the types after
typing. *)
Errors.raise_spanned_error pos
"Internal error: typing at this point could not be resolved"
if unsafe then A.TAny, pos
else
(* No polymorphism in Catala: type inference should return full types
without wildcards, and this function is used to recover the types after
typing. *)
Errors.raise_spanned_error pos
"Internal error: typing at this point could not be resolved"
(* Checks that there are no type variables remaining *)
let rec all_resolved ty =
match Marked.unmark (UnionFind.get (UnionFind.find ty)) with
| TAny _ -> false
| TLit _ | TStruct _ | TEnum _ -> true
| TOption t1 | TArray t1 -> all_resolved t1
| TArrow (t1, t2) -> all_resolved t1 && all_resolved t2
| TTuple ts -> List.for_all all_resolved ts
let rec ast_to_typ (ty : A.typ) : unionfind_typ =
let ty' =
@ -111,9 +123,11 @@ let rec format_typ
format_typ t2
| TArray t1 -> (
match Marked.unmark (UnionFind.get (UnionFind.find t1)) with
| TAny _ -> Format.pp_print_string fmt "collection"
| TAny _ when not !Cli.debug_flag -> Format.pp_print_string fmt "collection"
| _ -> Format.fprintf fmt "@[collection@ %a@]" format_typ t1)
| TAny _ -> Format.pp_print_string fmt "<any>"
| TAny v ->
if !Cli.debug_flag then Format.fprintf fmt "<a%d>" (Any.hash v)
else Format.pp_print_string fmt "<any>"
exception Type_error of A.any_expr * unionfind_typ * unionfind_typ
@ -215,7 +229,7 @@ let lit_type (type a) (lit : a A.glit) : naked_typ =
This allows us to have a simpler type system, while we argue the syntactic
burden of operator annotations helps the programmer visualize the type flow
in the code. *)
let op_type (op : A.operator Marked.pos) : unionfind_typ =
let op_type (op : 'a A.operator Marked.pos) : unionfind_typ =
let pos = Marked.get_mark op in
let bt = UnionFind.make (TLit TBool, pos) in
let it = UnionFind.make (TLit TInt, pos) in
@ -284,32 +298,41 @@ let op_type (op : A.operator Marked.pos) : unionfind_typ =
module Env = struct
type 'e t = {
vars : ('e, unionfind_typ) Var.Map.t;
scope_vars : A.typ A.ScopeVarMap.t;
scopes : A.typ A.ScopeVarMap.t A.ScopeMap.t;
scope_vars : A.typ A.ScopeVar.Map.t;
scopes : A.typ A.ScopeVar.Map.t A.ScopeName.Map.t;
}
let empty =
{
vars = Var.Map.empty;
scope_vars = A.ScopeVarMap.empty;
scopes = A.ScopeMap.empty;
scope_vars = A.ScopeVar.Map.empty;
scopes = A.ScopeName.Map.empty;
}
let get t v = Var.Map.find_opt v t.vars
let get_scope_var t sv = A.ScopeVarMap.find_opt sv t.scope_vars
let get_scope_var t sv = A.ScopeVar.Map.find_opt sv t.scope_vars
let get_subscope_out_var t scope var =
Option.bind (A.ScopeMap.find_opt scope t.scopes) (fun vmap ->
A.ScopeVarMap.find_opt var vmap)
Option.bind (A.ScopeName.Map.find_opt scope t.scopes) (fun vmap ->
A.ScopeVar.Map.find_opt var vmap)
let add v tau t = { t with vars = Var.Map.add v tau t.vars }
let add_var v typ t = add v (ast_to_typ typ) t
let add_scope_var v typ t =
{ t with scope_vars = A.ScopeVarMap.add v typ t.scope_vars }
{ t with scope_vars = A.ScopeVar.Map.add v typ t.scope_vars }
let add_scope scope_name ~vars t =
{ t with scopes = A.ScopeMap.add scope_name vars t.scopes }
{ t with scopes = A.ScopeName.Map.add scope_name vars t.scopes }
let open_scope scope_name t =
let scope_vars =
A.ScopeVar.Map.union
(fun _ _ -> assert false)
t.scope_vars
(A.ScopeName.Map.find scope_name t.scopes)
in
{ t with scope_vars }
end
let add_pos e ty = Marked.mark (Expr.pos e) ty
@ -373,33 +396,32 @@ and typecheck_expr_top_down :
Expr.elocation loc (uf_mark (ast_to_typ ty))
| A.EStruct { name; fields } ->
let mark = ty_mark (TStruct name) in
let str = A.StructMap.find name ctx.A.ctx_structs in
let str = A.StructName.Map.find name ctx.A.ctx_structs in
let _check_fields : unit =
let missing_fields, extra_fields =
A.StructFieldMap.fold
A.StructField.Map.fold
(fun fld x (remaining, extra) ->
if A.StructFieldMap.mem fld remaining then
A.StructFieldMap.remove fld remaining, extra
else remaining, A.StructFieldMap.add fld x extra)
if A.StructField.Map.mem fld remaining then
A.StructField.Map.remove fld remaining, extra
else remaining, A.StructField.Map.add fld x extra)
fields
(str, A.StructFieldMap.empty)
(str, A.StructField.Map.empty)
in
let errs =
List.map
(fun (f, ty) ->
( Some
(Format.asprintf "Missing field %a" A.StructFieldName.format_t f),
( Some (Format.asprintf "Missing field %a" A.StructField.format_t f),
Marked.get_mark ty ))
(A.StructFieldMap.bindings missing_fields)
(A.StructField.Map.bindings missing_fields)
@ List.map
(fun (f, ef) ->
let dup = A.StructFieldMap.mem f str in
let dup = A.StructField.Map.mem f str in
( Some
(Format.asprintf "%s field %a"
(if dup then "Duplicate" else "Unknown")
A.StructFieldName.format_t f),
A.StructField.format_t f),
Expr.pos ef ))
(A.StructFieldMap.bindings extra_fields)
(A.StructField.Map.bindings extra_fields)
in
if errs <> [] then
Errors.raise_multispanned_error errs
@ -407,22 +429,62 @@ and typecheck_expr_top_down :
name
in
let fields' =
A.StructFieldMap.mapi
A.StructField.Map.mapi
(fun f_name f_e ->
let f_ty = A.StructFieldMap.find f_name str in
let f_ty = A.StructField.Map.find f_name str in
typecheck_expr_top_down ctx env (ast_to_typ f_ty) f_e)
fields
in
Expr.estruct name fields' mark
| A.EStructAccess { e = e_struct; name; field } ->
| A.EDStructAccess { e = e_struct; name_opt; field } ->
let t_struct =
match name_opt with
| Some name -> TStruct name
| None -> TAny (Any.fresh ())
in
let e_struct' =
typecheck_expr_top_down ctx env (unionfind t_struct) e_struct
in
let name =
match UnionFind.get (ty e_struct') with
| TStruct name, _ -> name
| TAny _, _ ->
Printf.ksprintf failwith
"Disambiguation failed before reaching field %s" field
| _ ->
Errors.raise_spanned_error (Expr.pos e)
"This is not a structure, cannot access field %s (%a)" field
(format_typ ctx) (ty e_struct')
in
let fld_ty =
let str =
try A.StructMap.find name ctx.A.ctx_structs
try A.StructName.Map.find name ctx.A.ctx_structs
with Not_found ->
Errors.raise_spanned_error pos_e "No structure %a found"
A.StructName.format_t name
in
try A.StructFieldMap.find field str
let field =
try
A.StructName.Map.find name
(A.IdentName.Map.find field ctx.ctx_struct_fields)
with Not_found ->
Errors.raise_spanned_error context_mark.pos
"Field %s does not belong to structure %a" field
A.StructName.format_t name
in
A.StructField.Map.find field str
in
let mark = uf_mark (ast_to_typ fld_ty) in
Expr.edstructaccess e_struct' field (Some name) mark
| A.EStructAccess { e = e_struct; name; field } ->
let fld_ty =
let str =
try A.StructName.Map.find name ctx.A.ctx_structs
with Not_found ->
Errors.raise_spanned_error pos_e "No structure %a found"
A.StructName.format_t name
in
try A.StructField.Map.find field str
with Not_found ->
Errors.raise_multispanned_error
[
@ -431,7 +493,7 @@ and typecheck_expr_top_down :
Marked.get_mark (A.StructName.get_info name) );
]
"Structure %a doesn't define a field %a" A.StructName.format_t name
A.StructFieldName.format_t field
A.StructField.format_t field
in
let mark = uf_mark (ast_to_typ fld_ty) in
let e_struct' =
@ -443,20 +505,20 @@ and typecheck_expr_top_down :
let e_enum' =
typecheck_expr_top_down ctx env
(ast_to_typ
(A.EnumConstructorMap.find cons
(A.EnumMap.find name ctx.A.ctx_enums)))
(A.EnumConstructor.Map.find cons
(A.EnumName.Map.find name ctx.A.ctx_enums)))
e_enum
in
Expr.einj e_enum' cons name mark
| A.EMatch { e = e1; name; cases } ->
let cases_ty = A.EnumMap.find name ctx.A.ctx_enums in
let cases_ty = A.EnumName.Map.find name ctx.A.ctx_enums in
let t_ret = unionfind ~pos:e1 (TAny (Any.fresh ())) in
let mark = uf_mark t_ret in
let e1' = typecheck_expr_top_down ctx env (unionfind (TEnum name)) e1 in
let cases' =
A.EnumConstructorMap.mapi
A.EnumConstructor.Map.mapi
(fun c_name e ->
let c_ty = A.EnumConstructorMap.find c_name cases_ty in
let c_ty = A.EnumConstructor.Map.find c_name cases_ty in
let e_ty = unionfind ~pos:e (TArrow (ast_to_typ c_ty, t_ret)) in
typecheck_expr_top_down ctx env e_ty e)
cases
@ -464,15 +526,15 @@ and typecheck_expr_top_down :
Expr.ematch e1' name cases' mark
| A.EScopeCall { scope; args } ->
let scope_out_struct =
(A.ScopeMap.find scope ctx.ctx_scopes).out_struct_name
(A.ScopeName.Map.find scope ctx.ctx_scopes).out_struct_name
in
let mark = uf_mark (unionfind (TStruct scope_out_struct)) in
let vars = A.ScopeMap.find scope env.scopes in
let vars = A.ScopeName.Map.find scope env.scopes in
let args' =
A.ScopeVarMap.mapi
A.ScopeVar.Map.mapi
(fun name ->
typecheck_expr_top_down ctx env
(ast_to_typ (A.ScopeVarMap.find name vars)))
(ast_to_typ (A.ScopeVar.Map.find name vars)))
args
in
Expr.escopecall scope args' mark
@ -522,6 +584,7 @@ and typecheck_expr_top_down :
tau_args t_ret
in
let mark = uf_mark t_func in
assert (List.for_all all_resolved tau_args);
let xs, body = Bindlib.unmbind binder in
let xs' = Array.map Var.translate xs in
let env =
@ -532,7 +595,13 @@ and typecheck_expr_top_down :
let body' = typecheck_expr_top_down ctx env t_ret body in
let binder' = Bindlib.bind_mvar xs' (Expr.Box.lift body') in
Expr.eabs binder' (List.map typ_to_ast tau_args) mark
| A.EApp { f = e1; args } ->
| A.EApp { f = (EOp _, _) as e1; args } ->
(* Same as EApp, but the typing order is different to help with
disambiguation: - type of the operator is extracted first (to figure
linked type vars between arguments) - arguments are typed right-to-left,
because our operators with function args always have the functions first,
and the argument types of those functions can always be inferred from the
later operator arguments *)
let t_args = List.map (fun _ -> unionfind (TAny (Any.fresh ()))) args in
let t_func =
List.fold_right
@ -540,7 +609,24 @@ and typecheck_expr_top_down :
t_args tau
in
let e1' = typecheck_expr_top_down ctx env t_func e1 in
let args' =
List.rev_map2
(typecheck_expr_top_down ctx env)
(List.rev t_args) (List.rev args)
in
Expr.eapp e1' args' context_mark
| A.EApp { f = e1; args } ->
(* Here we type the arguments first (in order), to ensure we know the types
of the arguments if [f] is [EAbs] before disambiguation. This is also the
right order for the [let-in] form. *)
let t_args = List.map (fun _ -> unionfind (TAny (Any.fresh ()))) args in
let t_func =
List.fold_right
(fun t_arg acc -> unionfind (TArrow (t_arg, acc)))
t_args tau
in
let args' = List.map2 (typecheck_expr_top_down ctx env) t_args args in
let e1' = typecheck_expr_top_down ctx env t_func e1 in
Expr.eapp e1' args' context_mark
| A.EOp op -> Expr.eop op (uf_mark (op_type (Marked.mark pos_e op)))
| A.EDefault { excepts; just; cons } ->
@ -588,19 +674,27 @@ let wrap_expr ctx f e =
let get_ty_mark { uf; pos } = A.Typed { ty = typ_to_ast uf; pos }
(* Infer the type of an expression *)
let expr
let expr_raw
(type a)
(ctx : A.decl_ctx)
?(env = Env.empty)
?(typ : A.typ option)
(e : (a, 'm) A.gexpr) : (a, A.typed A.mark) A.boxed_gexpr =
(e : (a, 'm) A.gexpr) : (a, mark) A.gexpr =
let fty =
match typ with
| None -> typecheck_expr_bottom_up ctx env
| Some typ -> typecheck_expr_top_down ctx env (ast_to_typ typ)
in
Expr.map_marks ~f:get_ty_mark (wrap_expr ctx fty e)
wrap_expr ctx fty e
let check_expr ctx ?env ?typ e =
Expr.map_marks
~f:(fun { pos; _ } -> A.Untyped { pos })
(expr_raw ctx ?env ?typ e)
(* Infer the type of an expression *)
let expr ctx ?env ?typ e =
Expr.map_marks ~f:get_ty_mark (expr_raw ctx ?env ?typ e)
let rec scope_body_expr ctx env ty_out body_expr =
match body_expr with

View File

@ -25,7 +25,8 @@ module Env : sig
val empty : 'e t
val add_var : 'e Var.t -> typ -> 'e t -> 'e t
val add_scope_var : ScopeVar.t -> typ -> 'e t -> 'e t
val add_scope : ScopeName.t -> vars:typ ScopeVarMap.t -> 'e t -> 'e t
val add_scope : ScopeName.t -> vars:typ ScopeVar.Map.t -> 'e t -> 'e t
val open_scope : ScopeName.t -> 'e t -> 'e t
end
val expr :
@ -43,6 +44,17 @@ val expr :
filling the gaps ([TAny]) if any. Use [Expr.untype] first if this is not
what you want. *)
val check_expr :
decl_ctx ->
?env:'e Env.t ->
?typ:typ ->
(('a, 'm mark) gexpr as 'e) ->
('a, untyped mark) boxed_gexpr
(** Same as [expr], but doesn't annotate the returned expression. Equivalent to
[Typing.expr |> Expr.untype], but more efficient. This can be useful for
type-checking and disambiguation (some AST nodes are updated with missing
information, e.g. any [TAny] appearing in the AST is replaced) *)
val program : ('a, 'm mark) gexpr program -> ('a, typed mark) gexpr program
(** Typing on whole programs (as defined in Shared_ast.program, i.e. for the
later dcalc/lcalc stages.

View File

@ -19,7 +19,7 @@
[@@@ocaml.warning "-7"]
open Utils
open Catala_utils
(** {1 Visitor classes for programs} *)
(** To allow for quick traversal and/or modification of this AST structure, we

View File

@ -2,7 +2,7 @@
(name surface)
(public_name catala.surface)
(libraries
utils
catala_utils
menhirLib
sedlex
re

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
let fill_pos_with_legislative_info (p : Ast.program) : Ast.program =
let visitor =

View File

@ -14,7 +14,7 @@
open Tokens
open Sedlexing
open Utils
open Catala_utils
module L = Lexer_common
module R = Re.Pcre

View File

@ -17,7 +17,7 @@
open Tokens
open Sedlexing
open Utils
open Catala_utils
module R = Re.Pcre
(* Calculates the precedence according a {!val: matched_regex} of the form :

View File

@ -31,7 +31,7 @@ val code_buffer : Buffer.t
val update_acc : Sedlexing.lexbuf -> unit
(** Updates {!val:code_buffer} with the current lexeme *)
val raise_lexer_error : Utils.Pos.t -> string -> 'a
val raise_lexer_error : Catala_utils.Pos.t -> string -> 'a
(** Error-generating helper *)
val token_list_language_agnostic : (string * Tokens.token) list

View File

@ -18,7 +18,7 @@
*)
%{
open Utils
open Catala_utils
%}
%parameter<Localisation: sig

View File

@ -19,7 +19,7 @@
Parser_driver.parse_source_file} API. *)
open Sedlexing
open Utils
open Catala_utils
(** {1 Internal functions} *)

View File

@ -17,6 +17,6 @@
(** Wrapping module around parser and lexer that offers the
[Surface.Parser_driver.parse_source_file] API. *)
open Utils
open Catala_utils
val parse_top_level_file : Pos.input_file -> Cli.backend_lang -> Ast.program

View File

@ -15,7 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Dcalc
open Ast

View File

@ -17,7 +17,7 @@
(** Generates verification conditions from scope definitions *)
open Utils
open Catala_utils
open Shared_ast
type verification_condition_kind =

View File

@ -3,7 +3,7 @@
(public_name catala.verification)
(libraries
bindlib
utils
catala_utils
dcalc
catala.runtime_ocaml
dates_calc

View File

@ -15,7 +15,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
module type Backend = sig

View File

@ -14,6 +14,8 @@
License for the specific language governing permissions and limitations under
the License. *)
open Catala_utils
(** [solve_vc] is the main entry point of this module. It takes a list of
expressions [vcs] corresponding to verification conditions that must be
discharged by Z3, and attempts to solve them **)
@ -45,4 +47,4 @@ let solve_vc
true z3_vcs
in
if all_proven then
Utils.Cli.result_format "No errors found during the proof mode run."
Cli.result_format "No errors found during the proof mode run."

View File

@ -18,7 +18,7 @@
without the expected backend. All functions print an error message and exit *)
let dummy () =
Utils.Cli.error_print
Catala_utils.Cli.error_print
"This instance of Catala was compiled without Z3 support.";
exit 124
@ -36,7 +36,6 @@ module Io = struct
type model = unit
type vc_encoding_result = Success of model * model | Fail of string
let print_positive_result _ = dummy ()
let print_negative_result _ _ _ = dummy ()
let encode_and_check_vc _ _ = dummy ()
end

View File

@ -14,7 +14,7 @@
License for the specific language governing permissions and limitations under
the License. *)
open Utils
open Catala_utils
open Shared_ast
open Dcalc
open Ast
@ -35,13 +35,13 @@ type context = {
(* A map from strings, corresponding to Z3 symbol names, to the Catala
variable they represent. Used when to pretty-print Z3 models when a
counterexample is generated *)
ctx_z3datatypes : Sort.sort EnumMap.t;
ctx_z3datatypes : Sort.sort EnumName.Map.t;
(* A map from Catala enumeration names to the corresponding Z3 sort, from
which we can retrieve constructors and accessors *)
ctx_z3matchsubsts : (typed expr, Expr.expr) Var.Map.t;
(* A map from Catala temporary variables, generated when translating a match,
to the corresponding enum accessor call as a Z3 expression *)
ctx_z3structs : Sort.sort StructMap.t;
ctx_z3structs : Sort.sort StructName.Map.t;
(* A map from Catala struct names to the corresponding Z3 sort, from which we
can retrieve the constructor and the accessors *)
ctx_z3unit : Sort.sort * Expr.expr;
@ -80,7 +80,7 @@ let add_z3var (name : string) (v : typed expr Var.t) (ty : typ) (ctx : context)
corresponding Z3 datatype [sort] to the context **)
let add_z3enum (enum : EnumName.t) (sort : Sort.sort) (ctx : context) : context
=
{ ctx with ctx_z3datatypes = EnumMap.add enum sort ctx.ctx_z3datatypes }
{ ctx with ctx_z3datatypes = EnumName.Map.add enum sort ctx.ctx_z3datatypes }
(** [add_z3matchsubst] adds the mapping between temporary variable [v] and the
Z3 expression [e] representing an accessor application to the context **)
@ -92,7 +92,7 @@ let add_z3matchsubst (v : typed expr Var.t) (e : Expr.expr) (ctx : context) :
corresponding Z3 datatype [sort] to the context **)
let add_z3struct (s : StructName.t) (sort : Sort.sort) (ctx : context) : context
=
{ ctx with ctx_z3structs = StructMap.add s sort ctx.ctx_z3structs }
{ ctx with ctx_z3structs = StructName.Map.add s sort ctx.ctx_z3structs }
let add_z3constraint (e : Expr.expr) (ctx : context) : context =
{ ctx with ctx_z3constraints = e :: ctx.ctx_z3constraints }
@ -161,16 +161,16 @@ let rec print_z3model_expr (ctx : context) (ty : typ) (e : Expr.expr) : string =
match Marked.unmark ty with
| TLit ty -> print_lit ty
| TStruct name ->
let s = StructMap.find name ctx.ctx_decl.ctx_structs in
let get_fieldname (fn : StructFieldName.t) : string =
Marked.unmark (StructFieldName.get_info fn)
let s = StructName.Map.find name ctx.ctx_decl.ctx_structs in
let get_fieldname (fn : StructField.t) : string =
Marked.unmark (StructField.get_info fn)
in
let fields =
List.map2
(fun (fn, ty) e ->
Format.asprintf "-- %s : %s" (get_fieldname fn)
(print_z3model_expr ctx ty e))
(StructFieldMap.bindings s)
(StructField.Map.bindings s)
(Expr.get_args e)
in
@ -187,13 +187,13 @@ let rec print_z3model_expr (ctx : context) (ty : typ) (e : Expr.expr) : string =
let fd = Expr.get_func_decl e in
let fd_name = Symbol.to_string (FuncDecl.get_name fd) in
let enum_ctrs = EnumMap.find name ctx.ctx_decl.ctx_enums in
let enum_ctrs = EnumName.Map.find name ctx.ctx_decl.ctx_enums in
let case =
List.find
(fun (ctr, _) ->
(* FIXME: don't match on strings *)
String.equal fd_name (Marked.unmark (EnumConstructor.get_info ctr)))
(EnumConstructorMap.bindings enum_ctrs)
(EnumConstructor.Map.bindings enum_ctrs)
in
Format.asprintf "%s (%s)" fd_name (print_z3model_expr ctx (snd case) e')
@ -310,12 +310,12 @@ and find_or_create_enum (ctx : context) (enum : EnumName.t) :
[Sort.get_id arg_z3_ty] )
in
match EnumMap.find_opt enum ctx.ctx_z3datatypes with
match EnumName.Map.find_opt enum ctx.ctx_z3datatypes with
| Some e -> ctx, e
| None ->
let ctrs = EnumMap.find enum ctx.ctx_decl.ctx_enums in
let ctrs = EnumName.Map.find enum ctx.ctx_decl.ctx_enums in
let ctx, z3_ctrs =
EnumConstructorMap.fold
EnumConstructor.Map.fold
(fun ctr ty (ctx, ctrs) ->
let ctx, ctr = create_constructor ctr ty ctx in
ctx, ctr :: ctrs)
@ -334,20 +334,20 @@ and find_or_create_enum (ctx : context) (enum : EnumName.t) :
context *)
and find_or_create_struct (ctx : context) (s : StructName.t) :
context * Sort.sort =
match StructMap.find_opt s ctx.ctx_z3structs with
match StructName.Map.find_opt s ctx.ctx_z3structs with
| Some s -> ctx, s
| None ->
let s_name = Marked.unmark (StructName.get_info s) in
let fields = StructMap.find s ctx.ctx_decl.ctx_structs in
let fields = StructName.Map.find s ctx.ctx_decl.ctx_structs in
let z3_fieldnames =
List.map
(fun f ->
Marked.unmark (StructFieldName.get_info (fst f))
Marked.unmark (StructField.get_info (fst f))
|> Symbol.mk_string ctx.ctx_z3)
(StructFieldMap.bindings fields)
(StructField.Map.bindings fields)
in
let ctx, z3_fieldtypes_rev =
StructFieldMap.fold
StructField.Map.fold
(fun _ ty (ctx, ftypes) ->
let ctx, ftype = translate_typ ctx (Marked.unmark ty) in
ctx, ftype :: ftypes)
@ -426,8 +426,8 @@ let is_leap_year = Runtime.is_leap_year
(** [translate_op] returns the Z3 expression corresponding to the application of
[op] to the arguments [args] **)
let rec translate_op (ctx : context) (op : operator) (args : 'm expr list) :
context * Expr.expr =
let rec translate_op (ctx : context) (op : dcalc operator) (args : 'm expr list)
: context * Expr.expr =
match op with
| Ternop _top ->
let _e1, _e2, _e3 =
@ -709,14 +709,12 @@ and translate_expr (ctx : context) (vc : typed expr) : context * Expr.expr =
let idx_mappings =
List.combine
(List.map fst
(StructFieldMap.bindings
(StructMap.find name ctx.ctx_decl.ctx_structs)))
(StructField.Map.bindings
(StructName.Map.find name ctx.ctx_decl.ctx_structs)))
accessors
in
let _, accessor =
List.find
(fun (field1, _) -> StructFieldName.equal field field1)
idx_mappings
List.find (fun (field1, _) -> StructField.equal field field1) idx_mappings
in
let ctx, s = translate_expr ctx e in
ctx, Expr.mk_app ctx.ctx_z3 accessor [s]
@ -730,8 +728,8 @@ and translate_expr (ctx : context) (vc : typed expr) : context * Expr.expr =
let idx_mappings =
List.combine
(List.map fst
(EnumConstructorMap.bindings
(EnumMap.find name ctx.ctx_decl.ctx_enums)))
(EnumConstructor.Map.bindings
(EnumName.Map.find name ctx.ctx_decl.ctx_enums)))
ctrs
in
let _, ctr =
@ -760,7 +758,7 @@ and translate_expr (ctx : context) (vc : typed expr) : context * Expr.expr =
(translate_match_arm z3_arg)
ctx
(List.combine
(List.map snd (EnumConstructorMap.bindings cases))
(List.map snd (EnumConstructor.Map.bindings cases))
(Datatype.get_accessors z3_enum))
in
let z3_arms =
@ -873,9 +871,9 @@ module Backend = struct
ctx_decl = decl_ctx;
ctx_funcdecl = Var.Map.empty;
ctx_z3vars = StringMap.empty;
ctx_z3datatypes = EnumMap.empty;
ctx_z3datatypes = EnumName.Map.empty;
ctx_z3matchsubsts = Var.Map.empty;
ctx_z3structs = StructMap.empty;
ctx_z3structs = StructName.Map.empty;
ctx_z3unit = z3unit;
ctx_z3constraints = [];
}

View File

@ -33,17 +33,15 @@ Message: unexpected token
Autosuggestion: did you mean "content", or maybe "condition"?
Error token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾
Last good token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾‾‾‾‾
@ -79,17 +77,15 @@ Message: unexpected token
Autosuggestion: did you mean "content", or maybe "condition"?
Error token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾
Last good token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾‾‾‾‾
@ -125,17 +121,15 @@ Message: unexpected token
Autosuggestion: did you mean "content", or maybe "condition"?
Error token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾
Last good token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾‾‾‾‾
@ -173,17 +167,15 @@ Message: unexpected token
Autosuggestion: did you mean "content", or maybe "condition"?
Error token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.20-25:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾
Last good token:
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19
┌─⯈ examples/NSW_community_gaming/tests/test_nsw_social_housie.catala_en:11.10-19:
└──┐
11 │ context my_gaming scope GamingAuthorized
│ ‾‾‾‾‾‾‾‾‾

View File

@ -640,9 +640,9 @@ champ d'application ÉligibilitéAidePersonnaliséeLogement:
règle condition_logement_bailleur sous condition
selon ménage.logement.mode_occupation sous forme
-- Locataire de location:
(selon location.Location.bailleur sous forme
(selon location.bailleur sous forme
-- BailleurSocial de convention:
convention.ConventionBailleurSocial.
convention.
conventionné_livre_III_titre_V_chap_III
-- BailleurPrivéAvecConventionnementSocial de convention:
convention.conventionné_livre_III_titre_II_chap_I_sec_3
@ -683,7 +683,7 @@ champ d'application ÉligibilitéAidePersonnaliséeLogement:
règle condition_logement_bailleur sous condition
selon ménage.logement.mode_occupation sous forme
-- RésidentLogementFoyer de location:
location.LogementFoyer.conventionné_livre_III_titre_V_chap_III
location.conventionné_livre_III_titre_V_chap_III
-- n'importe quel: faux
conséquence rempli
```
@ -891,19 +891,19 @@ champ d'application ÉligibilitéAllocationLogement:
-- AutrePersonneÀCharge: faux
-- EnfantÀCharge de enfant: (prestations_familiales.droit_ouvert de
EnfantPrestationsFamiliales {
-- identifiant: enfant.EnfantÀCharge.identifiant
-- obligation_scolaire: enfant.EnfantÀCharge.obligation_scolaire
-- rémuneration_mensuelle: enfant.EnfantÀCharge.rémuneration_mensuelle
-- date_de_naissance: enfant.EnfantÀCharge.date_de_naissance
-- identifiant: enfant.identifiant
-- obligation_scolaire: enfant.obligation_scolaire
-- rémuneration_mensuelle: enfant.rémuneration_mensuelle
-- date_de_naissance: enfant.date_de_naissance
-- prise_en_charge: (selon enfant.situation_garde_alternée sous forme
-- GardeAlternéeCoefficientPriseEnCharge:
PriseEnChargeEnfant.GardeAlternéePartageAllocations
-- PasDeGardeAlternée:
PriseEnChargeEnfant.EffectiveEtPermanente)
-- a_déjà_ouvert_droit_aux_allocations_familiales:
enfant.EnfantÀCharge.a_déjà_ouvert_droit_aux_allocations_familiales
enfant.a_déjà_ouvert_droit_aux_allocations_familiales
-- bénéficie_titre_personnel_aide_personnelle_logement:
enfant.EnfantÀCharge.
enfant.
bénéficie_titre_personnel_aide_personnelle_logement
}
)
@ -923,19 +923,19 @@ champ d'application ÉligibilitéAllocationLogement:
-- AutrePersonneÀCharge: faux
-- EnfantÀCharge de enfant: non (prestations_familiales.droit_ouvert de
EnfantPrestationsFamiliales {
-- identifiant: enfant.EnfantÀCharge.identifiant
-- obligation_scolaire: enfant.EnfantÀCharge.obligation_scolaire
-- rémuneration_mensuelle: enfant.EnfantÀCharge.rémuneration_mensuelle
-- date_de_naissance: enfant.EnfantÀCharge.date_de_naissance
-- identifiant: enfant.identifiant
-- obligation_scolaire: enfant.obligation_scolaire
-- rémuneration_mensuelle: enfant.rémuneration_mensuelle
-- date_de_naissance: enfant.date_de_naissance
-- prise_en_charge: (selon enfant.situation_garde_alternée sous forme
-- GardeAlternéeCoefficientPriseEnCharge:
PriseEnChargeEnfant.GardeAlternéePartageAllocations
-- PasDeGardeAlternée:
PriseEnChargeEnfant.EffectiveEtPermanente)
-- a_déjà_ouvert_droit_aux_allocations_familiales:
enfant.EnfantÀCharge.a_déjà_ouvert_droit_aux_allocations_familiales
enfant.a_déjà_ouvert_droit_aux_allocations_familiales
-- bénéficie_titre_personnel_aide_personnelle_logement:
enfant.EnfantÀCharge.
enfant.
bénéficie_titre_personnel_aide_personnelle_logement
}
)

View File

@ -128,7 +128,7 @@ champ d'application RessourcesAidesPersonnelleLogement:
définition ressources_personnes_vivant_habituellement_foyer égal à
somme argent pour personne dans personnes_vivant_habituellement_foyer de
personne.PersonneVivantHabituellementAuFoyer.ressources
personne.ressources
```
Sont considérées comme vivant habituellement au foyer les personnes y ayant
@ -1137,7 +1137,7 @@ champ d'application ÉligibilitéAidesPersonnelleLogement:
règle prise_en_compte_personne_à_charge de personne_à_charge sous condition
selon personne_à_charge sous forme
-- EnfantÀCharge de enfant:
enfant.EnfantÀCharge.date_de_naissance +@ 21 an >@ date_courante
enfant.date_de_naissance +@ 21 an >@ date_courante
-- AutrePersonneÀCharge de parent: faux
conséquence rempli
```
@ -1163,16 +1163,16 @@ champ d'application ÉligibilitéAidesPersonnelleLogement:
-- EnfantÀCharge de enfant: faux
-- AutrePersonneÀCharge de parent:
parent.parenté = Ascendant et
parent.AutrePersonneÀCharge.ressources <=€
parent.ressources <=€
plafond_individuel_l815_9_sécu *€ 1,25 et
(
(parent.AutrePersonneÀCharge.date_naissance +@
(parent.date_naissance +@
âge_l351_8_1_sécu <=@ date_courante ou
(parent.titulaire_allocation_personne_âgée et
parent.AutrePersonneÀCharge.date_naissance +@ 65 an <=@
parent.date_naissance +@ 65 an <=@
date_courante)
) ou
(parent.AutrePersonneÀCharge.date_naissance +@
(parent.date_naissance +@
âge_l161_17_2_sécu <=@ date_courante et
parent.bénéficiaire_l161_19_l351_8_l643_3_sécu)
)
@ -1204,7 +1204,7 @@ champ d'application ÉligibilitéAidesPersonnelleLogement:
-- AutrePersonneÀCharge de parent:
# Pas besoin de préciser parenté car inclusif ici
parent.incapacité_80_pourcent_ou_restriction_emploi et
parent.AutrePersonneÀCharge.ressources <=€
parent.ressources <=€
plafond_individuel_l815_9_sécu *€ 1,25
conséquence rempli
```
@ -1393,7 +1393,7 @@ champ d'application CalculAllocationLogement:
AccessionPropriété contenu propriétaire
définition aide_finale_formule égal à
sous_calcul_traitement.Traitement_formule_aide_finale.aide_finale_formule
sous_calcul_traitement.aide_finale_formule
définition traitement_aide_finale de arg égal à
(sous_calcul_traitement.
Traitement_formule_aide_finale.traitement_aide_finale de arg)
@ -1411,7 +1411,7 @@ champ d'application CalculAidePersonnaliséeLogement:
AccessionPropriété contenu propriétaire
définition aide_finale_formule égal à
sous_calcul_traitement.Traitement_formule_aide_finale.aide_finale_formule
sous_calcul_traitement.aide_finale_formule
définition traitement_aide_finale de arg égal à
(sous_calcul_traitement.
Traitement_formule_aide_finale.traitement_aide_finale de arg)
@ -1441,7 +1441,7 @@ champ d'application CalculAidePersonnaliséeLogement:
location.âgées_ou_handicap_adultes_hébergées_onéreux_particuliers
-- type_aide: type_aide
-- réduction_loyer_solidarité:
(selon location.Location.bailleur sous forme
(selon location.bailleur sous forme
-- BailleurSocial de bailleur:
bailleur.réduction_loyer_solidarité_perçue
-- n'importe quel: 0€)
@ -1525,7 +1525,7 @@ champ d'application CalculAllocationLogement:
location.âgées_ou_handicap_adultes_hébergées_onéreux_particuliers
-- type_aide: type_aide
-- réduction_loyer_solidarité:
(selon location.Location.bailleur sous forme
(selon location.bailleur sous forme
-- BailleurSocial de bailleur:
bailleur.réduction_loyer_solidarité_perçue
-- n'importe quel: 0€)
@ -1534,7 +1534,7 @@ champ d'application CalculAllocationLogement:
}
dans Traitement_formule_aide_finale {
-- aide_finale_formule:
traitement_formule.CalculAllocationLogementLocatif.aide_finale_formule
traitement_formule.aide_finale_formule
-- traitement_aide_finale:
traitement_formule.
CalculAllocationLogementLocatif.
@ -1557,7 +1557,7 @@ champ d'application CalculAllocationLogement:
location.âgées_ou_handicap_adultes_hébergées_onéreux_particuliers
-- type_aide: type_aide
-- réduction_loyer_solidarité:
(selon location.Location.bailleur sous forme
(selon location.bailleur sous forme
-- BailleurSocial de bailleur:
bailleur.réduction_loyer_solidarité_perçue
-- n'importe quel: 0€)
@ -1588,7 +1588,7 @@ champ d'application CalculAllocationLogement:
}
dans Traitement_formule_aide_finale {
-- aide_finale_formule:
traitement_formule.CalculAllocationLogementFoyer.aide_finale_formule
traitement_formule.aide_finale_formule
-- traitement_aide_finale:
traitement_formule.
CalculAllocationLogementFoyer.traitement_aide_finale
@ -2973,8 +2973,8 @@ par l'article D. 331-64.
champ d'application ÉligibilitéAidePersonnaliséeLogement:
règle caractéristiques_prêt_l831_1_1 de prêt sous condition
prêt.titulaire_prêt sous forme Demandeur et (
prêt.Prêt.type_prêt sous forme D331_32 ou
prêt.Prêt.type_prêt sous forme D331_63_64)
prêt.type_prêt sous forme D331_32 ou
prêt.type_prêt sous forme D331_63_64)
conséquence rempli
```
@ -3009,8 +3009,8 @@ champ d'application ÉligibilitéAidePersonnaliséeLogement:
règle caractéristiques_prêt_l831_1_1 de prêt sous condition
prêt.titulaire_prêt sous forme
VendeurQuandDemandeurAContratLocationAccession et (
prêt.Prêt.type_prêt sous forme D331_59_8 ou
prêt.Prêt.type_prêt sous forme D331_76_1)
prêt.type_prêt sous forme D331_59_8 ou
prêt.type_prêt sous forme D331_76_1)
conséquence rempli
```
@ -4027,14 +4027,14 @@ champ d'application CalculÉquivalenceLoyerMinimale:
définition tranches_revenus_d832_26_multipliées égal à
application pour tranche dans tranches_revenus_d832_26 de
TrancheRevenuDécimal {
-- haut: (selon tranche.TrancheRevenu.haut sous forme
-- haut: (selon tranche.haut sous forme
-- LimiteTranche.Infini: LimiteTrancheDécimal.Infini
-- LimiteTranche.Revenu de tranche_haut:
LimiteTrancheDécimal.Revenu contenu
((argent_vers_décimal de tranche_haut) *. n_nombre_parts_d832_25))
-- bas: argent_vers_décimal de tranche.TrancheRevenu.bas *.
-- bas: argent_vers_décimal de tranche.bas *.
n_nombre_parts_d832_25
-- taux: tranche.TrancheRevenu.taux
-- taux: tranche.taux
}
définition montant égal à
@ -4044,23 +4044,23 @@ champ d'application CalculÉquivalenceLoyerMinimale:
décimal_vers_argent de (
(((somme décimal pour tranche dans tranches_revenus_d832_26_multipliées de
(si
ressources_ménage_arrondies <=. tranche.TrancheRevenuDécimal.bas
ressources_ménage_arrondies <=. tranche.bas
alors 0,0
sinon
(selon tranche.TrancheRevenuDécimal.haut sous forme
(selon tranche.haut sous forme
-- LimiteTrancheDécimal.Revenu de tranche_haut:
(si
ressources_ménage_arrondies >=. tranche_haut
alors
(tranche_haut -. tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux
(tranche_haut -. tranche.bas) *.
tranche.taux
sinon
((ressources_ménage_arrondies -.
tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux))
tranche.bas) *.
tranche.taux))
-- LimiteTrancheDécimal.Infini:
(ressources_ménage_arrondies -. tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux)
(ressources_ménage_arrondies -. tranche.bas) *.
tranche.taux)
))) +.
argent_vers_décimal de montant_forfaitaire_d832_26 *.
n_nombre_parts_d832_25) /. 12,0)
@ -4083,23 +4083,23 @@ champ d'application CalculÉquivalenceLoyerMinimale:
décimal_vers_argent de (
(((somme décimal pour tranche dans tranches_revenus_d832_26_multipliées de
(si
ressources_ménage_arrondies <=. tranche.TrancheRevenuDécimal.bas
ressources_ménage_arrondies <=. tranche.bas
alors 0,0
sinon
(selon tranche.TrancheRevenuDécimal.haut sous forme
(selon tranche.haut sous forme
-- LimiteTrancheDécimal.Revenu de tranche_haut:
(si
ressources_ménage_arrondies >=. tranche_haut
alors
(tranche_haut -. tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux
(tranche_haut -. tranche.bas) *.
tranche.taux
sinon
((ressources_ménage_arrondies -.
tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux))
tranche.bas) *.
tranche.taux))
-- LimiteTrancheDécimal.Infini:
(ressources_ménage_arrondies -. tranche.TrancheRevenuDécimal.bas) *.
tranche.TrancheRevenuDécimal.taux)
(ressources_ménage_arrondies -. tranche.bas) *.
tranche.taux)
))) +.
argent_vers_décimal de montant_forfaitaire_d832_26) /. 12,0)
```

View File

@ -121,7 +121,7 @@ champ d'application OuvertureDroitsRetraite:
champ d'application ÉligibilitéAidesPersonnelleLogement:
définition ouverture_droits_retraite.date_naissance_assuré égal à
demandeur.Demandeur.date_naissance
demandeur.date_naissance
définition âge_l161_17_2_sécu égal à
ouverture_droits_retraite.âge_ouverture_droit
```

View File

@ -53,8 +53,8 @@ ouvre droit aux prestations familiales :
```catala
champ d'application ÉligibilitéPrestationsFamiliales :
étiquette cas_base règle droit_ouvert de enfant sous condition
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Avant ou
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Pendant
enfant.obligation_scolaire sous forme Avant ou
enfant.obligation_scolaire sous forme Pendant
conséquence rempli
```
@ -64,20 +64,20 @@ dont la rémunération éventuelle n'excède pas un plafond.
```catala
champ d'application ÉligibilitéPrestationsFamiliales :
étiquette cas_base règle droit_ouvert de enfant sous condition
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Après et
(enfant.EnfantPrestationsFamiliales.rémuneration_mensuelle <=€
enfant.obligation_scolaire sous forme Après et
(enfant.rémuneration_mensuelle <=€
plafond_l512_3_2) et
(enfant.EnfantPrestationsFamiliales.date_de_naissance +@ âge_l512_3_2 >@
(enfant.date_de_naissance +@ âge_l512_3_2 >@
date_courante)
conséquence rempli
# On définit les conditions hors âge d'abord car elles
# sont référencées plus tard dans l'article L521-1
règle conditions_hors_âge de enfant sous condition
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Avant ou
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Pendant ou
enfant.EnfantPrestationsFamiliales.obligation_scolaire sous forme Après et
(enfant.EnfantPrestationsFamiliales.rémuneration_mensuelle <=€
enfant.obligation_scolaire sous forme Avant ou
enfant.obligation_scolaire sous forme Pendant ou
enfant.obligation_scolaire sous forme Après et
(enfant.rémuneration_mensuelle <=€
plafond_l512_3_2)
conséquence rempli
```

Some files were not shown because too many files have changed in this diff Show More