From 1c1f5beb4c45d1a1867774cb1092e1acbf9212a0 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 22 Nov 2020 20:56:27 +0100 Subject: [PATCH 001/142] Implemented type inference for default calculus --- src/catala/dune | 2 +- src/catala/revamping/dcalculus_ast.ml | 34 +++++++ src/catala/revamping/dcalculus_typing.ml | 121 +++++++++++++++++++++++ 3 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 src/catala/revamping/dcalculus_ast.ml create mode 100644 src/catala/revamping/dcalculus_typing.ml diff --git a/src/catala/dune b/src/catala/dune index 652c0f06..d8d5117e 100644 --- a/src/catala/dune +++ b/src/catala/dune @@ -3,7 +3,7 @@ (library (public_name catala) (libraries ANSITerminal sedlex menhirLib re cmdliner dune-build-info - ocamlgraph) + ocamlgraph bindlib unionFind) (preprocess (pps sedlex.ppx))) diff --git a/src/catala/revamping/dcalculus_ast.ml b/src/catala/revamping/dcalculus_ast.ml new file mode 100644 index 00000000..be499f5f --- /dev/null +++ b/src/catala/revamping/dcalculus_ast.ml @@ -0,0 +1,34 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +type typ = TBool | TUnit | TArrow of typ Pos.marked * typ Pos.marked + +type lit = LTrue | LFalse | LEmptyError | LConflictError + +type expr = + | EVar of expr Bindlib.var + | ELit of lit + | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.binder * typ + | EApp of expr Pos.marked * expr Pos.marked + | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + +module Var = struct + type t = expr Bindlib.var + + let compare x y = Bindlib.compare_vars x y +end + +module VarMap = Map.Make (Var) + +type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/revamping/dcalculus_typing.ml b/src/catala/revamping/dcalculus_typing.ml new file mode 100644 index 00000000..c2fe9fb7 --- /dev/null +++ b/src/catala/revamping/dcalculus_typing.ml @@ -0,0 +1,121 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +(** Typing for the default calculus. Because of the error terms, we perform type inference using the + classical W algorithm with union-find unification. *) + +module A = Dcalculus_ast + +type typ = + | TUnit + | TBool + | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem + | TAny + +let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = + let ty_repr = UnionFind.get (UnionFind.find ty) in + match Pos.unmark ty_repr with + | TUnit -> Format.fprintf fmt "unit" + | TBool -> Format.fprintf fmt "bool" + | TAny -> Format.fprintf fmt "any" + | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 + +let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = + let t1_repr = UnionFind.get (UnionFind.find t1) in + let t2_repr = UnionFind.get (UnionFind.find t2) in + match (t1_repr, t2_repr) with + | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) -> () + | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> + unify t11 t21; + unify t12 t22 + | (TAny, _), (TAny, _) -> ignore (UnionFind.union t1 t2) + | (TAny, _), t_repr | t_repr, (TAny, _) -> + let t_union = UnionFind.union t1 t2 in + ignore (UnionFind.set t_union t_repr) + | (_, t1_pos), (_, t2_pos) -> + Errors.raise_multispanned_error + (Format.asprintf "Error during typechecking, type mismatch: cannot unify %a and %a" + format_typ t1 format_typ t2) + [ + (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); + (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); + ] + +let rec ast_to_typ (ty : A.typ) : typ = + match ty with + | A.TUnit -> TUnit + | A.TBool -> TBool + | A.TArrow (t1, t2) -> + TArrow + ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), + UnionFind.make (Pos.map_under_mark ast_to_typ t2) ) + +type env = { expr_vars : typ Pos.marked A.VarMap.t } + +let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem + = + match Pos.unmark e with + | EVar v -> ( + match A.VarMap.find_opt v env.expr_vars with + | Some t -> UnionFind.make t + | None -> + Errors.raise_spanned_error "Variable not found in the current context" + (Pos.get_position e) ) + | ELit (LTrue | LFalse) -> UnionFind.make (Pos.same_pos_as TBool e) + | ELit (LEmptyError | LConflictError) -> UnionFind.make (Pos.same_pos_as TAny e) + | EAbs (pos_binder, binder, tau) -> + let x, body = Bindlib.unbind binder in + let env = { expr_vars = A.VarMap.add x (ast_to_typ tau, pos_binder) env.expr_vars } in + typecheck_expr_bottom_up env body + | EApp (e1, e2) -> + let t2 = typecheck_expr_bottom_up env e2 in + let t_arg = UnionFind.make (Pos.same_pos_as TAny e) in + let t_app = UnionFind.make (Pos.same_pos_as (TArrow (t_arg, t2)) e) in + typecheck_expr_top_down env e1 t_app; + t_app + | EDefault (just, cons, subs) -> + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + let tcons = typecheck_expr_bottom_up env cons in + List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; + tcons + +and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) + (tau : typ Pos.marked UnionFind.elem) : unit = + match Pos.unmark e with + | EVar v -> ( + match A.VarMap.find_opt v env.expr_vars with + | Some tau' -> ignore (unify tau (UnionFind.make tau')) + | None -> + Errors.raise_spanned_error "Variable not found in the current context" + (Pos.get_position e) ) + | ELit (LTrue | LFalse) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) + | ELit (LEmptyError | LConflictError) -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) + | EAbs (pos_binder, binder, t_arg) -> + let x, body = Bindlib.unbind binder in + let env = { expr_vars = A.VarMap.add x (ast_to_typ t_arg, pos_binder) env.expr_vars } in + let t_out = typecheck_expr_bottom_up env body in + let t_func = + UnionFind.make + (Pos.same_pos_as (TArrow (UnionFind.make (ast_to_typ t_arg, pos_binder), t_out)) e) + in + unify t_func tau + | EApp (e1, e2) -> + let te2 = typecheck_expr_bottom_up env e2 in + let te1 = typecheck_expr_bottom_up env e1 in + let t_func = UnionFind.make (Pos.same_pos_as (TArrow (te2, tau)) e) in + unify te1 t_func + | EDefault (just, cons, subs) -> + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + typecheck_expr_top_down env cons tau; + List.iter (fun sub -> typecheck_expr_top_down env sub tau) subs From 32800d3011ccbfdb3e56e4fd808604072e1c5da8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 22 Nov 2020 21:00:14 +0100 Subject: [PATCH 002/142] Added unionfind as a dependencu --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 9a9bd5a3..f6ab8de3 100644 --- a/Makefile +++ b/Makefile @@ -18,8 +18,9 @@ install-dependencies-ocaml: menhirLib \ dune dune-build-info \ cmdliner obelisk \ - re reason\ - obelisk\ + re reason \ + obelisk \ + unionfind \ ocamlgraph init-submodules: From 4c66a09895bf8c2b65988aa61333b5fc8312109c Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 22 Nov 2020 21:04:29 +0100 Subject: [PATCH 003/142] Added bindlib as a dependency --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index f6ab8de3..faac5b99 100644 --- a/Makefile +++ b/Makefile @@ -21,6 +21,7 @@ install-dependencies-ocaml: re reason \ obelisk \ unionfind \ + bindlib \ ocamlgraph init-submodules: From 0888422eadcd7d15afe260d47895787e74927f33 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 09:22:47 +0100 Subject: [PATCH 004/142] Big code reorg with better dune config --- .github/workflows/build.yml | 5 - dune-project | 1 + .../catala_surface/{catala_ast.ml => ast.ml} | 2 + src/catala/catala_surface/desugaring.ml | 235 -------------- src/catala/catala_surface/dune | 7 + src/catala/catala_surface/lexer.ml | 6 +- src/catala/catala_surface/lexer_en.ml | 6 +- src/catala/catala_surface/lexer_fr.ml | 9 +- src/catala/catala_surface/parser.mly | 8 +- src/catala/catala_surface/parser_driver.ml | 19 +- .../ast.ml} | 2 + src/catala/default_calculus/dune | 4 + .../typing.ml} | 4 +- src/catala/driver.ml | 45 ++- src/catala/dune | 8 +- src/catala/lambda_calculus/format_lambda.ml | 84 ----- src/catala/lambda_calculus/lambda_ast.ml | 120 ------- .../lambda_calculus/lambda_interpreter.ml | 218 ------------- .../lambda_calculus/lambda_typechecker.ml | 138 -------- src/catala/literate_programming/dune | 4 + src/catala/literate_programming/html.ml | 5 +- src/catala/literate_programming/latex.ml | 5 +- .../scope_language/{scope_ast.ml => ast.ml} | 11 +- src/catala/scope_language/desugaring.ml | 182 +++++++++++ src/catala/scope_language/dune | 4 + .../{format_scope.ml => format.ml} | 10 +- src/catala/scope_language/interpreter.ml | 126 ++++++++ .../name_resolution.ml | 90 +++--- .../scope_language/scope_interpreter.ml | 301 ------------------ src/catala/scope_language/uid.ml | 1 + src/catala/scope_language/uid.mli | 2 + src/catala/{ => utils}/cli.ml | 0 src/catala/utils/dune | 4 + src/catala/{ => utils}/errors.ml | 0 src/catala/{ => utils}/pos.ml | 0 src/catala/{ => utils}/pos.mli | 0 36 files changed, 461 insertions(+), 1205 deletions(-) rename src/catala/catala_surface/{catala_ast.ml => ast.ml} (99%) delete mode 100644 src/catala/catala_surface/desugaring.ml rename src/catala/{revamping/dcalculus_ast.ml => default_calculus/ast.ml} (98%) create mode 100644 src/catala/default_calculus/dune rename src/catala/{revamping/dcalculus_typing.ml => default_calculus/typing.ml} (98%) delete mode 100644 src/catala/lambda_calculus/format_lambda.ml delete mode 100644 src/catala/lambda_calculus/lambda_ast.ml delete mode 100644 src/catala/lambda_calculus/lambda_interpreter.ml delete mode 100644 src/catala/lambda_calculus/lambda_typechecker.ml create mode 100644 src/catala/literate_programming/dune rename src/catala/scope_language/{scope_ast.ml => ast.ml} (83%) create mode 100644 src/catala/scope_language/desugaring.ml create mode 100644 src/catala/scope_language/dune rename src/catala/scope_language/{format_scope.ml => format.ml} (83%) create mode 100644 src/catala/scope_language/interpreter.ml rename src/catala/{catala_surface => scope_language}/name_resolution.ml (77%) delete mode 100644 src/catala/scope_language/scope_interpreter.ml rename src/catala/{ => utils}/cli.ml (100%) create mode 100644 src/catala/utils/dune rename src/catala/{ => utils}/errors.ml (100%) rename src/catala/{ => utils}/pos.ml (100%) rename src/catala/{ => utils}/pos.mli (100%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index df9207a9..08c057c2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -55,11 +55,6 @@ jobs: eval $(opam env) make build - - name: Run tests - run: | - eval $(opam env) - make tests - - name: Make examples run: | eval $(opam env) diff --git a/dune-project b/dune-project index 6829ba13..1c7ab125 100644 --- a/dune-project +++ b/dune-project @@ -2,6 +2,7 @@ (name catala) (version 0.1.1) (generate_opam_files true) +(formatting) (source (uri git+https://github.com/CatalaLang/catala.git)) (homepage https://github.com/CatalaLang/catala) diff --git a/src/catala/catala_surface/catala_ast.ml b/src/catala/catala_surface/ast.ml similarity index 99% rename from src/catala/catala_surface/catala_ast.ml rename to src/catala/catala_surface/ast.ml index ee7fb811..0fc97640 100644 --- a/src/catala/catala_surface/catala_ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -12,6 +12,8 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Pos = Utils.Pos + type constructor = string type ident = string diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml deleted file mode 100644 index e5295c83..00000000 --- a/src/catala/catala_surface/desugaring.ml +++ /dev/null @@ -1,235 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - Denis Merigoux - - 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 Catala_ast -open Lambda_ast - -(** The optional argument subdef allows to choose between differents uids in case the expression is - a redefinition of a subvariable *) -let rec expr_to_lambda (scope : Uid.Scope.t) (def_key : Uid.ScopeDef.t option) - (ctxt : Name_resolution.context) ((expr, pos) : Catala_ast.expression Pos.marked) : - Lambda_ast.term = - let scope_ctxt = Uid.ScopeMap.find scope ctxt.scopes in - let rec_helper = expr_to_lambda scope def_key ctxt in - match expr with - | IfThenElse (e_if, e_then, e_else) -> - ((EIfThenElse (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos), TDummy) - | Binop (op, e1, e2) -> - let op_term = (Pos.same_pos_as (EOp (Binop (Pos.unmark op))) op, TDummy) in - ((EApp (op_term, [ rec_helper e1; rec_helper e2 ]), pos), TDummy) - | Unop (op, e) -> - let op_term = (Pos.same_pos_as (EOp (Unop (Pos.unmark op))) op, TDummy) in - ((EApp (op_term, [ rec_helper e ]), pos), TDummy) - | Literal l -> - let untyped_term = - match l with - | Number ((Int i, _), _) -> EInt i - | Number ((Dec (i, f), _), _) -> EDec (i, f) - | Bool b -> EBool b - | _ -> Name_resolution.raise_unsupported_feature "literal" pos - in - ((untyped_term, pos), TDummy) - | Ident x -> ( - (* first we check whether this is a local var, then we resort to scope-wide variables *) - match def_key with - | Some def_key -> ( - let def_ctxt = Uid.ScopeDefMap.find def_key scope_ctxt.definitions in - match Uid.IdentMap.find_opt x def_ctxt.var_idmap with - | None -> ( - match Uid.IdentMap.find_opt x scope_ctxt.var_idmap with - | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) - | None -> - Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" - (x, pos) ) - | Some uid -> ((ELocalVar uid, pos), TDummy) ) - | None -> ( - match Uid.IdentMap.find_opt x scope_ctxt.var_idmap with - | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) - | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) - ) - | Dotted (e, x) -> ( - (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) - match Pos.unmark e with - | Ident y -> - let subscope_uid : Uid.SubScope.t = - Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) - in - let subscope_real_uid : Uid.Scope.t = - Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes - in - let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in - ((EVar (SubScopePrefix subscope_uid, subscope_var_uid), pos), TDummy) - | _ -> - Name_resolution.raise_unsupported_feature - "left hand side of a dotted expression should be an identifier" pos ) - | FunCall (f, arg) -> ((EApp (rec_helper f, [ rec_helper arg ]), pos), TDummy) - | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos - -(* Translation from the parsed ast to the scope language *) - -let merge_conditions (precond : Lambda_ast.term option) (cond : Lambda_ast.term option) - (default_pos : Pos.t) : Lambda_ast.term = - match (precond, cond) with - | Some precond, Some cond -> - let op_term = ((EOp (Binop And), Pos.get_position (fst precond)), TDummy) in - ((EApp (op_term, [ precond; cond ]), Pos.get_position (fst precond)), TDummy) - | Some cond, None | None, Some cond -> cond - | None, None -> ((EBool true, default_pos), TBool) - -let process_default (ctxt : Name_resolution.context) (scope : Uid.Scope.t) - (def_key : Uid.ScopeDef.t) (def : Lambda_ast.default_term) (param_uid : Uid.LocalVar.t option) - (precond : Lambda_ast.term option) (just : Catala_ast.expression Pos.marked option) - (body : Catala_ast.expression Pos.marked) : Lambda_ast.default_term = - let just = - match just with - | Some cond -> Some (expr_to_lambda scope (Some def_key) ctxt cond) - | None -> None - in - let condition = merge_conditions precond just (Pos.get_position body) in - let body = expr_to_lambda scope (Some def_key) ctxt body in - (* if there's a parameter, we have to wrap the justifiction and the body in a func *) - let condition, body = - match param_uid with - | None -> (condition, body) - | Some param_uid -> - ( ((EFun ([ (param_uid, TDummy) ], condition), Pos.get_position (fst condition)), TDummy), - ((EFun ([ (param_uid, TDummy) ], body), Pos.get_position (fst body)), TDummy) ) - in - Lambda_ast.add_default condition body def - -(* Process a definition *) -let process_def (precond : Lambda_ast.term option) (scope_uid : Uid.Scope.t) - (ctxt : Name_resolution.context) (prgm : Scope_ast.program) (def : Catala_ast.definition) : - Scope_ast.program = - let scope : Scope_ast.scope = Uid.ScopeMap.find scope_uid prgm in - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in - let default_pos = Pos.get_position def.definition_expr in - let param_uid (def_uid : Uid.ScopeDef.t) : Uid.LocalVar.t option = - match def.definition_parameter with - | None -> None - | Some param -> - let def_ctxt = Uid.ScopeDefMap.find def_uid scope_ctxt.definitions in - Some (Uid.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) - in - let def_key = - match Pos.unmark def.definition_name with - | [ x ] -> - let x_uid = Name_resolution.get_var_uid scope_uid ctxt x in - Uid.ScopeDef.Var x_uid - | [ y; x ] -> - let subscope_uid : Uid.SubScope.t = Name_resolution.get_subscope_uid scope_uid ctxt y in - let subscope_real_uid : Uid.Scope.t = - Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes - in - let x_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in - Uid.ScopeDef.SubScopeVar (subscope_uid, x_uid) - | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos - in - let scope_updated = - let x_def = - match Uid.ScopeDefMap.find_opt def_key scope.scope_defs with - | Some def -> def - | None -> - let typ = Name_resolution.get_def_typ ctxt def_key in - Scope_ast.empty_def default_pos typ - in - let x_def = - Lambda_ast.map_untype - (fun t -> - match t with - | EDefault default -> - EDefault - (process_default ctxt scope_uid def_key default (param_uid def_key) precond - def.definition_condition def.definition_expr) - | _ -> assert false - (* should not happen *)) - x_def - in - { scope with scope_defs = Uid.ScopeDefMap.add def_key x_def scope.scope_defs } - in - Uid.ScopeMap.add scope_uid scope_updated prgm - -(** Process a rule from the surface language *) -let process_rule (precond : Lambda_ast.term option) (scope : Uid.Scope.t) - (ctxt : Name_resolution.context) (prgm : Scope_ast.program) (rule : Catala_ast.rule) : - Scope_ast.program = - let consequence_expr = Catala_ast.Literal (Catala_ast.Bool (Pos.unmark rule.rule_consequence)) in - let def = - { - definition_name = rule.rule_name; - definition_parameter = rule.rule_parameter; - definition_condition = rule.rule_condition; - definition_expr = (consequence_expr, Pos.get_position rule.rule_consequence); - } - in - process_def precond scope ctxt prgm def - -let process_scope_use_item (cond : Lambda_ast.term option) (scope : Uid.Scope.t) - (ctxt : Name_resolution.context) (prgm : Scope_ast.program) - (item : Catala_ast.scope_use_item Pos.marked) : Scope_ast.program = - match Pos.unmark item with - | Catala_ast.Rule rule -> process_rule cond scope ctxt prgm rule - | Catala_ast.Definition def -> process_def cond scope ctxt prgm def - | _ -> prgm - -let process_scope_use (ctxt : Name_resolution.context) (prgm : Scope_ast.program) - (use : Catala_ast.scope_use) : Scope_ast.program = - let name = fst use.scope_use_name in - let scope_uid = Uid.IdentMap.find name ctxt.scope_idmap in - (* Make sure the scope exists *) - let prgm = - match Uid.ScopeMap.find_opt scope_uid prgm with - | Some _ -> prgm - | None -> Uid.ScopeMap.add scope_uid (Scope_ast.empty_scope scope_uid) prgm - in - let cond = - match use.scope_use_condition with - | Some expr -> - let untyped_term = expr_to_lambda scope_uid None ctxt expr in - Some untyped_term - | None -> None - in - List.fold_left (process_scope_use_item cond scope_uid ctxt) prgm use.scope_use_items - -(** Scopes processing *) -let translate_program_to_scope (ctxt : Name_resolution.context) (prgm : Catala_ast.program) : - Scope_ast.program = - let empty_prgm = Uid.ScopeMap.empty in - let processer_article_item (prgm : Scope_ast.program) (item : Catala_ast.law_article_item) : - Scope_ast.program = - match item with - | CodeBlock (block, _) -> - List.fold_left - (fun prgm item -> - match Pos.unmark item with ScopeUse use -> process_scope_use ctxt prgm use | _ -> prgm) - prgm block - | _ -> prgm - in - let rec processer_structure (prgm : Scope_ast.program) (item : Catala_ast.law_structure) : - Scope_ast.program = - match item with - | LawHeading (_, children) -> - List.fold_left (fun prgm child -> processer_structure prgm child) prgm children - | LawArticle (_, children) -> - List.fold_left (fun prgm child -> processer_article_item prgm child) prgm children - | MetadataBlock (b, c) -> processer_article_item prgm (CodeBlock (b, c)) - | IntermediateText _ -> prgm - in - - let processer_item (prgm : Scope_ast.program) (item : Catala_ast.program_item) : Scope_ast.program - = - match item with LawStructure s -> processer_structure prgm s - in - - List.fold_left processer_item empty_prgm prgm.program_items diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index 06fb8365..24fe0376 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -1,3 +1,10 @@ +(library + (name surface) + (libraries utils menhirLib sedlex re) + (public_name catala.surface) + (preprocess + (pps sedlex.ppx))) + (menhir (modules parser) (flags --table)) diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 992574f5..b899b3d2 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -14,6 +14,8 @@ open Parser open Sedlexing +module Pos = Utils.Pos +module Errors = Utils.Errors module R = Re.Pcre let is_code : bool ref = ref false @@ -384,8 +386,8 @@ let rec lex_law (lexbuf : lexbuf) : token = let name = get_component 1 in let pages = try Some (int_of_string (get_component 3)) with Not_found -> None in let pos = lexing_positions lexbuf in - if Filename.extension name = ".pdf" then LAW_INCLUDE (Catala_ast.PdfFile ((name, pos), pages)) - else LAW_INCLUDE (Catala_ast.CatalaFile (name, pos)) + if Filename.extension name = ".pdf" then LAW_INCLUDE (Ast.PdfFile ((name, pos), pages)) + else LAW_INCLUDE (Ast.CatalaFile (name, pos)) | "@@", Plus (Compl '@'), "@@", Star '+' -> let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 6f2c8d9e..fdd6a2bc 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -14,6 +14,8 @@ open Parser open Sedlexing +module Pos = Utils.Pos +module Errors = Utils.Errors module L = Lexer module R = Re.Pcre @@ -356,8 +358,8 @@ let rec lex_law_en (lexbuf : lexbuf) : token = let name = get_component 1 in let pages = try Some (int_of_string (get_component 3)) with Not_found -> None in let pos = lexing_positions lexbuf in - if Filename.extension name = ".pdf" then LAW_INCLUDE (Catala_ast.PdfFile ((name, pos), pages)) - else LAW_INCLUDE (Catala_ast.CatalaFile (name, pos)) + if Filename.extension name = ".pdf" then LAW_INCLUDE (Ast.PdfFile ((name, pos), pages)) + else LAW_INCLUDE (Ast.CatalaFile (name, pos)) | "@@", Plus (Compl '@'), "@@", Star '+' -> let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 3944df39..1b62c4da 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -14,6 +14,8 @@ open Parser open Sedlexing +module Pos = Utils.Pos +module Errors = Utils.Errors module L = Lexer module R = Re.Pcre @@ -371,10 +373,9 @@ let rec lex_law_fr (lexbuf : lexbuf) : token = let name = get_component 1 in let pages = try Some (int_of_string (get_component 3)) with Not_found -> None in let pos = lexing_positions lexbuf in - if R.pmatch ~rex:jorftext name then LAW_INCLUDE (Catala_ast.LegislativeText (name, pos)) - else if Filename.extension name = ".pdf" then - LAW_INCLUDE (Catala_ast.PdfFile ((name, pos), pages)) - else LAW_INCLUDE (Catala_ast.CatalaFile (name, pos)) + if R.pmatch ~rex:jorftext name then LAW_INCLUDE (Ast.LegislativeText (name, pos)) + else if Filename.extension name = ".pdf" then LAW_INCLUDE (Ast.PdfFile ((name, pos), pages)) + else LAW_INCLUDE (Ast.CatalaFile (name, pos)) | "@@", Plus (Compl '@'), "@@", Star '+' -> let extract_code_title = R.regexp "@@([^@]+)@@([\\+]*)" in let get_match = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 5c8bd226..45207d3b 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -17,7 +17,9 @@ *) %{ - open Catala_ast + open Ast + + module Errors = Utils.Errors type struct_or_enum_inject_content = | StructContent of (ident Pos.marked * expression Pos.marked) list @@ -28,7 +30,7 @@ %token EOF %token LAW_ARTICLE %token LAW_HEADING -%token LAW_INCLUDE +%token LAW_INCLUDE %token LAW_TEXT %token CONSTRUCTOR IDENT %token END_CODE @@ -53,7 +55,7 @@ %token BEGIN_METADATA END_METADATA MONEY DECIMAL %token UNDER_CONDITION CONSEQUENCE -%type source_file_or_master +%type source_file_or_master %start source_file_or_master diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index 31064e33..5f66f610 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -13,6 +13,9 @@ the License. *) open Sedlexing +module Pos = Utils.Pos +module Errors = Utils.Errors +module Cli = Utils.Cli module I = Parser.MenhirInterpreter let state (env : 'semantic_value I.env) : int = @@ -125,7 +128,7 @@ let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * let rec loop (next_token : unit -> Parser.token * Lexing.position * Lexing.position) (token_list : (string * Parser.token) list) (lexbuf : lexbuf) (last_input_needed : 'semantic_value I.env option) (checkpoint : 'semantic_value I.checkpoint) : - Catala_ast.source_file_or_master = + Ast.source_file_or_master = match checkpoint with | I.InputNeeded env -> let token = next_token () in @@ -142,7 +145,7 @@ let rec loop (next_token : unit -> Parser.token * Lexing.position * Lexing.posit let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * Parser.token) list) (target_rule : Lexing.position -> 'semantic_value I.checkpoint) (lexbuf : lexbuf) : - Catala_ast.source_file_or_master = + Ast.source_file_or_master = let lexer : unit -> Parser.token * Lexing.position * Lexing.position = with_tokenizer lexer' lexbuf in @@ -150,8 +153,8 @@ let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * with Sedlexing.MalFormed | Sedlexing.InvalidCodepoint _ -> Lexer.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "malformed token" -let rec parse_source_files (source_files : string list) (language : Cli.frontend_lang) : - Catala_ast.program = +let rec parse_source_files (source_files : string list) (language : Cli.frontend_lang) : Ast.program + = match source_files with | [] -> { program_items = []; program_source_files = [] } | source_file :: rest -> ( @@ -178,13 +181,13 @@ let rec parse_source_files (source_files : string list) (language : Cli.frontend in close_in input; match commands_or_includes with - | Catala_ast.SourceFile commands -> + | Ast.SourceFile commands -> let rest_program = parse_source_files rest language in { - program_items = commands @ rest_program.Catala_ast.program_items; - program_source_files = source_file :: rest_program.Catala_ast.program_source_files; + program_items = commands @ rest_program.Ast.program_items; + program_source_files = source_file :: rest_program.Ast.program_source_files; } - | Catala_ast.MasterFile includes -> + | Ast.MasterFile includes -> let current_source_file_dirname = Filename.dirname source_file in let includes = List.map diff --git a/src/catala/revamping/dcalculus_ast.ml b/src/catala/default_calculus/ast.ml similarity index 98% rename from src/catala/revamping/dcalculus_ast.ml rename to src/catala/default_calculus/ast.ml index be499f5f..fbed878c 100644 --- a/src/catala/revamping/dcalculus_ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -12,6 +12,8 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Pos = Utils.Pos + type typ = TBool | TUnit | TArrow of typ Pos.marked * typ Pos.marked type lit = LTrue | LFalse | LEmptyError | LConflictError diff --git a/src/catala/default_calculus/dune b/src/catala/default_calculus/dune new file mode 100644 index 00000000..feeb8fd6 --- /dev/null +++ b/src/catala/default_calculus/dune @@ -0,0 +1,4 @@ +(library + (name dcalc) + (public_name catala.dcalc) + (libraries bindlib unionFind utils)) diff --git a/src/catala/revamping/dcalculus_typing.ml b/src/catala/default_calculus/typing.ml similarity index 98% rename from src/catala/revamping/dcalculus_typing.ml rename to src/catala/default_calculus/typing.ml index c2fe9fb7..bca77818 100644 --- a/src/catala/revamping/dcalculus_typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -15,7 +15,9 @@ (** Typing for the default calculus. Because of the error terms, we perform type inference using the classical W algorithm with union-find unification. *) -module A = Dcalculus_ast +module Pos = Utils.Pos +module Errors = Utils.Errors +module A = Ast type typ = | TUnit diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 66615ef3..f64dc47d 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -12,6 +12,9 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Cli = Utils.Cli +module Errors = Utils.Errors + (** Entry function for the executable. Returns a negative number in case of error. *) let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_output : bool) (pygmentize_loc : string option) (backend : string) (language : string option) @@ -40,7 +43,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ Errors.raise_error (Printf.sprintf "The selected backend (%s) is not supported by Catala" backend) in - let program = Parser_driver.parse_source_files [ source_file ] language in + let program = Surface.Parser_driver.parse_source_files [ source_file ] language in match backend with | Cli.Makefile -> let backend_extensions_list = [ ".tex" ] in @@ -74,8 +77,8 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ let oc = open_out output_file in let weave_output = match backend with - | Cli.Latex -> Latex.ast_to_latex language - | Cli.Html -> Html.ast_to_html pygmentize_loc language + | Cli.Latex -> Literate.Latex.ast_to_latex language + | Cli.Html -> Literate.Html.ast_to_html pygmentize_loc language | _ -> assert false in Cli.debug_print (Printf.sprintf "Writing to %s" output_file); @@ -83,47 +86,43 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ if wrap_weaved_output then match backend with | Cli.Latex -> - Latex.wrap_latex program.Catala_ast.program_source_files pygmentize_loc language fmt - (fun fmt -> weave_output fmt program) + Literate.Latex.wrap_latex program.Surface.Ast.program_source_files pygmentize_loc + language fmt (fun fmt -> weave_output fmt program) | Cli.Html -> - Html.wrap_html program.Catala_ast.program_source_files pygmentize_loc language fmt - (fun fmt -> weave_output fmt program) + Literate.Html.wrap_html program.Surface.Ast.program_source_files pygmentize_loc + language fmt (fun fmt -> weave_output fmt program) | _ -> assert false else weave_output fmt program; close_out oc; 0 | Cli.Run -> - let ctxt = Name_resolution.form_context program in + let ctxt = Scope.Name_resolution.form_context program in let scope_uid = match ex_scope with | None -> Errors.raise_error "No scope was provided for execution." | Some name -> ( - match Uid.IdentMap.find_opt name ctxt.scope_idmap with + match Scope.Uid.IdentMap.find_opt name ctxt.scope_idmap with | None -> Errors.raise_error (Printf.sprintf "There is no scope %s inside the program." name) | Some uid -> uid ) in - let prgm = Desugaring.translate_program_to_scope ctxt program in - let scope = - match Uid.ScopeMap.find_opt scope_uid prgm with + let prgm = Scope.Desugaring.translate_program_to_scope ctxt program in + let _scope = + match Scope.Uid.ScopeMap.find_opt scope_uid prgm with | Some scope -> scope | None -> - let scope_info = Uid.Scope.get_info scope_uid in + let scope_info = Scope.Uid.Scope.get_info scope_uid in Errors.raise_spanned_error (Printf.sprintf "Scope %s does not define anything, and therefore cannot be executed" - (Pos.unmark scope_info)) - (Pos.get_position scope_info) + (Utils.Pos.unmark scope_info)) + (Utils.Pos.get_position scope_info) in - let exec_ctxt = Scope_interpreter.execute_scope ctxt prgm scope in - Lambda_interpreter.ExecContext.iter - (fun context_key value -> - Cli.result_print - (Printf.sprintf "%s -> %s" - (Lambda_interpreter.ExecContextKey.format_t context_key) - (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) - exec_ctxt; + (* let exec_ctxt = Scope.Interpreter.execute_scope ctxt prgm scope in + Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print + (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) + (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) 0 with Errors.StructuredError (msg, pos) -> Cli.error_print (Errors.print_structured_error msg pos); diff --git a/src/catala/dune b/src/catala/dune index d8d5117e..1bb61551 100644 --- a/src/catala/dune +++ b/src/catala/dune @@ -1,11 +1,7 @@ -(include_subdirs unqualified) - (library (public_name catala) - (libraries ANSITerminal sedlex menhirLib re cmdliner dune-build-info - ocamlgraph bindlib unionFind) - (preprocess - (pps sedlex.ppx))) + (libraries catala.utils catala.surface catala.scope catala.literate + catala.dcalc)) (documentation (package catala)) diff --git a/src/catala/lambda_calculus/format_lambda.ml b/src/catala/lambda_calculus/format_lambda.ml deleted file mode 100644 index 8616a08e..00000000 --- a/src/catala/lambda_calculus/format_lambda.ml +++ /dev/null @@ -1,84 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - - - 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. *) - -module IdentMap = Map.Make (String) - -(* Printing functions for Lambda_ast.term *) - -let rec format_typ (ty : Lambda_ast.typ) : string = - match ty with - | TBool -> "bool" - | TInt -> "int" - | TArrow (t1, t2) -> Format.sprintf "(%s) -> (%s)" (format_typ t1) (format_typ t2) - | TDummy -> "??" - -(** Operator printer *) -let print_op (op : Lambda_ast.op) : string = - match op with - | Binop binop -> ( - match binop with - | And -> "and" - | Or -> "or" - | Add -> "+" - | Sub -> "-" - | Mult -> "*" - | Div -> "/" - | Lt -> "<" - | Lte -> "<=" - | Gt -> ">" - | Gte -> ">=" - | Eq -> "=" - | Neq -> "!=" ) - | Unop Not -> "not" - | Unop Minus -> "-" - -let rec repeat_string n s = if n = 0 then "" else s ^ repeat_string (n - 1) s - -let print_prefix (prefix : Lambda_ast.var_prefix) : string = - match prefix with - | NoPrefix -> "" - | SubScopePrefix s -> Uid.SubScope.format_t s ^ "." - | CallerPrefix (i, s) -> ( - repeat_string i "CALLER." - ^ match s with None -> "" | Some s -> Uid.SubScope.format_t s ^ "." ) - -(** Print Lambda_ast.term *) -let rec print_term (((t, _), _) : Lambda_ast.term) : string = - match t with - | EVar (s, uid) -> Printf.sprintf "%s%s" (print_prefix s) (Uid.Var.format_t uid) - | ELocalVar uid -> Uid.LocalVar.format_t uid - | EFun (binders, body) -> - let sbody = print_term body in - Printf.sprintf "fun %s -> %s" - (binders |> List.map (fun (uid, _) -> Uid.LocalVar.format_t uid) |> String.concat " ") - sbody - | EApp (f, args) -> - Printf.sprintf "(%s) [%s]" (print_term f) (args |> List.map print_term |> String.concat ";") - | EIfThenElse (tif, tthen, telse) -> - Printf.sprintf "IF %s THEN %s ELSE %s" (print_term tif) (print_term tthen) (print_term telse) - | EInt i -> Printf.sprintf "%d" i - | EBool b -> if b then "true" else "false" - | EDec (i, f) -> Printf.sprintf "%d.%d" i f - | EOp op -> print_op op - | EDefault t -> print_default_term t - -and print_default_term (term : Lambda_ast.default_term) : string = - ( term.defaults - |> List.mapi (fun i (cond, body) -> - Printf.sprintf "[%d]\t%s => %s" i (print_term cond) (print_term body)) - |> String.concat "\n" ) - ^ "\n" - ^ ( term.ordering - |> List.map (fun (hi, lo) -> Printf.sprintf "%d > %d" hi lo) - |> String.concat ", " ) diff --git a/src/catala/lambda_calculus/lambda_ast.ml b/src/catala/lambda_calculus/lambda_ast.ml deleted file mode 100644 index fe8263e4..00000000 --- a/src/catala/lambda_calculus/lambda_ast.ml +++ /dev/null @@ -1,120 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - - - 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. *) - -(* TDummy means the term is not typed *) -type typ = TBool | TInt | TArrow of typ * typ | TDummy - -type literal = Catala_ast.literal - -type binop = Catala_ast.binop - -type unop = Catala_ast.unop - -type op = Binop of binop | Unop of unop - -type binding = Uid.LocalVar.t * typ - -type var_prefix = - (* See [Scope_interpreter] for details about the meaning of this case. The `int` means the number - of times you have to go to the parent caller to get the variable *) - | CallerPrefix of int * Uid.SubScope.t option - | NoPrefix - | SubScopePrefix of Uid.SubScope.t - -type term = untyped_term Pos.marked * typ - -and untyped_term = - | EVar of var_prefix * Uid.Var.t - (** This case is only for terms embedded in the scope language *) - | ELocalVar of Uid.LocalVar.t - | EFun of binding list * term - | EApp of term * term list - | EIfThenElse of term * term * term - | EInt of int - | EBool of bool - | EDec of int * int - | EOp of op - | EDefault of default_term - -(* (x,y) in ordering means that default x has precedence over default y : if both are true then x - would be choser over y *) -and default_term = { defaults : (term * term) list; ordering : (int * int) list } - -let untype (((term, _), _) : term) : untyped_term = term - -let get_pos (((_, pos), _) : term) : Pos.t = pos - -let get_typ ((_, typ) : term) : typ = typ - -let map_untype (f : untyped_term -> untyped_term) (((term, pos), typ) : term) : term = - ((f term, pos), typ) - -let map_untype2 (f : untyped_term -> untyped_term -> untyped_term) (((t1, pos), typ) : term) - (((t2, _), _) : term) : term = - ((f t1 t2, pos), typ) - -let empty_default_term : default_term = { defaults = []; ordering = [] } - -let add_default (just : term) (cons : term) (term : default_term) = - { term with defaults = term.defaults @ [ (just, cons) ] } - -(** Merge two defalts terms, taking into account that one has higher precedence than the other *) -let merge_default_terms (lo_term : default_term) (hi_term : default_term) : default_term = - let n = List.length lo_term.defaults in - let n' = List.length hi_term.defaults in - let defaults = lo_term.defaults @ hi_term.defaults in - let rec add_hi_prec = function - | [] -> lo_term.ordering - | (k, k') :: xs -> (n + k, n + k') :: add_hi_prec xs - in - let prec = add_hi_prec hi_term.ordering in - let gen_prec lo hi = - List.fold_left - (fun acc x_lo -> - let sub_list = List.fold_left (fun acc' x_hi -> (x_hi, x_lo) :: acc') [] hi in - sub_list :: acc) - [] lo - |> List.flatten - in - let rec gen_list i j acc = if i = j then acc else gen_list (i + 1) j (i :: acc) in - let gen_list i j = gen_list i j [] in - let prec' = gen_prec (gen_list 0 n) (gen_list n (n + n')) in - { defaults; ordering = prec @ prec' } - -(** Returns the free variables (scope language variables) of a term. Used to build the dependency - graph *) -let rec term_fv (term : term) : Uid.ScopeDefSet.t = - match untype term with - | EVar (NoPrefix, uid) -> Uid.ScopeDefSet.singleton (Uid.ScopeDef.Var uid) - | EVar (SubScopePrefix sub_uid, uid) -> - Uid.ScopeDefSet.singleton (Uid.ScopeDef.SubScopeVar (sub_uid, uid)) - | EVar (CallerPrefix _, _) -> - Uid.ScopeDefSet.empty - (* here we return an empty dependency because when calling a subscope, the variables of the - caller graph needed for it are already computed *) - | ELocalVar _ -> Uid.ScopeDefSet.empty - | EFun (_, body) -> term_fv body - | EApp (f, args) -> - List.fold_left (fun fv arg -> Uid.ScopeDefSet.union fv (term_fv arg)) (term_fv f) args - | EIfThenElse (t_if, t_then, t_else) -> - Uid.ScopeDefSet.union (term_fv t_if) (Uid.ScopeDefSet.union (term_fv t_then) (term_fv t_else)) - | EDefault default -> default_term_fv default - | EBool _ | EInt _ | EDec _ | EOp _ -> Uid.ScopeDefSet.empty - -and default_term_fv (term : default_term) : Uid.ScopeDefSet.t = - List.fold_left - (fun acc (cond, body) -> - let fv = Uid.ScopeDefSet.union (term_fv cond) (term_fv body) in - Uid.ScopeDefSet.union fv acc) - Uid.ScopeDefSet.empty term.defaults diff --git a/src/catala/lambda_calculus/lambda_interpreter.ml b/src/catala/lambda_calculus/lambda_interpreter.ml deleted file mode 100644 index abdd7e06..00000000 --- a/src/catala/lambda_calculus/lambda_interpreter.ml +++ /dev/null @@ -1,218 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - - - 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 Lambda_ast - -type uid = int - -type scope_uid = int - -module ExecContextKey = struct - type t = LocalVar of Uid.LocalVar.t | ScopeVar of var_prefix * Uid.Var.t - - let compare x y = - match (x, y) with - | LocalVar x, LocalVar y -> Uid.LocalVar.compare x y - | ScopeVar (x1, x2), ScopeVar (y1, y2) -> ( - match (x1, y1) with - | NoPrefix, NoPrefix | CallerPrefix _, CallerPrefix _ -> Uid.Var.compare x2 y2 - | SubScopePrefix x1, SubScopePrefix y1 -> - let sub_comp = Uid.SubScope.compare x1 y1 in - if sub_comp = 0 then Uid.Var.compare x2 y2 else sub_comp - | _ -> compare x y ) - | _ -> compare x y - - let format_t (x : t) : string = - match x with - | LocalVar x -> Uid.LocalVar.format_t x - | ScopeVar (prefix, var) -> Format_lambda.print_prefix prefix ^ Uid.Var.format_t var -end - -module ExecContext = Map.Make (ExecContextKey) - -type exec_context = Lambda_ast.untyped_term ExecContext.t - -let format_exec_context (ctx : exec_context) = - String.concat "\n" - (List.map - (fun (key, value) -> - Printf.sprintf "%s -> %s" (ExecContextKey.format_t key) - (Format_lambda.print_term ((value, Pos.no_pos), TDummy))) - (ExecContext.bindings ctx)) - -let empty_exec_ctxt = ExecContext.empty - -let raise_default_conflict (def : Uid.ScopeDef.t) (true_pos : Pos.t list) (false_pos : Pos.t list) = - let var_str = Uid.ScopeDef.format_t def in - let var_pos = - match def with - | Uid.ScopeDef.SubScopeVar (_, v) | Uid.ScopeDef.Var v -> Pos.get_position (Uid.Var.get_info v) - in - - if List.length true_pos = 0 then - let justifications : (string option * Pos.t) list = - List.map (fun pos -> (Some "This justification is false:", pos)) false_pos - in - Errors.raise_multispanned_error - (Printf.sprintf "Default logic error for variable %s: no justification is true." var_str) - ( (Some (Printf.sprintf "The error concerns this variable %s" var_str), var_pos) - :: justifications ) - else - let justifications : (string option * Pos.t) list = - List.map (fun pos -> (Some "This justification is true:", pos)) true_pos - in - Errors.raise_multispanned_error - "Default logic conflict, multiple justifications are true but are not related by a precedence" - ( (Some (Printf.sprintf "The conflict concerns this variable %s" var_str), var_pos) - :: justifications ) - -let rec eval_term (top_uid : Uid.ScopeDef.t) (exec_ctxt : exec_context) (term : Lambda_ast.term) : - Lambda_ast.term = - let (term, pos), typ = term in - let evaled_term = - match term with - | EFun _ | EInt _ | EDec _ | EBool _ | EOp _ -> term (* already a value *) - | ELocalVar uid -> ( - let ctxt_key = ExecContextKey.LocalVar uid in - match ExecContext.find_opt ctxt_key exec_ctxt with - | Some t -> t - | None -> - Errors.raise_spanned_error - (Printf.sprintf "Local Variable %s is not defined" (Uid.LocalVar.format_t uid)) - pos ) - | EVar (prefix, uid) -> ( - let ctxt_key = ExecContextKey.ScopeVar (prefix, uid) in - match ExecContext.find_opt ctxt_key exec_ctxt with - | Some t -> t - | None -> - Errors.raise_spanned_error - (Printf.sprintf "Variable %s is not defined" (Uid.Var.format_t uid)) - pos ) - | EApp (f, args) -> ( - (* First evaluate and match the function body *) - let f = f |> eval_term top_uid exec_ctxt |> Lambda_ast.untype in - match f with - | EFun (bindings, body) -> - let exec_ctxt = - List.fold_left2 - (fun ctxt arg (uid, _) -> - ExecContext.add (ExecContextKey.LocalVar uid) - (arg |> eval_term top_uid exec_ctxt |> Lambda_ast.untype) - ctxt) - exec_ctxt args bindings - in - eval_term top_uid exec_ctxt body |> Lambda_ast.untype - | EOp op -> ( - let args = - List.map (fun arg -> arg |> eval_term top_uid exec_ctxt |> Lambda_ast.untype) args - in - match op with - | Binop binop -> ( - match binop with - | And | Or -> - let b1, b2 = - match args with [ EBool b1; EBool b2 ] -> (b1, b2) | _ -> assert false - (* should not happen *) - in - EBool (if binop = And then b1 && b2 else b1 || b2) - | _ -> ( - let i1, i2 = - match args with [ EInt i1; EInt i2 ] -> (i1, i2) | _ -> assert false - (* should not happen *) - in - match binop with - | Add | Sub | Mult | Div -> - let op_arith = - match binop with - | Add -> ( + ) - | Sub -> ( - ) - | Mult -> ( * ) - | Div -> ( / ) - | _ -> assert false - (* should not happen *) - in - EInt (op_arith i1 i2) - | _ -> - let op_comp = - match binop with - | Lt -> ( < ) - | Lte -> ( <= ) - | Gt -> ( > ) - | Gte -> ( >= ) - | Eq -> ( = ) - | Neq -> ( <> ) - | _ -> assert false - (* should not happen *) - in - EBool (op_comp i1 i2) ) ) - | Unop Minus -> ( - match args with - | [ EInt i ] -> EInt (-i) - | _ -> assert false (* should not happen *) ) - | Unop Not -> ( - match args with - | [ EBool b ] -> EBool (not b) - | _ -> assert false (* should not happen *) ) ) - | _ -> assert false ) - | EIfThenElse (t_if, t_then, t_else) -> - ( match eval_term top_uid exec_ctxt t_if |> Lambda_ast.untype with - | EBool b -> - if b then eval_term top_uid exec_ctxt t_then else eval_term top_uid exec_ctxt t_else - | _ -> assert false (* should not happen *) ) - |> Lambda_ast.untype - | EDefault t -> ( - match eval_default_term top_uid exec_ctxt t with - | Ok value -> value |> Lambda_ast.untype - | Error (true_pos, false_pos) -> raise_default_conflict top_uid true_pos false_pos ) - in - ((evaled_term, pos), typ) - -(* Evaluates a default term : see the formalization for an insight about this operation *) -and eval_default_term (top_uid : Uid.ScopeDef.t) (exec_ctxt : exec_context) - (term : Lambda_ast.default_term) : (Lambda_ast.term, Pos.t list * Pos.t list) result = - (* First filter out the term which justification are false *) - let defaults_numbered : (int * (term * term)) list = - List.mapi (fun (x : int) (y : term * term) -> (x, y)) term.defaults - in - let candidates : 'a list = - List.filter - (fun (_, (cond, _)) -> - match eval_term top_uid exec_ctxt cond |> Lambda_ast.untype with - | EBool b -> b - | _ -> assert false - (* should not happen *)) - defaults_numbered - in - (* Now filter out the terms that have a predecessor which justification is true *) - let module ISet = Set.Make (Int) in - let key_candidates = List.fold_left (fun acc (x, _) -> ISet.add x acc) ISet.empty candidates in - let chosen_one = - List.fold_left - (fun set (lo, hi) -> if ISet.mem lo set && ISet.mem hi set then ISet.remove hi set else set) - key_candidates term.ordering - in - match ISet.elements chosen_one with - | [ x ] -> - let _, (_, cons) = List.find (fun (i, _) -> i = x) defaults_numbered in - Ok (eval_term top_uid exec_ctxt cons) - | xs -> - let true_pos = - xs - |> List.map (fun x -> - List.find (fun (i, _) -> i = x) defaults_numbered |> snd |> fst |> Lambda_ast.get_pos) - in - let false_pos : Pos.t list = - List.map (fun (_, (cond, _)) -> Lambda_ast.get_pos cond) defaults_numbered - in - Error (true_pos, false_pos) diff --git a/src/catala/lambda_calculus/lambda_typechecker.ml b/src/catala/lambda_calculus/lambda_typechecker.ml deleted file mode 100644 index 4f7885f0..00000000 --- a/src/catala/lambda_calculus/lambda_typechecker.ml +++ /dev/null @@ -1,138 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - - - 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. *) - -(** Checks that a term is well typed and annotate it *) -let rec type_term (ctxt : Name_resolution.context) (local_ctx : Lambda_ast.typ Uid.LocalVarMap.t) - (((t, pos), _) : Lambda_ast.term) : Lambda_ast.term = - match t with - | EVar (s, uid) -> - (* so here we can ignore the subscope uid because the uid of the variable already corresponds - to the uid of the variable in its original scope *) - let typ = Name_resolution.get_var_typ ctxt uid in - ((EVar (s, uid), pos), typ) - | ELocalVar uid -> - let typ = Uid.LocalVarMap.find uid local_ctx in - ((ELocalVar uid, pos), typ) - | EFun (bindings, body) -> - let local_ctx = - List.fold_left - (fun local_ctx (binding, ty) -> Uid.LocalVarMap.add binding ty local_ctx) - local_ctx bindings - in - let body = type_term ctxt local_ctx body in - let ret_typ = Lambda_ast.get_typ body in - let rec build_typ = function - | [] -> ret_typ - | (_, arg_t) :: args -> TArrow (arg_t, build_typ args) - in - let fun_typ = build_typ bindings in - ((EFun (bindings, body), pos), fun_typ) - | EApp (f, args) -> - let f = type_term ctxt local_ctx f in - let f_typ = Lambda_ast.get_typ f in - let args = List.map (type_term ctxt local_ctx) args in - let args_typ = - List.map (fun arg -> (Lambda_ast.get_typ arg, Pos.get_position (fst arg))) args - in - let rec check_arrow_typ f_typ args_typ = - match (f_typ, args_typ) with - | typ, [] -> typ - | Lambda_ast.TArrow (arg_typ, ret_typ), fst_typ :: typs -> - let fst_typ_s = Pos.unmark fst_typ in - if arg_typ = fst_typ_s then check_arrow_typ ret_typ typs - else - Errors.raise_multispanned_error "error when comparing types of function arguments" - [ - ( Some (Printf.sprintf "expected type %s" (Format_lambda.format_typ f_typ)), - Pos.get_position (fst f) ); - ( Some (Printf.sprintf "got type %s" (Format_lambda.format_typ fst_typ_s)), - Pos.get_position fst_typ ); - ] - | _ -> - Errors.raise_multispanned_error "wrong number of arguments for function call" - [ - ( Some (Printf.sprintf "expected type %s" (Format_lambda.format_typ f_typ)), - Pos.get_position (fst f) ); - ( Some - (Printf.sprintf "got type %s" - (String.concat " -> " - (List.map (fun (ty, _) -> Format_lambda.format_typ ty) args_typ))), - Pos.get_position (List.hd args_typ) ); - ] - in - let ret_typ = check_arrow_typ f_typ args_typ in - ((EApp (f, args), pos), ret_typ) - | EIfThenElse (t_if, t_then, t_else) -> - let t_if = type_term ctxt local_ctx t_if in - let typ_if = Lambda_ast.get_typ t_if in - let t_then = type_term ctxt local_ctx t_then in - let typ_then = Lambda_ast.get_typ t_then in - let t_else = type_term ctxt local_ctx t_else in - let typ_else = Lambda_ast.get_typ t_else in - if typ_if <> TBool then - Errors.raise_spanned_error - (Format.sprintf "expecting type bool, got type %s" (Format_lambda.format_typ typ_if)) - (Pos.get_position (fst t_if)) - else if typ_then <> typ_else then - Errors.raise_multispanned_error - "expecting same types for the true and false branches of the conditional" - [ - ( Some (Format.sprintf "the true branch has type %s" (Format_lambda.format_typ typ_then)), - Pos.get_position (fst t_then) ); - ( Some - (Format.sprintf "the false branch has type %s" (Format_lambda.format_typ typ_else)), - Pos.get_position (fst t_else) ); - ] - else ((EIfThenElse (t_if, t_then, t_else), pos), typ_then) - | EInt _ | EDec _ -> ((t, pos), TInt) - | EBool _ -> ((t, pos), TBool) - | EOp op -> - let typ = - match op with - | Binop binop -> ( - match binop with - | And | Or -> Lambda_ast.TArrow (TBool, TArrow (TBool, TBool)) - | Add | Sub | Mult | Div -> TArrow (TInt, TArrow (TInt, TInt)) - | Lt | Lte | Gt | Gte | Eq | Neq -> TArrow (TInt, TArrow (TInt, TBool)) ) - | Unop Minus -> TArrow (TInt, TInt) - | Unop Not -> TArrow (TBool, TBool) - in - ((t, pos), typ) - | EDefault t -> - let defaults = - List.map - (fun (just, cons) -> - let just_t = type_term ctxt local_ctx just in - if Lambda_ast.get_typ just_t <> TBool then - let cons = type_term ctxt local_ctx cons in - (just_t, cons) - else - Errors.raise_spanned_error - (Format.sprintf "expected type of default condition to be bool, got %s" - (Format_lambda.format_typ (Lambda_ast.get_typ just))) - (Pos.get_position (fst just))) - t.defaults - in - let typ_cons = List.hd defaults |> snd |> snd in - List.iter - (fun (_, cons) -> - if Lambda_ast.get_typ cons <> typ_cons then - Errors.raise_spanned_error - (Format.sprintf "expected default condition to be of type %s, got type %s" - (Format_lambda.format_typ (Lambda_ast.get_typ cons)) - (Format_lambda.format_typ typ_cons)) - (Pos.get_position (fst cons)) - else ()) - defaults; - ((EDefault { t with defaults }, pos), typ_cons) diff --git a/src/catala/literate_programming/dune b/src/catala/literate_programming/dune new file mode 100644 index 00000000..8925f858 --- /dev/null +++ b/src/catala/literate_programming/dune @@ -0,0 +1,4 @@ +(library + (name literate) + (public_name catala.literate) + (libraries re utils surface)) diff --git a/src/catala/literate_programming/html.ml b/src/catala/literate_programming/html.ml index 8760ce80..8496df3e 100644 --- a/src/catala/literate_programming/html.ml +++ b/src/catala/literate_programming/html.ml @@ -15,7 +15,10 @@ (** This modules weaves the source code and the legislative text together into a document that law professionals can understand. *) -module A = Catala_ast +module Pos = Utils.Pos +module Cli = Utils.Cli +module Errors = Utils.Errors +module A = Surface.Ast module P = Printf module R = Re.Pcre module C = Cli diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index 750adbf6..aa47fe51 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -15,7 +15,10 @@ (** This modules weaves the source code and the legislative text together into a document that law professionals can understand. *) -module A = Catala_ast +module Pos = Utils.Pos +module Cli = Utils.Cli +module Errors = Utils.Errors +module A = Surface.Ast module R = Re.Pcre module C = Cli diff --git a/src/catala/scope_language/scope_ast.ml b/src/catala/scope_language/ast.ml similarity index 83% rename from src/catala/scope_language/scope_ast.ml rename to src/catala/scope_language/ast.ml index 7b596101..050507bf 100644 --- a/src/catala/scope_language/scope_ast.ml +++ b/src/catala/scope_language/ast.ml @@ -12,15 +12,16 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Pos = Utils.Pos + (* Scopes *) type binder = Uid.LocalVar.t -type definition = Lambda_ast.term +type definition = unit -let empty_def (pos : Pos.t) (typ : Lambda_ast.typ) : definition = - ((EDefault Lambda_ast.empty_default_term, pos), typ) +let empty_def (_pos : Pos.t) (_typ : Dcalc.Ast.typ) : definition = assert false -type assertion = Lambda_ast.term +type assertion = unit type variation_typ = Increasing | Decreasing @@ -28,7 +29,7 @@ type reference_typ = Decree | Law type meta_assertion = | FixedBy of reference_typ Pos.marked - | VariesWith of Lambda_ast.term * variation_typ Pos.marked option + | VariesWith of unit * variation_typ Pos.marked option type scope = { scope_uid : Uid.Scope.t; diff --git a/src/catala/scope_language/desugaring.ml b/src/catala/scope_language/desugaring.ml new file mode 100644 index 00000000..c2d71b4a --- /dev/null +++ b/src/catala/scope_language/desugaring.ml @@ -0,0 +1,182 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing + Denis Merigoux + + 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. *) + +module Pos = Utils.Pos +module Errors = Utils.Errors + +(** The optional argument subdef allows to choose between differents uids in case the expression is + a redefinition of a subvariable *) + +(* let rec expr_to_lambda (scope : Uid.Scope.t) (def_key : Uid.ScopeDef.t option) (ctxt : + Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : 'a = let scope_ctxt + = Uid.ScopeMap.find scope ctxt.scopes in let rec_helper = expr_to_lambda scope def_key ctxt in + match expr with | IfThenElse (e_if, e_then, e_else) -> ((EIfThenElse (rec_helper e_if, rec_helper + e_then, rec_helper e_else), pos), TDummy) | Binop (op, e1, e2) -> let op_term = (Pos.same_pos_as + (EOp (Binop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ rec_helper e1; rec_helper e2 ]), + pos), TDummy) | Unop (op, e) -> let op_term = (Pos.same_pos_as (EOp (Unop (Pos.unmark op))) op, + TDummy) in ((EApp (op_term, [ rec_helper e ]), pos), TDummy) | Literal l -> let untyped_term = + match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec (i, f), _), _) -> EDec (i, f) | + Bool b -> EBool b | _ -> Name_resolution.raise_unsupported_feature "literal" pos in + ((untyped_term, pos), TDummy) | Ident x -> ( (* first we check whether this is a local var, then + we resort to scope-wide variables *) match def_key with | Some def_key -> ( let def_ctxt = + Uid.ScopeDefMap.find def_key scope_ctxt.definitions in match Uid.IdentMap.find_opt x + def_ctxt.var_idmap with | None -> ( match Uid.IdentMap.find_opt x scope_ctxt.var_idmap with | + Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> + Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" (x, pos) ) | Some + uid -> ((ELocalVar uid, pos), TDummy) ) | None -> ( match Uid.IdentMap.find_opt x + scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> + Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | Dotted (e, x) + -> ( (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) match + Pos.unmark e with | Ident y -> let subscope_uid : Uid.SubScope.t = + Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in let subscope_real_uid : + Uid.Scope.t = Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in let subscope_var_uid = + Name_resolution.get_var_uid subscope_real_uid ctxt x in ((EVar (SubScopePrefix subscope_uid, + subscope_var_uid), pos), TDummy) | _ -> Name_resolution.raise_unsupported_feature "left hand side + of a dotted expression should be an identifier" pos ) | FunCall (f, arg) -> ((EApp (rec_helper f, + [ rec_helper arg ]), pos), TDummy) | _ -> Name_resolution.raise_unsupported_feature "unsupported + expression" pos *) + +(* Translation from the parsed ast to the scope language *) + +(* let merge_conditions (precond : Dcalc.Ast.term option) (cond : Dcalc.Ast.term option) + (default_pos : Pos.t) : Dcalc.Ast.term = match (precond, cond) with | Some precond, Some cond -> + let op_term = ((EOp (Binop And), Pos.get_position (fst precond)), TDummy) in ((EApp (op_term, [ + precond; cond ]), Pos.get_position (fst precond)), TDummy) | Some cond, None | None, Some cond -> + cond | None, None -> ((EBool true, default_pos), TBool) + + let process_default (ctxt : Name_resolution.context) (scope : Uid.Scope.t) (def_key : + Uid.ScopeDef.t) (def : Dcalc.Ast.default_term) (param_uid : Uid.LocalVar.t option) (precond : + Dcalc.Ast.term option) (just : Surface.Ast.expression Pos.marked option) (body : + Surface.Ast.expression Pos.marked) : Dcalc.Ast.default_term = let just = match just with | Some + cond -> Some (expr_to_lambda scope (Some def_key) ctxt cond) | None -> None in let condition = + merge_conditions precond just (Pos.get_position body) in let body = expr_to_lambda scope (Some + def_key) ctxt body in (* if there's a parameter, we have to wrap the justifiction and the body in + a func *) let condition, body = match param_uid with | None -> (condition, body) | Some param_uid + -> ( ((EFun ([ (param_uid, TDummy) ], condition), Pos.get_position (fst condition)), TDummy), + ((EFun ([ (param_uid, TDummy) ], body), Pos.get_position (fst body)), TDummy) ) in + Dcalc.Ast.add_default condition body def *) + +(* Process a definition *) +let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Uid.Scope.t) + (ctxt : Name_resolution.context) (prgm : Ast.program) (def : Surface.Ast.definition) : + Ast.program = + let scope : Ast.scope = Uid.ScopeMap.find scope_uid prgm in + let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in + let default_pos = Pos.get_position def.definition_expr in + let _param_uid (def_uid : Uid.ScopeDef.t) : Uid.LocalVar.t option = + match def.definition_parameter with + | None -> None + | Some param -> + let def_ctxt = Uid.ScopeDefMap.find def_uid scope_ctxt.definitions in + Some (Uid.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) + in + let def_key = + match Pos.unmark def.definition_name with + | [ x ] -> + let x_uid = Name_resolution.get_var_uid scope_uid ctxt x in + Uid.ScopeDef.Var x_uid + | [ y; x ] -> + let subscope_uid : Uid.SubScope.t = Name_resolution.get_subscope_uid scope_uid ctxt y in + let subscope_real_uid : Uid.Scope.t = + Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes + in + let x_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in + Uid.ScopeDef.SubScopeVar (subscope_uid, x_uid) + | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos + in + let scope_updated = + let _x_def = + match Uid.ScopeDefMap.find_opt def_key scope.scope_defs with + | Some def -> def + | None -> + let _typ = Name_resolution.get_def_typ ctxt def_key in + Ast.empty_def default_pos (assert false (* typ *)) + in + let x_def = + assert false + (* Dcalc.Ast.map_untype (fun t -> match t with | EDefault default -> EDefault (process_default + ctxt scope_uid def_key default (param_uid def_key) precond def.definition_condition + def.definition_expr) | _ -> assert false (* should not happen *)) x_def *) + in + { scope with scope_defs = Uid.ScopeDefMap.add def_key x_def scope.scope_defs } + in + Uid.ScopeMap.add scope_uid scope_updated prgm + +(** Process a rule from the surface language *) +let process_rule (precond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) + (ctxt : Name_resolution.context) (prgm : Ast.program) (rule : Surface.Ast.rule) : Ast.program = + let _consequence_expr = + Surface.Ast.Literal (Surface.Ast.Bool (Pos.unmark rule.rule_consequence)) + in + (* let def = { definition_name = rule.rule_name; definition_parameter = rule.rule_parameter; + definition_condition = rule.rule_condition; definition_expr = (consequence_expr, + Pos.get_position rule.rule_consequence); } in *) + process_def precond scope ctxt prgm (assert false (* def *)) + +let process_scope_use_item (cond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) + (ctxt : Name_resolution.context) (prgm : Ast.program) + (item : Surface.Ast.scope_use_item Pos.marked) : Ast.program = + match Pos.unmark item with + | Surface.Ast.Rule rule -> process_rule cond scope ctxt prgm rule + | Surface.Ast.Definition def -> process_def cond scope ctxt prgm def + | _ -> prgm + +let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) + (use : Surface.Ast.scope_use) : Ast.program = + let name = fst use.scope_use_name in + let scope_uid = Uid.IdentMap.find name ctxt.scope_idmap in + (* Make sure the scope exists *) + let prgm = + match Uid.ScopeMap.find_opt scope_uid prgm with + | Some _ -> prgm + | None -> Uid.ScopeMap.add scope_uid (Ast.empty_scope scope_uid) prgm + in + let cond = + match use.scope_use_condition with + | Some _expr -> + let untyped_term = assert false (* expr_to_lambda scope_uid None ctxt expr *) in + Some untyped_term + | None -> None + in + List.fold_left (process_scope_use_item cond scope_uid ctxt) prgm use.scope_use_items + +(** Scopes processing *) +let translate_program_to_scope (_ctxt : Name_resolution.context) (prgm : Surface.Ast.program) : + Ast.program = + let empty_prgm = Uid.ScopeMap.empty in + let processer_article_item (prgm : Ast.program) (item : Surface.Ast.law_article_item) : + Ast.program = + match item with + | CodeBlock (_block, _) -> + assert false + (* List.fold_left (fun prgm item -> match Pos.unmark item with ScopeUse use -> + process_scope_use ctxt prgm use | _ -> prgm) prgm block *) + | _ -> prgm + in + let rec processer_structure (prgm : Ast.program) (item : Surface.Ast.law_structure) : Ast.program + = + match item with + | LawHeading (_, children) -> + List.fold_left (fun prgm child -> processer_structure prgm child) prgm children + | LawArticle (_, children) -> + List.fold_left (fun prgm child -> processer_article_item prgm child) prgm children + | MetadataBlock (b, c) -> processer_article_item prgm (CodeBlock (b, c)) + | IntermediateText _ -> prgm + in + + let processer_item (prgm : Ast.program) (item : Surface.Ast.program_item) : Ast.program = + match item with LawStructure s -> processer_structure prgm s + in + + List.fold_left processer_item empty_prgm prgm.program_items diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune new file mode 100644 index 00000000..db4cfb47 --- /dev/null +++ b/src/catala/scope_language/dune @@ -0,0 +1,4 @@ +(library + (name scope) + (public_name catala.scope) + (libraries utils dcalc ocamlgraph surface)) diff --git a/src/catala/scope_language/format_scope.ml b/src/catala/scope_language/format.ml similarity index 83% rename from src/catala/scope_language/format_scope.ml rename to src/catala/scope_language/format.ml index 89d3491e..9ad7392e 100644 --- a/src/catala/scope_language/format_scope.ml +++ b/src/catala/scope_language/format.ml @@ -13,18 +13,18 @@ the License. *) (** Print a scope program *) -let print_scope (scope : Scope_ast.scope) : string = - let print_defs (defs : Scope_ast.definition Uid.ScopeDefMap.t) : string = +let print_scope (scope : Ast.scope) : string = + let print_defs (defs : Ast.definition Uid.ScopeDefMap.t) : string = defs |> Uid.ScopeDefMap.bindings - |> List.map (fun (uid, term) -> - Printf.sprintf "%s:\n%s" (Uid.ScopeDef.format_t uid) (Format_lambda.print_term term)) + |> List.map (fun (uid, _term) -> + Printf.sprintf "%s:\n%s" (Uid.ScopeDef.format_t uid) (assert false)) |> String.concat "" in "___Variables Definition___\n" ^ print_defs scope.scope_defs ^ "___Subscope (Re)definition___\n" ^ "\n" (** Print the whole program *) -let print_program (prgm : Scope_ast.program) : string = +let print_program (prgm : Ast.program) : string = prgm |> Uid.ScopeMap.bindings |> List.map (fun (uid, scope) -> Printf.sprintf "Scope %s:\n%s" (Uid.Scope.format_t uid) (print_scope scope)) diff --git a/src/catala/scope_language/interpreter.ml b/src/catala/scope_language/interpreter.ml new file mode 100644 index 00000000..d1612a50 --- /dev/null +++ b/src/catala/scope_language/interpreter.ml @@ -0,0 +1,126 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing + + + 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. *) + +module Pos = Utils.Pos +module Errors = Utils.Errors + +(** The vertices of the scope dependency graph are either : + + - the variables of the scope ; + - the subscopes of the scope. + + Indeed, during interpretation, subscopes are executed atomically. + + In the graph, x -> y if x is used in the definition of y. *) + +module Vertex = struct + type t = Var of Uid.Var.t | SubScope of Uid.SubScope.t + + let hash x = match x with Var x -> Uid.Var.hash x | SubScope x -> Uid.SubScope.hash x + + let compare = compare + + let equal x y = + match (x, y) with + | Var x, Var y -> Uid.Var.compare x y = 0 + | SubScope x, SubScope y -> Uid.SubScope.compare x y = 0 + | _ -> false + + let format_t (x : t) : string = + match x with Var v -> Uid.Var.format_t v | SubScope v -> Uid.SubScope.format_t v +end + +(** On the edges, the label is the expression responsible for the use of the variable *) +module Edge = struct + type t = Pos.t + + let compare = compare + + let default = Pos.no_pos +end + +module ScopeDependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge) +module TopologicalTraversal = Graph.Topological.Make (ScopeDependencies) + +module SCC = Graph.Components.Make (ScopeDependencies) +(** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) + +(** Outputs an error in case of cycles. *) +let check_for_cycle (g : ScopeDependencies.t) : unit = + (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) + let sccs = SCC.scc_list g in + if List.length sccs < ScopeDependencies.nb_vertex g then + let scc = List.find (fun scc -> List.length scc > 1) sccs in + Errors.raise_multispanned_error "cyclic dependency dected between variables!" + (List.flatten + (List.map + (fun v -> + let var_str, var_info = + match v with + | Vertex.Var v -> (Uid.Var.format_t v, Uid.Var.get_info v) + | Vertex.SubScope v -> (Uid.SubScope.format_t v, Uid.SubScope.get_info v) + in + let succs = ScopeDependencies.succ_e g v in + let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in + let succ_str = + match succ with + | Vertex.Var v -> Uid.Var.format_t v + | Vertex.SubScope v -> Uid.SubScope.format_t v + in + [ + (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); + ( Some ("used here in the definition of another cycle variable " ^ succ_str ^ ":"), + edge_pos ); + ]) + scc)) + +let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context) : + ScopeDependencies.t = + let g = ScopeDependencies.empty in + let scope_uid = scope.scope_uid in + (* Add all the vertices to the graph *) + let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in + let g = + Uid.IdentMap.fold + (fun _ (v : Uid.Var.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) + scope_ctxt.var_idmap g + in + let g = + Uid.IdentMap.fold + (fun _ (v : Uid.SubScope.t) g -> ScopeDependencies.add_vertex g (Vertex.SubScope v)) + scope_ctxt.sub_scopes_idmap g + in + let g = + Uid.ScopeDefMap.fold + (fun def_key _def g -> + let fv = assert false (* Dcalc.Ast.term_fv def *) in + Uid.ScopeDefSet.fold + (fun fv_def g -> + match (def_key, fv_def) with + | Uid.ScopeDef.Var defined, Uid.ScopeDef.Var used -> + (* simple case *) + ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) + | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.Var used -> + (* here we are defining the input of a subscope using a var of the scope *) + ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) + | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.SubScopeVar (used, _) -> + (* here we are defining the input of a scope with the output of another subscope *) + ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) + | Uid.ScopeDef.Var defined, Uid.ScopeDef.SubScopeVar (used, _) -> + (* finally we define a scope var with the output of a subscope *) + ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) + fv g) + scope.scope_defs g + in + g diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/scope_language/name_resolution.ml similarity index 77% rename from src/catala/catala_surface/name_resolution.ml rename to src/catala/scope_language/name_resolution.ml index 277411ca..2a58c3d9 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/scope_language/name_resolution.ml @@ -15,9 +15,12 @@ (** Builds a context that allows for mapping each name to a precise uid, taking lexical scopes into account *) +module Pos = Utils.Pos +module Errors = Utils.Errors + type ident = string -type typ = Lambda_ast.typ +type typ = unit type def_context = { var_idmap : Uid.LocalVar.t Uid.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern @@ -51,7 +54,7 @@ let get_var_typ (ctxt : context) (uid : Uid.Var.t) : typ = Uid.VarMap.find uid c (** Process a subscope declaration *) let process_subscope_decl (scope : Uid.Scope.t) (ctxt : context) - (decl : Catala_ast.scope_decl_context_scope) : context = + (decl : Surface.Ast.scope_decl_context_scope) : context = let name, name_pos = decl.scope_decl_context_scope_name in let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in let scope_ctxt = Uid.ScopeMap.find scope ctxt.scopes in @@ -78,30 +81,31 @@ let process_subscope_decl (scope : Uid.Scope.t) (ctxt : context) in { ctxt with scopes = Uid.ScopeMap.add scope scope_ctxt ctxt.scopes } -let process_base_typ ((typ, typ_pos) : Catala_ast.base_typ Pos.marked) : Lambda_ast.typ = +let process_base_typ ((typ, typ_pos) : Surface.Ast.base_typ Pos.marked) : Dcalc.Ast.typ Pos.marked = match typ with - | Catala_ast.Condition -> Lambda_ast.TBool - | Catala_ast.Data (Catala_ast.Collection _) -> raise_unsupported_feature "collection type" typ_pos - | Catala_ast.Data (Catala_ast.Optional _) -> raise_unsupported_feature "option type" typ_pos - | Catala_ast.Data (Catala_ast.Primitive prim) -> ( + | Surface.Ast.Condition -> (Dcalc.Ast.TBool, typ_pos) + | Surface.Ast.Data (Surface.Ast.Collection _) -> + raise_unsupported_feature "collection type" typ_pos + | Surface.Ast.Data (Surface.Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos + | Surface.Ast.Data (Surface.Ast.Primitive prim) -> ( match prim with - | Catala_ast.Integer | Catala_ast.Decimal | Catala_ast.Money | Catala_ast.Date -> - Lambda_ast.TInt - | Catala_ast.Boolean -> Lambda_ast.TBool - | Catala_ast.Text -> raise_unsupported_feature "text type" typ_pos - | Catala_ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) + | Surface.Ast.Integer | Surface.Ast.Decimal | Surface.Ast.Money | Surface.Ast.Date -> + assert false + | Surface.Ast.Boolean -> (Dcalc.Ast.TBool, typ_pos) + | Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos + | Surface.Ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) -let process_type ((typ, typ_pos) : Catala_ast.typ Pos.marked) : Lambda_ast.typ = +let process_type ((typ, typ_pos) : Surface.Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = match typ with - | Catala_ast.Base base_typ -> process_base_typ (base_typ, typ_pos) - | Catala_ast.Func { arg_typ; return_typ } -> - Lambda_ast.TArrow (process_base_typ arg_typ, process_base_typ return_typ) + | Surface.Ast.Base base_typ -> process_base_typ (base_typ, typ_pos) + | Surface.Ast.Func { arg_typ; return_typ } -> + (Dcalc.Ast.TArrow (process_base_typ arg_typ, process_base_typ return_typ), typ_pos) (** Process data declaration *) let process_data_decl (scope : Uid.Scope.t) (ctxt : context) - (decl : Catala_ast.scope_decl_context_data) : context = + (decl : Surface.Ast.scope_decl_context_data) : context = (* First check the type of the context data *) - let data_typ = process_type decl.scope_decl_context_item_typ in + let _data_typ = process_type decl.scope_decl_context_item_typ in let name, pos = decl.scope_decl_context_item_name in let scope_ctxt = Uid.ScopeMap.find scope ctxt.scopes in match Uid.IdentMap.find_opt name scope_ctxt.var_idmap with @@ -116,15 +120,15 @@ let process_data_decl (scope : Uid.Scope.t) (ctxt : context) { ctxt with scopes = Uid.ScopeMap.add scope scope_ctxt ctxt.scopes; - var_typs = Uid.VarMap.add uid data_typ ctxt.var_typs; + var_typs = assert false (* Uid.VarMap.add uid data_typ ctxt.var_typs *); } (** Process an item declaration *) let process_item_decl (scope : Uid.Scope.t) (ctxt : context) - (decl : Catala_ast.scope_decl_context_item) : context = + (decl : Surface.Ast.scope_decl_context_item) : context = match decl with - | Catala_ast.ContextData data_decl -> process_data_decl scope ctxt data_decl - | Catala_ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl + | Surface.Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl + | Surface.Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl (** Adds a binding to the context *) let add_def_local_var (ctxt : context) (scope_uid : Uid.Scope.t) (def_uid : Uid.ScopeDef.t) @@ -141,7 +145,7 @@ let add_def_local_var (ctxt : context) (scope_uid : Uid.Scope.t) (def_uid : Uid. { ctxt with scopes = Uid.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } (** Process a scope declaration *) -let process_scope_decl (ctxt : context) (decl : Catala_ast.scope_decl) : context = +let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : context = let name, pos = decl.scope_decl_name in (* Checks if the name is already used *) match Uid.IdentMap.find_opt name ctxt.scope_idmap with @@ -170,7 +174,7 @@ let process_scope_decl (ctxt : context) (decl : Catala_ast.scope_decl) : context ctxt decl.scope_decl_context let qident_to_scope_def (ctxt : context) (scope_uid : Uid.Scope.t) - (id : Catala_ast.qident Pos.marked) : Uid.ScopeDef.t = + (id : Surface.Ast.qident Pos.marked) : Uid.ScopeDef.t = let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in match Pos.unmark id with | [ x ] -> ( @@ -190,7 +194,7 @@ let qident_to_scope_def (ctxt : context) (scope_uid : Uid.Scope.t) | Some id -> Uid.ScopeDef.SubScopeVar (sub_scope_uid, id) ) | _ -> raise_unsupported_feature "wrong qident" (Pos.get_position id) -let process_scope_use (ctxt : context) (use : Catala_ast.scope_use) : context = +let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = let scope_uid = match Uid.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with | None -> raise_unknown_identifier "for a scope" use.scope_use_name @@ -199,7 +203,7 @@ let process_scope_use (ctxt : context) (use : Catala_ast.scope_use) : context = List.fold_left (fun ctxt use_item -> match Pos.unmark use_item with - | Catala_ast.Definition def -> + | Surface.Ast.Definition def -> let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in let def_uid = qident_to_scope_def ctxt scope_uid def.definition_name in let def_ctxt = @@ -222,47 +226,47 @@ let process_scope_use (ctxt : context) (use : Catala_ast.scope_use) : context = ctxt use.scope_use_items (** Process a code item : for now it only handles scope decls *) -let process_use_item (ctxt : context) (item : Catala_ast.code_item Pos.marked) : context = +let process_use_item (ctxt : context) (item : Surface.Ast.code_item Pos.marked) : context = match Pos.unmark item with | ScopeDecl _ -> ctxt | ScopeUse use -> process_scope_use ctxt use | _ -> raise_unsupported_feature "item not supported" (Pos.get_position item) (** Process a code item : for now it only handles scope decls *) -let process_decl_item (ctxt : context) (item : Catala_ast.code_item Pos.marked) : context = +let process_decl_item (ctxt : context) (item : Surface.Ast.code_item Pos.marked) : context = match Pos.unmark item with ScopeDecl decl -> process_scope_decl ctxt decl | _ -> ctxt (** Process a code block *) -let process_code_block (ctxt : context) (block : Catala_ast.code_block) - (process_item : context -> Catala_ast.code_item Pos.marked -> context) : context = +let process_code_block (ctxt : context) (block : Surface.Ast.code_block) + (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block (** Process a program item *) -let process_law_article_item (ctxt : context) (item : Catala_ast.law_article_item) - (process_item : context -> Catala_ast.code_item Pos.marked -> context) : context = +let process_law_article_item (ctxt : context) (item : Surface.Ast.law_article_item) + (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = match item with CodeBlock (block, _) -> process_code_block ctxt block process_item | _ -> ctxt (** Process a law structure *) -let rec process_law_structure (ctxt : context) (s : Catala_ast.law_structure) - (process_item : context -> Catala_ast.code_item Pos.marked -> context) : context = +let rec process_law_structure (ctxt : context) (s : Surface.Ast.law_structure) + (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = match s with - | Catala_ast.LawHeading (_, children) -> + | Surface.Ast.LawHeading (_, children) -> List.fold_left (fun ctxt child -> process_law_structure ctxt child process_item) ctxt children - | Catala_ast.LawArticle (_, children) -> + | Surface.Ast.LawArticle (_, children) -> List.fold_left (fun ctxt child -> process_law_article_item ctxt child process_item) ctxt children - | Catala_ast.MetadataBlock (b, c) -> - process_law_article_item ctxt (Catala_ast.CodeBlock (b, c)) process_item - | Catala_ast.IntermediateText _ -> ctxt + | Surface.Ast.MetadataBlock (b, c) -> + process_law_article_item ctxt (Surface.Ast.CodeBlock (b, c)) process_item + | Surface.Ast.IntermediateText _ -> ctxt (** Process a program item *) -let process_program_item (ctxt : context) (item : Catala_ast.program_item) - (process_item : context -> Catala_ast.code_item Pos.marked -> context) : context = - match item with Catala_ast.LawStructure s -> process_law_structure ctxt s process_item +let process_program_item (ctxt : context) (item : Surface.Ast.program_item) + (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = + match item with Surface.Ast.LawStructure s -> process_law_structure ctxt s process_item (** Derive the context from metadata, in two passes *) -let form_context (prgm : Catala_ast.program) : context = +let form_context (prgm : Surface.Ast.program) : context = let empty_ctxt = { scope_idmap = Uid.IdentMap.empty; scopes = Uid.ScopeMap.empty; var_typs = Uid.VarMap.empty } in diff --git a/src/catala/scope_language/scope_interpreter.ml b/src/catala/scope_language/scope_interpreter.ml deleted file mode 100644 index 81a7b4fc..00000000 --- a/src/catala/scope_language/scope_interpreter.ml +++ /dev/null @@ -1,301 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Nicolas Chataing - - - 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. *) - -(** The vertices of the scope dependency graph are either : - - - the variables of the scope ; - - the subscopes of the scope. - - Indeed, during interpretation, subscopes are executed atomically. - - In the graph, x -> y if x is used in the definition of y. *) - -module Vertex = struct - type t = Var of Uid.Var.t | SubScope of Uid.SubScope.t - - let hash x = match x with Var x -> Uid.Var.hash x | SubScope x -> Uid.SubScope.hash x - - let compare = compare - - let equal x y = - match (x, y) with - | Var x, Var y -> Uid.Var.compare x y = 0 - | SubScope x, SubScope y -> Uid.SubScope.compare x y = 0 - | _ -> false - - let format_t (x : t) : string = - match x with Var v -> Uid.Var.format_t v | SubScope v -> Uid.SubScope.format_t v -end - -(** On the edges, the label is the expression responsible for the use of the variable *) -module Edge = struct - type t = Pos.t - - let compare = compare - - let default = Pos.no_pos -end - -module ScopeDependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge) -module TopologicalTraversal = Graph.Topological.Make (ScopeDependencies) - -module SCC = Graph.Components.Make (ScopeDependencies) -(** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) - -(** Outputs an error in case of cycles. *) -let check_for_cycle (g : ScopeDependencies.t) : unit = - (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) - let sccs = SCC.scc_list g in - if List.length sccs < ScopeDependencies.nb_vertex g then - let scc = List.find (fun scc -> List.length scc > 1) sccs in - Errors.raise_multispanned_error "cyclic dependency dected between variables!" - (List.flatten - (List.map - (fun v -> - let var_str, var_info = - match v with - | Vertex.Var v -> (Uid.Var.format_t v, Uid.Var.get_info v) - | Vertex.SubScope v -> (Uid.SubScope.format_t v, Uid.SubScope.get_info v) - in - let succs = ScopeDependencies.succ_e g v in - let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in - let succ_str = - match succ with - | Vertex.Var v -> Uid.Var.format_t v - | Vertex.SubScope v -> Uid.SubScope.format_t v - in - [ - (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); - ( Some ("used here in the definition of another cycle variable " ^ succ_str ^ ":"), - edge_pos ); - ]) - scc)) - -let build_scope_dependencies (scope : Scope_ast.scope) (ctxt : Name_resolution.context) : - ScopeDependencies.t = - let g = ScopeDependencies.empty in - let scope_uid = scope.scope_uid in - (* Add all the vertices to the graph *) - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in - let g = - Uid.IdentMap.fold - (fun _ (v : Uid.Var.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) - scope_ctxt.var_idmap g - in - let g = - Uid.IdentMap.fold - (fun _ (v : Uid.SubScope.t) g -> ScopeDependencies.add_vertex g (Vertex.SubScope v)) - scope_ctxt.sub_scopes_idmap g - in - let g = - Uid.ScopeDefMap.fold - (fun def_key def g -> - let fv = Lambda_ast.term_fv def in - Uid.ScopeDefSet.fold - (fun fv_def g -> - match (def_key, fv_def) with - | Uid.ScopeDef.Var defined, Uid.ScopeDef.Var used -> - (* simple case *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) - | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.Var used -> - (* here we are defining the input of a subscope using a var of the scope *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) - | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.SubScopeVar (used, _) -> - (* here we are defining the input of a scope with the output of another subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) - | Uid.ScopeDef.Var defined, Uid.ScopeDef.SubScopeVar (used, _) -> - (* finally we define a scope var with the output of a subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) - fv g) - scope.scope_defs g - in - g - -let rec rewrite_subscope_redef_before_call (ctxt : Name_resolution.context) - (parent_scope : Uid.Scope.t) (subscope : Scope_ast.scope) - ((redef, redef_ty) : Scope_ast.definition) : Scope_ast.definition = - let parent_scope_ctx = Uid.ScopeMap.find parent_scope ctxt.scopes in - let rec_call = rewrite_subscope_redef_before_call ctxt parent_scope subscope in - match Pos.unmark redef with - | Lambda_ast.EVar (prefix, var) -> ( - match prefix with - | Lambda_ast.NoPrefix -> - (* this is a variable of the parent scope, we add the prefix *) - ( Pos.same_pos_as (Lambda_ast.EVar (Lambda_ast.CallerPrefix (1, None), var)) redef, - redef_ty ) - | Lambda_ast.SubScopePrefix parent_sub -> - let parent_sub_real = Uid.SubScopeMap.find parent_sub parent_scope_ctx.sub_scopes in - (* two cases here *) - if parent_sub_real = subscope.scope_uid then - (* we remove the prefix since we're calling this precise subscope *) - (Pos.same_pos_as (Lambda_ast.EVar (Lambda_ast.NoPrefix, var)) redef, redef_ty) - else - (* we add the caller prefix*) - ( Pos.same_pos_as - (Lambda_ast.EVar (Lambda_ast.CallerPrefix (1, Some parent_sub), var)) - redef, - redef_ty ) - | Lambda_ast.CallerPrefix (i, grand_parent_sub) -> - (* In this tricky case, we are trying to call a subscope while being executed as a - subscope of a "grand-parent" scope. See [tests/scopes/grand_parent_scope.catala] for an - exemple. What we do in this case is that we propagate the prefix while adding 1 to the - generation counter *) - ( Pos.same_pos_as - (Lambda_ast.EVar (Lambda_ast.CallerPrefix (i + 1, grand_parent_sub), var)) - redef, - redef_ty ) ) - | Lambda_ast.EInt _ | Lambda_ast.EBool _ | Lambda_ast.EDec _ | Lambda_ast.EOp _ - | Lambda_ast.ELocalVar _ -> - (redef, redef_ty) - | Lambda_ast.EFun (bindings, body) -> - (Pos.same_pos_as (Lambda_ast.EFun (bindings, rec_call body)) redef, redef_ty) - | Lambda_ast.EApp (f, args) -> - (Pos.same_pos_as (Lambda_ast.EApp (rec_call f, List.map rec_call args)) redef, redef_ty) - | Lambda_ast.EIfThenElse (if_t, then_t, else_t) -> - ( Pos.same_pos_as - (Lambda_ast.EIfThenElse (rec_call if_t, rec_call then_t, rec_call else_t)) - redef, - redef_ty ) - | Lambda_ast.EDefault default -> - ( Pos.same_pos_as - (Lambda_ast.EDefault - { - default with - defaults = List.map (fun (x, y) -> (rec_call x, rec_call y)) default.defaults; - }) - redef, - redef_ty ) - -(** In this function, the keys of the [redefs] maps are variables of the [subscope] *) -let merge_var_redefs_before_subscope_call (ctxt : Name_resolution.context) - (parent_scope : Uid.Scope.t) (subscope : Scope_ast.scope) - (redefs : Scope_ast.definition Uid.VarMap.t) : Scope_ast.scope = - let merge_defaults : Lambda_ast.term -> Lambda_ast.term -> Lambda_ast.term = - Lambda_ast.map_untype2 (fun old_t new_t -> - match (old_t, new_t) with - | EDefault old_def, EDefault new_def -> - EDefault (Lambda_ast.merge_default_terms old_def new_def) - | _ -> assert false - (* should not happen *)) - in - (* when merging redefinitions inside a subscope for execution, we need to annotate the variables - of the parent scope with the caller prefix *) - { - subscope with - scope_defs = - Uid.VarMap.fold - (fun new_def_var new_def sub_defs -> - let new_def = rewrite_subscope_redef_before_call ctxt parent_scope subscope new_def in - match Uid.ScopeDefMap.find_opt (Uid.ScopeDef.Var new_def_var) sub_defs with - | None -> Uid.ScopeDefMap.add (Uid.ScopeDef.Var new_def_var) new_def sub_defs - | Some old_def -> - let def = merge_defaults old_def new_def in - Uid.ScopeDefMap.add (Uid.ScopeDef.Var new_def_var) def sub_defs) - redefs subscope.scope_defs; - } - -let rewrite_context_before_executing_subscope (subscope : Uid.SubScope.t) - (exec_context : Lambda_interpreter.exec_context) : Lambda_interpreter.exec_context = - Lambda_interpreter.ExecContext.fold - (fun key value acc -> - match key with - | Lambda_interpreter.ExecContextKey.LocalVar _ -> - (* we can forget local vars when entering a subscope *) - acc - | Lambda_interpreter.ExecContextKey.ScopeVar (prefix, var) -> - let new_prefix = - (* note: this has to match with the behavior of [rewrite_subscope_redef_before_call] *) - match prefix with - | Lambda_ast.NoPrefix -> Lambda_ast.CallerPrefix (1, None) - | Lambda_ast.CallerPrefix (i, sub) -> Lambda_ast.CallerPrefix (i + 1, sub) - | Lambda_ast.SubScopePrefix sub -> - if sub = subscope then Lambda_ast.NoPrefix else Lambda_ast.CallerPrefix (1, Some sub) - in - Lambda_interpreter.ExecContext.add - (Lambda_interpreter.ExecContextKey.ScopeVar (new_prefix, var)) - value acc) - exec_context Lambda_interpreter.ExecContext.empty - -let rewrite_context_after_executing_subscope (subscope : Uid.SubScope.t) - (exec_context : Lambda_interpreter.exec_context) : Lambda_interpreter.exec_context = - Lambda_interpreter.ExecContext.fold - (fun key value acc -> - match key with - | Lambda_interpreter.ExecContextKey.LocalVar _ -> - (* we can forget local vars when entering a subscope *) - acc - | Lambda_interpreter.ExecContextKey.ScopeVar (prefix, var) -> ( - let new_prefix = - match prefix with - | Lambda_ast.NoPrefix -> Some (Lambda_ast.SubScopePrefix subscope) - | Lambda_ast.CallerPrefix (i, sub) -> ( - if i > 1 then Some (Lambda_ast.CallerPrefix (i - 1, sub)) - else - match sub with - | None -> Some Lambda_ast.NoPrefix - | Some sub -> Some (Lambda_ast.SubScopePrefix sub) ) - | Lambda_ast.SubScopePrefix _ -> None - (* we drop the subscope's subscopes since they can't be accessed *) - in - match new_prefix with - | None -> acc - | Some new_prefix -> - Lambda_interpreter.ExecContext.add - (Lambda_interpreter.ExecContextKey.ScopeVar (new_prefix, var)) - value acc )) - exec_context Lambda_interpreter.ExecContext.empty - -let rec execute_scope ?(exec_context = Lambda_interpreter.empty_exec_ctxt) - (ctxt : Name_resolution.context) (prgm : Scope_ast.program) (scope_prgm : Scope_ast.scope) : - Lambda_interpreter.exec_context = - let scope_ctxt = Uid.ScopeMap.find scope_prgm.scope_uid ctxt.scopes in - let deps = build_scope_dependencies scope_prgm ctxt in - check_for_cycle deps; - TopologicalTraversal.fold - (fun v exec_context -> - match v with - | Vertex.Var var -> ( - match Uid.ScopeDefMap.find_opt (Uid.ScopeDef.Var var) scope_prgm.scope_defs with - | Some def -> - (* we evaluate a variable of the scope, no tricky business here *) - Lambda_interpreter.ExecContext.add - (Lambda_interpreter.ExecContextKey.ScopeVar (Lambda_ast.NoPrefix, var)) - ( Lambda_interpreter.eval_term (Uid.ScopeDef.Var var) exec_context def - |> Lambda_ast.untype ) - exec_context - | None -> assert false (* should not happen *) ) - | Vertex.SubScope subscope_uid -> - (* this is the tricky case where we have to the the bookkeeping of rewriting the context - and additional defaults that we pass for the subscope for execution. See formalization - for more details *) - let subscope_real_uid = Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in - let subscope = Uid.ScopeMap.find subscope_real_uid prgm in - let redefs_to_include_to_subscope = - Uid.ScopeDefMap.fold - (fun def_key def acc -> - match def_key with - | Uid.ScopeDef.Var _ -> acc - | Uid.ScopeDef.SubScopeVar (def_sub_uid, var) -> - if def_sub_uid = subscope_uid then Uid.VarMap.add var def acc else acc) - scope_prgm.scope_defs Uid.VarMap.empty - in - let subscope = - merge_var_redefs_before_subscope_call ctxt scope_prgm.scope_uid subscope - redefs_to_include_to_subscope - in - let exec_context = rewrite_context_before_executing_subscope subscope_uid exec_context in - let exec_context = execute_scope ~exec_context ctxt prgm subscope in - let exec_context = rewrite_context_after_executing_subscope subscope_uid exec_context in - exec_context) - deps exec_context diff --git a/src/catala/scope_language/uid.ml b/src/catala/scope_language/uid.ml index 270b411c..bcff381a 100644 --- a/src/catala/scope_language/uid.ml +++ b/src/catala/scope_language/uid.ml @@ -12,6 +12,7 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Pos = Utils.Pos module IdentMap = Map.Make (String) module type Id = sig diff --git a/src/catala/scope_language/uid.mli b/src/catala/scope_language/uid.mli index 2207ebcb..fc80ecbb 100644 --- a/src/catala/scope_language/uid.mli +++ b/src/catala/scope_language/uid.mli @@ -12,6 +12,8 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +module Pos = Utils.Pos + module IdentMap : Map.S with type key = String.t module MarkedString : sig diff --git a/src/catala/cli.ml b/src/catala/utils/cli.ml similarity index 100% rename from src/catala/cli.ml rename to src/catala/utils/cli.ml diff --git a/src/catala/utils/dune b/src/catala/utils/dune new file mode 100644 index 00000000..ee8dc89b --- /dev/null +++ b/src/catala/utils/dune @@ -0,0 +1,4 @@ +(library + (name utils) + (public_name catala.utils) + (libraries cmdliner dune-build-info ANSITerminal)) diff --git a/src/catala/errors.ml b/src/catala/utils/errors.ml similarity index 100% rename from src/catala/errors.ml rename to src/catala/utils/errors.ml diff --git a/src/catala/pos.ml b/src/catala/utils/pos.ml similarity index 100% rename from src/catala/pos.ml rename to src/catala/utils/pos.ml diff --git a/src/catala/pos.mli b/src/catala/utils/pos.mli similarity index 100% rename from src/catala/pos.mli rename to src/catala/utils/pos.mli From df2c0f1b0189ca626dd2bfa03eb9534ea790f8b6 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 09:27:55 +0100 Subject: [PATCH 005/142] Fixed github workflow --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 08c057c2..10e47e17 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -63,4 +63,4 @@ jobs: - name: Make assets and documentation run: | eval $(opam env) - make all + make website-assets doc From 0e7943b8f79281f8bac67d14e02af60a8b7a453c Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 09:33:07 +0100 Subject: [PATCH 006/142] Fix makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index faac5b99..8a2297cd 100644 --- a/Makefile +++ b/Makefile @@ -141,7 +141,7 @@ tests: build .FORCE grammar.html: src/catala/catala_surface/parser.mly obelisk html -o $@ $< -catala.html: src/catala/cli.ml +catala.html: src/catala/utils/cli.ml dune exec src/catala.exe -- --help=groff | man2html | sed -e '1,8d' \ | tac | sed "1,20d" | tac > $@ From 8917383a92c16af2d323817ea0a0dc53126ccc7f Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 10:44:06 +0100 Subject: [PATCH 007/142] Implemented interpreter --- src/catala/default_calculus/ast.ml | 8 +-- src/catala/default_calculus/interpreter.ml | 73 ++++++++++++++++++++++ src/catala/default_calculus/typing.ml | 31 ++++++--- 3 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 src/catala/default_calculus/interpreter.ml diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index fbed878c..e105180c 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -16,17 +16,17 @@ module Pos = Utils.Pos type typ = TBool | TUnit | TArrow of typ Pos.marked * typ Pos.marked -type lit = LTrue | LFalse | LEmptyError | LConflictError +type lit = LTrue | LFalse | LEmptyError type expr = - | EVar of expr Bindlib.var + | EVar of expr Pos.marked Bindlib.var | ELit of lit - | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.binder * typ + | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * typ | EApp of expr Pos.marked * expr Pos.marked | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list module Var = struct - type t = expr Bindlib.var + type t = expr Pos.marked Bindlib.var let compare x y = Bindlib.compare_vars x y end diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml new file mode 100644 index 00000000..d588f731 --- /dev/null +++ b/src/catala/default_calculus/interpreter.ml @@ -0,0 +1,73 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module Pos = Utils.Pos +module Errors = Utils.Errors +module A = Ast + +let is_value (e : A.expr Pos.marked) : bool = + match Pos.unmark e with A.EAbs _ | ELit _ -> true | _ -> false + +let is_empty_error (e : A.expr Pos.marked) : bool = + match Pos.unmark e with ELit LEmptyError -> true | _ -> false + +let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = + if is_value e then e + else + match Pos.unmark e with + | EVar _ -> + Errors.raise_spanned_error + "Free variable found at evaluation (should not happen if term was well-typed" + (Pos.get_position e) + | EApp (e1, e2) -> ( + let e1 = evaluate_expr e1 in + let e2 = evaluate_expr e2 in + match Pos.unmark e1 with + | EAbs (_, binder, _) -> evaluate_expr (Bindlib.subst binder e2) + | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e + | _ -> + Errors.raise_spanned_error + "Function has not been reduced to a lambda at evaluation (should not happen if the \ + term was well-typed" + (Pos.get_position e) ) + | EAbs _ | ELit _ -> assert false (* should not happen because the remaining cases are values *) + | EDefault (just, cons, subs) -> ( + let just = evaluate_expr just in + match Pos.unmark just with + | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e + | ELit LTrue -> evaluate_expr cons + | ELit LFalse -> ( + let subs = List.map evaluate_expr subs in + let empty_count = List.length (List.filter is_empty_error subs) in + match List.length subs - empty_count with + | 0 -> Pos.same_pos_as (A.ELit LEmptyError) e + | 1 -> List.find (fun sub -> not (is_empty_error sub)) subs + | _ -> + Errors.raise_multispanned_error + "There is a conflict between multiple rules for assigning a single value." + ( [ + ( Some "This rule is not triggered, so we consider rules of lower priority", + Pos.get_position e ); + ] + @ List.map + (fun sub -> + ( Some + "This value is available because the justification of its rule is true", + Pos.get_position sub )) + (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) + | _ -> + Errors.raise_spanned_error + "Default justification has not been reduced to a boolean at evaluation (should not \ + happen if the term was well-typed" + (Pos.get_position e) ) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index bca77818..a27dbeb0 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -63,22 +63,32 @@ let rec ast_to_typ (ty : A.typ) : typ = ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), UnionFind.make (Pos.map_under_mark ast_to_typ t2) ) -type env = { expr_vars : typ Pos.marked A.VarMap.t } +let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = + Pos.map_under_mark + (fun ty -> + match ty with + | TUnit -> A.TUnit + | TBool -> A.TBool + | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) + | TAny -> A.TUnit) + (UnionFind.get (UnionFind.find ty)) + +type env = typ Pos.marked A.VarMap.t let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem = match Pos.unmark e with | EVar v -> ( - match A.VarMap.find_opt v env.expr_vars with + match A.VarMap.find_opt v env with | Some t -> UnionFind.make t | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) | ELit (LTrue | LFalse) -> UnionFind.make (Pos.same_pos_as TBool e) - | ELit (LEmptyError | LConflictError) -> UnionFind.make (Pos.same_pos_as TAny e) + | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | EAbs (pos_binder, binder, tau) -> let x, body = Bindlib.unbind binder in - let env = { expr_vars = A.VarMap.add x (ast_to_typ tau, pos_binder) env.expr_vars } in + let env = A.VarMap.add x (ast_to_typ tau, pos_binder) env in typecheck_expr_bottom_up env body | EApp (e1, e2) -> let t2 = typecheck_expr_bottom_up env e2 in @@ -96,16 +106,16 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = match Pos.unmark e with | EVar v -> ( - match A.VarMap.find_opt v env.expr_vars with + match A.VarMap.find_opt v env with | Some tau' -> ignore (unify tau (UnionFind.make tau')) | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) | ELit (LTrue | LFalse) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) - | ELit (LEmptyError | LConflictError) -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) + | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | EAbs (pos_binder, binder, t_arg) -> let x, body = Bindlib.unbind binder in - let env = { expr_vars = A.VarMap.add x (ast_to_typ t_arg, pos_binder) env.expr_vars } in + let env = A.VarMap.add x (ast_to_typ t_arg, pos_binder) env in let t_out = typecheck_expr_bottom_up env body in let t_func = UnionFind.make @@ -121,3 +131,10 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); typecheck_expr_top_down env cons tau; List.iter (fun sub -> typecheck_expr_top_down env sub tau) subs + +let infer_type (e : A.expr Pos.marked) : A.typ Pos.marked = + let ty = typecheck_expr_bottom_up A.VarMap.empty e in + typ_to_ast ty + +let check_type (e : A.expr Pos.marked) (tau : A.typ Pos.marked) = + typecheck_expr_top_down A.VarMap.empty e (UnionFind.make (Pos.map_under_mark ast_to_typ tau)) From aafd6045e2f2fd332be2e34a73acd4e4fb9b3fe2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 10:52:32 +0100 Subject: [PATCH 008/142] Scope -> desugared --- src/catala/default_calculus/interpreter.ml | 4 ++-- src/catala/{scope_language => desugared}/ast.ml | 0 .../{scope_language => desugared}/desugaring.ml | 0 src/catala/{scope_language => desugared}/dune | 4 ++-- src/catala/{scope_language => desugared}/format.ml | 0 .../{scope_language => desugared}/interpreter.ml | 0 .../{scope_language => desugared}/name_resolution.ml | 0 src/catala/{scope_language => desugared}/uid.ml | 0 src/catala/{scope_language => desugared}/uid.mli | 0 src/catala/driver.ml | 12 ++++++------ src/catala/dune | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) rename src/catala/{scope_language => desugared}/ast.ml (100%) rename src/catala/{scope_language => desugared}/desugaring.ml (100%) rename src/catala/{scope_language => desugared}/dune (51%) rename src/catala/{scope_language => desugared}/format.ml (100%) rename src/catala/{scope_language => desugared}/interpreter.ml (100%) rename src/catala/{scope_language => desugared}/name_resolution.ml (100%) rename src/catala/{scope_language => desugared}/uid.ml (100%) rename src/catala/{scope_language => desugared}/uid.mli (100%) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index d588f731..558f3150 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -57,13 +57,13 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = Errors.raise_multispanned_error "There is a conflict between multiple rules for assigning a single value." ( [ - ( Some "This rule is not triggered, so we consider rules of lower priority", + ( Some "This rule is not triggered, so we consider rules of lower priority:", Pos.get_position e ); ] @ List.map (fun sub -> ( Some - "This value is available because the justification of its rule is true", + "This value is available because the justification of its rule is true:", Pos.get_position sub )) (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) | _ -> diff --git a/src/catala/scope_language/ast.ml b/src/catala/desugared/ast.ml similarity index 100% rename from src/catala/scope_language/ast.ml rename to src/catala/desugared/ast.ml diff --git a/src/catala/scope_language/desugaring.ml b/src/catala/desugared/desugaring.ml similarity index 100% rename from src/catala/scope_language/desugaring.ml rename to src/catala/desugared/desugaring.ml diff --git a/src/catala/scope_language/dune b/src/catala/desugared/dune similarity index 51% rename from src/catala/scope_language/dune rename to src/catala/desugared/dune index db4cfb47..046691fa 100644 --- a/src/catala/scope_language/dune +++ b/src/catala/desugared/dune @@ -1,4 +1,4 @@ (library - (name scope) - (public_name catala.scope) + (name desugared) + (public_name catala.desugared) (libraries utils dcalc ocamlgraph surface)) diff --git a/src/catala/scope_language/format.ml b/src/catala/desugared/format.ml similarity index 100% rename from src/catala/scope_language/format.ml rename to src/catala/desugared/format.ml diff --git a/src/catala/scope_language/interpreter.ml b/src/catala/desugared/interpreter.ml similarity index 100% rename from src/catala/scope_language/interpreter.ml rename to src/catala/desugared/interpreter.ml diff --git a/src/catala/scope_language/name_resolution.ml b/src/catala/desugared/name_resolution.ml similarity index 100% rename from src/catala/scope_language/name_resolution.ml rename to src/catala/desugared/name_resolution.ml diff --git a/src/catala/scope_language/uid.ml b/src/catala/desugared/uid.ml similarity index 100% rename from src/catala/scope_language/uid.ml rename to src/catala/desugared/uid.ml diff --git a/src/catala/scope_language/uid.mli b/src/catala/desugared/uid.mli similarity index 100% rename from src/catala/scope_language/uid.mli rename to src/catala/desugared/uid.mli diff --git a/src/catala/driver.ml b/src/catala/driver.ml index f64dc47d..91d44658 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -96,30 +96,30 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ close_out oc; 0 | Cli.Run -> - let ctxt = Scope.Name_resolution.form_context program in + let ctxt = Desugared.Name_resolution.form_context program in let scope_uid = match ex_scope with | None -> Errors.raise_error "No scope was provided for execution." | Some name -> ( - match Scope.Uid.IdentMap.find_opt name ctxt.scope_idmap with + match Desugared.Uid.IdentMap.find_opt name ctxt.scope_idmap with | None -> Errors.raise_error (Printf.sprintf "There is no scope %s inside the program." name) | Some uid -> uid ) in - let prgm = Scope.Desugaring.translate_program_to_scope ctxt program in + let prgm = Desugared.Desugaring.translate_program_to_scope ctxt program in let _scope = - match Scope.Uid.ScopeMap.find_opt scope_uid prgm with + match Desugared.Uid.ScopeMap.find_opt scope_uid prgm with | Some scope -> scope | None -> - let scope_info = Scope.Uid.Scope.get_info scope_uid in + let scope_info = Desugared.Uid.Scope.get_info scope_uid in Errors.raise_spanned_error (Printf.sprintf "Scope %s does not define anything, and therefore cannot be executed" (Utils.Pos.unmark scope_info)) (Utils.Pos.get_position scope_info) in - (* let exec_ctxt = Scope.Interpreter.execute_scope ctxt prgm scope in + (* let exec_ctxt = Desugared.Interpreter.execute_scope ctxt prgm scope in Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) diff --git a/src/catala/dune b/src/catala/dune index 1bb61551..8f8f5e9e 100644 --- a/src/catala/dune +++ b/src/catala/dune @@ -1,6 +1,6 @@ (library (public_name catala) - (libraries catala.utils catala.surface catala.scope catala.literate + (libraries catala.utils catala.surface catala.desugared catala.literate catala.dcalc)) (documentation From 39b1b4af08628e5c0091964c5c7216b59b56e266 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 11:42:29 +0100 Subject: [PATCH 009/142] Split UId --- src/catala/desugared/uid.ml | 49 +----------------------- src/catala/desugared/uid.mli | 31 +++------------ src/catala/scope_language/ast.ml | 15 ++++++++ src/catala/scope_language/dune | 4 ++ src/catala/utils/uid.ml | 65 ++++++++++++++++++++++++++++++++ src/catala/utils/uid.mli | 39 +++++++++++++++++++ 6 files changed, 130 insertions(+), 73 deletions(-) create mode 100644 src/catala/scope_language/ast.ml create mode 100644 src/catala/scope_language/dune create mode 100644 src/catala/utils/uid.ml create mode 100644 src/catala/utils/uid.mli diff --git a/src/catala/desugared/uid.ml b/src/catala/desugared/uid.ml index bcff381a..3107be91 100644 --- a/src/catala/desugared/uid.ml +++ b/src/catala/desugared/uid.ml @@ -12,55 +12,10 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +open Utils.Uid module Pos = Utils.Pos +module Orig = Utils.Uid module IdentMap = Map.Make (String) - -module type Id = sig - type t - - type info - - val fresh : info -> t - - val get_info : t -> info - - val compare : t -> t -> int - - val format_t : t -> string - - val hash : t -> int -end - -module Make (X : sig - type info - - val format_info : info -> string -end) : Id with type info = X.info = struct - type t = { id : int; info : X.info } - - type info = X.info - - let counter = ref 0 - - let fresh (info : X.info) : t = - incr counter; - { 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 format_t (x : t) : string = Printf.sprintf "%s" (X.format_info x.info) - - let hash (x : t) : int = x.id -end - -module MarkedString = struct - type info = string Pos.marked - - let format_info (s, _) = s -end - module Scope = Make (MarkedString) module ScopeSet = Set.Make (Scope) module ScopeMap = Map.Make (Scope) diff --git a/src/catala/desugared/uid.mli b/src/catala/desugared/uid.mli index fc80ecbb..e897de35 100644 --- a/src/catala/desugared/uid.mli +++ b/src/catala/desugared/uid.mli @@ -13,50 +13,29 @@ the License. *) module Pos = Utils.Pos +module Orig = Utils.Uid module IdentMap : Map.S with type key = String.t -module MarkedString : sig - type info = string Pos.marked - - val format_info : 'a * 'b -> 'a -end - -module type Id = sig - type t - - type info - - val fresh : info -> t - - val get_info : t -> info - - val compare : t -> t -> int - - val format_t : t -> string - - val hash : t -> int -end - -module Scope : Id with type info = MarkedString.info +module Scope : Orig.Id with type info = Orig.MarkedString.info module ScopeSet : Set.S with type elt = Scope.t module ScopeMap : Map.S with type key = Scope.t -module Var : Id with type info = MarkedString.info +module Var : Orig.Id with type info = Orig.MarkedString.info module VarSet : Set.S with type elt = Var.t module VarMap : Map.S with type key = Var.t -module LocalVar : Id with type info = MarkedString.info +module LocalVar : Orig.Id with type info = Orig.MarkedString.info module LocalVarSet : Set.S with type elt = LocalVar.t module LocalVarMap : Map.S with type key = LocalVar.t -module SubScope : Id with type info = MarkedString.info +module SubScope : Orig.Id with type info = Orig.MarkedString.info module SubScopeSet : Set.S with type elt = SubScope.t diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml new file mode 100644 index 00000000..7139d599 --- /dev/null +++ b/src/catala/scope_language/ast.ml @@ -0,0 +1,15 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module Pos = Utils.Pos diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune new file mode 100644 index 00000000..f4d9414d --- /dev/null +++ b/src/catala/scope_language/dune @@ -0,0 +1,4 @@ +(library + (name scope) + (public_name catala.scope) + (libraries utils dcalc)) diff --git a/src/catala/utils/uid.ml b/src/catala/utils/uid.ml new file mode 100644 index 00000000..e0cce563 --- /dev/null +++ b/src/catala/utils/uid.ml @@ -0,0 +1,65 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module type Info = sig + type info + + val format_info : info -> string +end + +module type Id = sig + type t + + type info + + val fresh : info -> t + + val get_info : t -> info + + val compare : t -> t -> int + + val format_t : t -> string + + val hash : t -> int +end + +module Make (X : sig + type info + + val format_info : info -> string +end) : Id with type info = X.info = struct + type t = { id : int; info : X.info } + + type info = X.info + + let counter = ref 0 + + let fresh (info : X.info) : t = + incr counter; + { 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 format_t (x : t) : string = Printf.sprintf "%s" (X.format_info x.info) + + let hash (x : t) : int = x.id +end + +module MarkedString = struct + type info = string Pos.marked + + let format_info (s, _) = s +end diff --git a/src/catala/utils/uid.mli b/src/catala/utils/uid.mli new file mode 100644 index 00000000..c32c1afc --- /dev/null +++ b/src/catala/utils/uid.mli @@ -0,0 +1,39 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module type Info = sig + type info + + val format_info : info -> string +end + +module MarkedString : Info with type info = string Pos.marked + +module type Id = sig + type t + + type info + + val fresh : info -> t + + val get_info : t -> info + + val compare : t -> t -> int + + val format_t : t -> string + + val hash : t -> int +end + +module Make (X : Info) : Id with type info = X.info From e5078b1c98b52d2d81685523eab5f57c7a5823b2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 12:20:38 +0100 Subject: [PATCH 010/142] Restored build --- src/catala/desugared/ast.ml | 45 ++++++- src/catala/desugared/desugaring.ml | 96 +++++++------- src/catala/desugared/dune | 2 +- src/catala/desugared/format.ml | 10 +- src/catala/desugared/interpreter.ml | 43 ++++--- src/catala/desugared/name_resolution.ml | 160 +++++++++++++----------- src/catala/desugared/uid.ml | 54 -------- src/catala/desugared/uid.mli | 60 --------- src/catala/driver.ml | 6 +- src/catala/scope_language/ast.ml | 7 ++ src/catala/scope_language/dune | 4 +- 11 files changed, 213 insertions(+), 274 deletions(-) delete mode 100644 src/catala/desugared/uid.ml delete mode 100644 src/catala/desugared/uid.mli diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 050507bf..d328385d 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -13,9 +13,42 @@ the License. *) module Pos = Utils.Pos +module Uid = Utils.Uid +module IdentMap = Map.Make (String) +module Var = Uid.Make (Uid.MarkedString) +module VarSet = Set.Make (Var) +module VarMap = Map.Make (Var) +module LocalVar = Uid.Make (Uid.MarkedString) +module LocalVarSet = Set.Make (LocalVar) +module LocalVarMap = Map.Make (LocalVar) + +(** Inside a scope, a definition can refer either to a scope def, or a subscope def *) +module ScopeDef = struct + type t = + | Var of Var.t + | SubScopeVar of Scopelang.Ast.SubScopeName.t * Var.t + (** In this case, the [Uid.Var.t] lives inside the context of the subscope's original + declaration *) + + let compare x y = + match (x, y) with + | Var x, Var y | Var x, SubScopeVar (_, y) | SubScopeVar (_, x), Var y -> Var.compare x y + | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.SubScopeName.compare x y + + let format_t x = + match x with + | Var v -> Var.format_t v + | SubScopeVar (s, v) -> + Printf.sprintf "%s.%s" (Scopelang.Ast.SubScopeName.format_t s) (Var.format_t v) + + let hash x = match x with Var v -> Var.hash v | SubScopeVar (_, v) -> Var.hash v +end + +module ScopeDefMap = Map.Make (ScopeDef) +module ScopeDefSet = Set.Make (ScopeDef) (* Scopes *) -type binder = Uid.LocalVar.t +type binder = LocalVar.t type definition = unit @@ -32,18 +65,18 @@ type meta_assertion = | VariesWith of unit * variation_typ Pos.marked option type scope = { - scope_uid : Uid.Scope.t; - scope_defs : definition Uid.ScopeDefMap.t; + scope_uid : Scopelang.Ast.ScopeName.t; + scope_defs : definition ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } -let empty_scope (uid : Uid.Scope.t) : scope = +let empty_scope (uid : Scopelang.Ast.ScopeName.t) : scope = { scope_uid = uid; - scope_defs = Uid.ScopeDefMap.empty; + scope_defs = ScopeDefMap.empty; scope_assertions = []; scope_meta_assertions = []; } -type program = scope Uid.ScopeMap.t +type program = scope Scopelang.Ast.ScopeMap.t diff --git a/src/catala/desugared/desugaring.ml b/src/catala/desugared/desugaring.ml index c2d71b4a..18f99445 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/desugared/desugaring.ml @@ -18,34 +18,34 @@ module Errors = Utils.Errors (** The optional argument subdef allows to choose between differents uids in case the expression is a redefinition of a subvariable *) -(* let rec expr_to_lambda (scope : Uid.Scope.t) (def_key : Uid.ScopeDef.t option) (ctxt : - Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : 'a = let scope_ctxt - = Uid.ScopeMap.find scope ctxt.scopes in let rec_helper = expr_to_lambda scope def_key ctxt in - match expr with | IfThenElse (e_if, e_then, e_else) -> ((EIfThenElse (rec_helper e_if, rec_helper - e_then, rec_helper e_else), pos), TDummy) | Binop (op, e1, e2) -> let op_term = (Pos.same_pos_as - (EOp (Binop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ rec_helper e1; rec_helper e2 ]), - pos), TDummy) | Unop (op, e) -> let op_term = (Pos.same_pos_as (EOp (Unop (Pos.unmark op))) op, - TDummy) in ((EApp (op_term, [ rec_helper e ]), pos), TDummy) | Literal l -> let untyped_term = - match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec (i, f), _), _) -> EDec (i, f) | - Bool b -> EBool b | _ -> Name_resolution.raise_unsupported_feature "literal" pos in - ((untyped_term, pos), TDummy) | Ident x -> ( (* first we check whether this is a local var, then - we resort to scope-wide variables *) match def_key with | Some def_key -> ( let def_ctxt = - Uid.ScopeDefMap.find def_key scope_ctxt.definitions in match Uid.IdentMap.find_opt x - def_ctxt.var_idmap with | None -> ( match Uid.IdentMap.find_opt x scope_ctxt.var_idmap with | - Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> - Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" (x, pos) ) | Some - uid -> ((ELocalVar uid, pos), TDummy) ) | None -> ( match Uid.IdentMap.find_opt x - scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> +(* let rec expr_to_lambda (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t option) + (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : 'a = let + scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in let rec_helper = expr_to_lambda + scope def_key ctxt in match expr with | IfThenElse (e_if, e_then, e_else) -> ((EIfThenElse + (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos), TDummy) | Binop (op, e1, e2) -> + let op_term = (Pos.same_pos_as (EOp (Binop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ + rec_helper e1; rec_helper e2 ]), pos), TDummy) | Unop (op, e) -> let op_term = (Pos.same_pos_as + (EOp (Unop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ rec_helper e ]), pos), TDummy) | + Literal l -> let untyped_term = match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec + (i, f), _), _) -> EDec (i, f) | Bool b -> EBool b | _ -> + Name_resolution.raise_unsupported_feature "literal" pos in ((untyped_term, pos), TDummy) | Ident + x -> ( (* first we check whether this is a local var, then we resort to scope-wide variables *) + match def_key with | Some def_key -> ( let def_ctxt = Ast.ScopeDefMap.find def_key + scope_ctxt.definitions in match Ast.IdentMap.find_opt x def_ctxt.var_idmap with | None -> ( match + Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), + TDummy) | None -> Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" + (x, pos) ) | Some uid -> ((ELocalVar uid, pos), TDummy) ) | None -> ( match Ast.IdentMap.find_opt + x scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | Dotted (e, x) -> ( (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) match - Pos.unmark e with | Ident y -> let subscope_uid : Uid.SubScope.t = + Pos.unmark e with | Ident y -> let subscope_uid : Scopelang.Ast.SubScopeName.t = Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in let subscope_real_uid : - Uid.Scope.t = Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in let subscope_var_uid = - Name_resolution.get_var_uid subscope_real_uid ctxt x in ((EVar (SubScopePrefix subscope_uid, - subscope_var_uid), pos), TDummy) | _ -> Name_resolution.raise_unsupported_feature "left hand side - of a dotted expression should be an identifier" pos ) | FunCall (f, arg) -> ((EApp (rec_helper f, - [ rec_helper arg ]), pos), TDummy) | _ -> Name_resolution.raise_unsupported_feature "unsupported - expression" pos *) + Scopelang.Ast.ScopeName.t = Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in + let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in ((EVar + (SubScopePrefix subscope_uid, subscope_var_uid), pos), TDummy) | _ -> + Name_resolution.raise_unsupported_feature "left hand side of a dotted expression should be an + identifier" pos ) | FunCall (f, arg) -> ((EApp (rec_helper f, [ rec_helper arg ]), pos), TDummy) + | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos *) (* Translation from the parsed ast to the scope language *) @@ -55,8 +55,8 @@ module Errors = Utils.Errors precond; cond ]), Pos.get_position (fst precond)), TDummy) | Some cond, None | None, Some cond -> cond | None, None -> ((EBool true, default_pos), TBool) - let process_default (ctxt : Name_resolution.context) (scope : Uid.Scope.t) (def_key : - Uid.ScopeDef.t) (def : Dcalc.Ast.default_term) (param_uid : Uid.LocalVar.t option) (precond : + let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) (def_key + : Ast.ScopeDef.t) (def : Dcalc.Ast.default_term) (param_uid : Ast.LocalVar.t option) (precond : Dcalc.Ast.term option) (just : Surface.Ast.expression Pos.marked option) (body : Surface.Ast.expression Pos.marked) : Dcalc.Ast.default_term = let just = match just with | Some cond -> Some (expr_to_lambda scope (Some def_key) ctxt cond) | None -> None in let condition = @@ -68,36 +68,38 @@ module Errors = Utils.Errors Dcalc.Ast.add_default condition body def *) (* Process a definition *) -let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Uid.Scope.t) +let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) (def : Surface.Ast.definition) : Ast.program = - let scope : Ast.scope = Uid.ScopeMap.find scope_uid prgm in - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in + let scope : Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in - let _param_uid (def_uid : Uid.ScopeDef.t) : Uid.LocalVar.t option = + let _param_uid (def_uid : Ast.ScopeDef.t) : Ast.LocalVar.t option = match def.definition_parameter with | None -> None | Some param -> - let def_ctxt = Uid.ScopeDefMap.find def_uid scope_ctxt.definitions in - Some (Uid.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) + let def_ctxt = Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in + Some (Ast.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) in let def_key = match Pos.unmark def.definition_name with | [ x ] -> let x_uid = Name_resolution.get_var_uid scope_uid ctxt x in - Uid.ScopeDef.Var x_uid + Ast.ScopeDef.Var x_uid | [ y; x ] -> - let subscope_uid : Uid.SubScope.t = Name_resolution.get_subscope_uid scope_uid ctxt y in - let subscope_real_uid : Uid.Scope.t = - Uid.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes + let subscope_uid : Scopelang.Ast.SubScopeName.t = + Name_resolution.get_subscope_uid scope_uid ctxt y + in + let subscope_real_uid : Scopelang.Ast.ScopeName.t = + Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in let x_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in - Uid.ScopeDef.SubScopeVar (subscope_uid, x_uid) + Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid) | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos in let scope_updated = let _x_def = - match Uid.ScopeDefMap.find_opt def_key scope.scope_defs with + match Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def | None -> let _typ = Name_resolution.get_def_typ ctxt def_key in @@ -109,12 +111,12 @@ let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Uid.Scope.t) ctxt scope_uid def_key default (param_uid def_key) precond def.definition_condition def.definition_expr) | _ -> assert false (* should not happen *)) x_def *) in - { scope with scope_defs = Uid.ScopeDefMap.add def_key x_def scope.scope_defs } + { scope with scope_defs = Ast.ScopeDefMap.add def_key x_def scope.scope_defs } in - Uid.ScopeMap.add scope_uid scope_updated prgm + Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm (** Process a rule from the surface language *) -let process_rule (precond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) +let process_rule (precond : Dcalc.Ast.expr option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) (rule : Surface.Ast.rule) : Ast.program = let _consequence_expr = Surface.Ast.Literal (Surface.Ast.Bool (Pos.unmark rule.rule_consequence)) @@ -124,7 +126,7 @@ let process_rule (precond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) Pos.get_position rule.rule_consequence); } in *) process_def precond scope ctxt prgm (assert false (* def *)) -let process_scope_use_item (cond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) +let process_scope_use_item (cond : Dcalc.Ast.expr option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) (item : Surface.Ast.scope_use_item Pos.marked) : Ast.program = match Pos.unmark item with @@ -135,12 +137,12 @@ let process_scope_use_item (cond : Dcalc.Ast.expr option) (scope : Uid.Scope.t) let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) (use : Surface.Ast.scope_use) : Ast.program = let name = fst use.scope_use_name in - let scope_uid = Uid.IdentMap.find name ctxt.scope_idmap in + let scope_uid = Ast.IdentMap.find name ctxt.scope_idmap in (* Make sure the scope exists *) let prgm = - match Uid.ScopeMap.find_opt scope_uid prgm with + match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with | Some _ -> prgm - | None -> Uid.ScopeMap.add scope_uid (Ast.empty_scope scope_uid) prgm + | None -> Scopelang.Ast.ScopeMap.add scope_uid (Ast.empty_scope scope_uid) prgm in let cond = match use.scope_use_condition with @@ -154,7 +156,7 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) (** Scopes processing *) let translate_program_to_scope (_ctxt : Name_resolution.context) (prgm : Surface.Ast.program) : Ast.program = - let empty_prgm = Uid.ScopeMap.empty in + let empty_prgm = Scopelang.Ast.ScopeMap.empty in let processer_article_item (prgm : Ast.program) (item : Surface.Ast.law_article_item) : Ast.program = match item with diff --git a/src/catala/desugared/dune b/src/catala/desugared/dune index 046691fa..48e8bf21 100644 --- a/src/catala/desugared/dune +++ b/src/catala/desugared/dune @@ -1,4 +1,4 @@ (library (name desugared) (public_name catala.desugared) - (libraries utils dcalc ocamlgraph surface)) + (libraries utils dcalc scopelang ocamlgraph surface)) diff --git a/src/catala/desugared/format.ml b/src/catala/desugared/format.ml index 9ad7392e..76d77002 100644 --- a/src/catala/desugared/format.ml +++ b/src/catala/desugared/format.ml @@ -14,10 +14,10 @@ (** Print a scope program *) let print_scope (scope : Ast.scope) : string = - let print_defs (defs : Ast.definition Uid.ScopeDefMap.t) : string = - defs |> Uid.ScopeDefMap.bindings + let print_defs (defs : Ast.definition Ast.ScopeDefMap.t) : string = + defs |> Ast.ScopeDefMap.bindings |> List.map (fun (uid, _term) -> - Printf.sprintf "%s:\n%s" (Uid.ScopeDef.format_t uid) (assert false)) + Printf.sprintf "%s:\n%s" (Ast.ScopeDef.format_t uid) (assert false)) |> String.concat "" in "___Variables Definition___\n" ^ print_defs scope.scope_defs ^ "___Subscope (Re)definition___\n" @@ -25,8 +25,8 @@ let print_scope (scope : Ast.scope) : string = (** Print the whole program *) let print_program (prgm : Ast.program) : string = - prgm |> Uid.ScopeMap.bindings + prgm |> Scopelang.Ast.ScopeMap.bindings |> List.map (fun (uid, scope) -> - Printf.sprintf "Scope %s:\n%s" (Uid.Scope.format_t uid) (print_scope scope)) + Printf.sprintf "Scope %s:\n%s" (Scopelang.Ast.ScopeName.format_t uid) (print_scope scope)) |> String.concat "\n" |> Printf.sprintf "Scope program\n%s" diff --git a/src/catala/desugared/interpreter.ml b/src/catala/desugared/interpreter.ml index d1612a50..1acbeafd 100644 --- a/src/catala/desugared/interpreter.ml +++ b/src/catala/desugared/interpreter.ml @@ -25,20 +25,21 @@ module Errors = Utils.Errors In the graph, x -> y if x is used in the definition of y. *) module Vertex = struct - type t = Var of Uid.Var.t | SubScope of Uid.SubScope.t + type t = Var of Ast.Var.t | SubScope of Scopelang.Ast.SubScopeName.t - let hash x = match x with Var x -> Uid.Var.hash x | SubScope x -> Uid.SubScope.hash x + let hash x = + match x with Var x -> Ast.Var.hash x | SubScope x -> Scopelang.Ast.SubScopeName.hash x let compare = compare let equal x y = match (x, y) with - | Var x, Var y -> Uid.Var.compare x y = 0 - | SubScope x, SubScope y -> Uid.SubScope.compare x y = 0 + | Var x, Var y -> Ast.Var.compare x y = 0 + | SubScope x, SubScope y -> Scopelang.Ast.SubScopeName.compare x y = 0 | _ -> false let format_t (x : t) : string = - match x with Var v -> Uid.Var.format_t v | SubScope v -> Uid.SubScope.format_t v + match x with Var v -> Ast.Var.format_t v | SubScope v -> Scopelang.Ast.SubScopeName.format_t v end (** On the edges, the label is the expression responsible for the use of the variable *) @@ -68,15 +69,16 @@ let check_for_cycle (g : ScopeDependencies.t) : unit = (fun v -> let var_str, var_info = match v with - | Vertex.Var v -> (Uid.Var.format_t v, Uid.Var.get_info v) - | Vertex.SubScope v -> (Uid.SubScope.format_t v, Uid.SubScope.get_info v) + | Vertex.Var v -> (Ast.Var.format_t v, Ast.Var.get_info v) + | Vertex.SubScope v -> + (Scopelang.Ast.SubScopeName.format_t v, Scopelang.Ast.SubScopeName.get_info v) in let succs = ScopeDependencies.succ_e g v in let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in let succ_str = match succ with - | Vertex.Var v -> Uid.Var.format_t v - | Vertex.SubScope v -> Uid.SubScope.format_t v + | Vertex.Var v -> Ast.Var.format_t v + | Vertex.SubScope v -> Scopelang.Ast.SubScopeName.format_t v in [ (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); @@ -90,34 +92,35 @@ let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context let g = ScopeDependencies.empty in let scope_uid = scope.scope_uid in (* Add all the vertices to the graph *) - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let g = - Uid.IdentMap.fold - (fun _ (v : Uid.Var.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) + Ast.IdentMap.fold + (fun _ (v : Ast.Var.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) scope_ctxt.var_idmap g in let g = - Uid.IdentMap.fold - (fun _ (v : Uid.SubScope.t) g -> ScopeDependencies.add_vertex g (Vertex.SubScope v)) + Ast.IdentMap.fold + (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> + ScopeDependencies.add_vertex g (Vertex.SubScope v)) scope_ctxt.sub_scopes_idmap g in let g = - Uid.ScopeDefMap.fold + Ast.ScopeDefMap.fold (fun def_key _def g -> let fv = assert false (* Dcalc.Ast.term_fv def *) in - Uid.ScopeDefSet.fold + Ast.ScopeDefSet.fold (fun fv_def g -> match (def_key, fv_def) with - | Uid.ScopeDef.Var defined, Uid.ScopeDef.Var used -> + | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> (* simple case *) ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) - | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.Var used -> + | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> (* here we are defining the input of a subscope using a var of the scope *) ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) - | Uid.ScopeDef.SubScopeVar (defined, _), Uid.ScopeDef.SubScopeVar (used, _) -> + | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar (used, _) -> (* here we are defining the input of a scope with the output of another subscope *) ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) - | Uid.ScopeDef.Var defined, Uid.ScopeDef.SubScopeVar (used, _) -> + | Ast.ScopeDef.Var defined, Ast.ScopeDef.SubScopeVar (used, _) -> (* finally we define a scope var with the output of a subscope *) ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) fv g) diff --git a/src/catala/desugared/name_resolution.ml b/src/catala/desugared/name_resolution.ml index 2a58c3d9..e7ea5593 100644 --- a/src/catala/desugared/name_resolution.ml +++ b/src/catala/desugared/name_resolution.ml @@ -22,23 +22,23 @@ type ident = string type typ = unit -type def_context = { var_idmap : Uid.LocalVar.t Uid.IdentMap.t } +type def_context = { var_idmap : Ast.LocalVar.t Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern matching *) type scope_context = { - var_idmap : Uid.Var.t Uid.IdentMap.t; - sub_scopes_idmap : Uid.SubScope.t Uid.IdentMap.t; - sub_scopes : Uid.Scope.t Uid.SubScopeMap.t; - definitions : def_context Uid.ScopeDefMap.t; + var_idmap : Ast.Var.t Ast.IdentMap.t; + sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Ast.IdentMap.t; + sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; + definitions : def_context Ast.ScopeDefMap.t; (** Contains the local variables in all the definitions *) } (** Inside a scope, we distinguish between the variables and the subscopes. *) type context = { - scope_idmap : Uid.Scope.t Uid.IdentMap.t; - scopes : scope_context Uid.ScopeMap.t; - var_typs : typ Uid.VarMap.t; + scope_idmap : Scopelang.Ast.ScopeName.t Ast.IdentMap.t; + scopes : scope_context Scopelang.Ast.ScopeMap.t; + var_typs : typ Ast.VarMap.t; } let raise_unsupported_feature (msg : string) (pos : Pos.t) = @@ -50,36 +50,37 @@ let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = (Pos.get_position ident) (** Get the type associated to an uid *) -let get_var_typ (ctxt : context) (uid : Uid.Var.t) : typ = Uid.VarMap.find uid ctxt.var_typs +let get_var_typ (ctxt : context) (uid : Ast.Var.t) : typ = Ast.VarMap.find uid ctxt.var_typs (** Process a subscope declaration *) -let process_subscope_decl (scope : Uid.Scope.t) (ctxt : context) +let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (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 = Uid.ScopeMap.find scope ctxt.scopes in - match Uid.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in + match Ast.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with | Some use -> Errors.raise_multispanned_error "subscope name already used" [ - (Some "first use", Pos.get_position (Uid.SubScope.get_info use)); + (Some "first use", Pos.get_position (Scopelang.Ast.SubScopeName.get_info use)); (Some "second use", s_pos); ] | None -> - let sub_scope_uid = Uid.SubScope.fresh (name, name_pos) in + let sub_scope_uid = Scopelang.Ast.SubScopeName.fresh (name, name_pos) in let original_subscope_uid = - match Uid.IdentMap.find_opt subscope ctxt.scope_idmap with + match Ast.IdentMap.find_opt subscope ctxt.scope_idmap with | None -> raise_unknown_identifier "for a scope" (subscope, s_pos) | Some id -> id in let scope_ctxt = { scope_ctxt with - sub_scopes_idmap = Uid.IdentMap.add name sub_scope_uid scope_ctxt.sub_scopes_idmap; - sub_scopes = Uid.SubScopeMap.add sub_scope_uid original_subscope_uid scope_ctxt.sub_scopes; + sub_scopes_idmap = Ast.IdentMap.add name sub_scope_uid scope_ctxt.sub_scopes_idmap; + sub_scopes = + Scopelang.Ast.SubScopeMap.add sub_scope_uid original_subscope_uid scope_ctxt.sub_scopes; } in - { ctxt with scopes = Uid.ScopeMap.add scope scope_ctxt ctxt.scopes } + { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } let process_base_typ ((typ, typ_pos) : Surface.Ast.base_typ Pos.marked) : Dcalc.Ast.typ Pos.marked = match typ with @@ -102,69 +103,72 @@ let process_type ((typ, typ_pos) : Surface.Ast.typ Pos.marked) : Dcalc.Ast.typ P (Dcalc.Ast.TArrow (process_base_typ arg_typ, process_base_typ return_typ), typ_pos) (** Process data declaration *) -let process_data_decl (scope : Uid.Scope.t) (ctxt : context) +let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Surface.Ast.scope_decl_context_data) : context = (* First check the type of the context data *) let _data_typ = process_type decl.scope_decl_context_item_typ in let name, pos = decl.scope_decl_context_item_name in - let scope_ctxt = Uid.ScopeMap.find scope ctxt.scopes in - match Uid.IdentMap.find_opt name scope_ctxt.var_idmap with + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in + match Ast.IdentMap.find_opt name scope_ctxt.var_idmap with | Some use -> Errors.raise_multispanned_error "var name already used" - [ (Some "first use", Pos.get_position (Uid.Var.get_info use)); (Some "second use", pos) ] + [ (Some "first use", Pos.get_position (Ast.Var.get_info use)); (Some "second use", pos) ] | None -> - let uid = Uid.Var.fresh (name, pos) in + let uid = Ast.Var.fresh (name, pos) in let scope_ctxt = - { scope_ctxt with var_idmap = Uid.IdentMap.add name uid scope_ctxt.var_idmap } + { scope_ctxt with var_idmap = Ast.IdentMap.add name uid scope_ctxt.var_idmap } in { ctxt with - scopes = Uid.ScopeMap.add scope scope_ctxt ctxt.scopes; - var_typs = assert false (* Uid.VarMap.add uid data_typ ctxt.var_typs *); + scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes; + var_typs = assert false (* Ast.VarMap.add uid data_typ ctxt.var_typs *); } (** Process an item declaration *) -let process_item_decl (scope : Uid.Scope.t) (ctxt : context) +let process_item_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Surface.Ast.scope_decl_context_item) : context = match decl with | Surface.Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl | Surface.Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl (** Adds a binding to the context *) -let add_def_local_var (ctxt : context) (scope_uid : Uid.Scope.t) (def_uid : Uid.ScopeDef.t) - (name : ident Pos.marked) : context = - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in - let def_ctx = Uid.ScopeDefMap.find def_uid scope_ctxt.definitions in - let local_var_uid = Uid.LocalVar.fresh name in +let add_def_local_var (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) + (def_uid : Ast.ScopeDef.t) (name : ident Pos.marked) : context = + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + let def_ctx = Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in + let local_var_uid = Ast.LocalVar.fresh name in let def_ctx = - { var_idmap = Uid.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } + { var_idmap = Ast.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } in let scope_ctxt = - { scope_ctxt with definitions = Uid.ScopeDefMap.add def_uid def_ctx scope_ctxt.definitions } + { scope_ctxt with definitions = Ast.ScopeDefMap.add def_uid def_ctx scope_ctxt.definitions } in - { ctxt with scopes = Uid.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } + { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } (** Process a scope declaration *) let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : context = let name, pos = decl.scope_decl_name in (* Checks if the name is already used *) - match Uid.IdentMap.find_opt name ctxt.scope_idmap with + match Ast.IdentMap.find_opt name ctxt.scope_idmap with | Some use -> Errors.raise_multispanned_error "scope name already used" - [ (Some "first use", Pos.get_position (Uid.Scope.get_info use)); (Some "second use", pos) ] + [ + (Some "first use", Pos.get_position (Scopelang.Ast.ScopeName.get_info use)); + (Some "second use", pos); + ] | None -> - let scope_uid = Uid.Scope.fresh (name, pos) in + let scope_uid = Scopelang.Ast.ScopeName.fresh (name, pos) in let ctxt = { ctxt with - scope_idmap = Uid.IdentMap.add name scope_uid ctxt.scope_idmap; + scope_idmap = Ast.IdentMap.add name scope_uid ctxt.scope_idmap; scopes = - Uid.ScopeMap.add scope_uid + Scopelang.Ast.ScopeMap.add scope_uid { - var_idmap = Uid.IdentMap.empty; - sub_scopes_idmap = Uid.IdentMap.empty; - definitions = Uid.ScopeDefMap.empty; - sub_scopes = Uid.SubScopeMap.empty; + var_idmap = Ast.IdentMap.empty; + sub_scopes_idmap = Ast.IdentMap.empty; + definitions = Ast.ScopeDefMap.empty; + sub_scopes = Scopelang.Ast.SubScopeMap.empty; } ctxt.scopes; } @@ -173,30 +177,30 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : contex (fun ctxt item -> process_item_decl scope_uid ctxt (Pos.unmark item)) ctxt decl.scope_decl_context -let qident_to_scope_def (ctxt : context) (scope_uid : Uid.Scope.t) - (id : Surface.Ast.qident Pos.marked) : Uid.ScopeDef.t = - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in +let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) + (id : Surface.Ast.qident Pos.marked) : Ast.ScopeDef.t = + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in match Pos.unmark id with | [ x ] -> ( - match Uid.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with + match Ast.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with | None -> raise_unknown_identifier "for a var of the scope" x - | Some id -> Uid.ScopeDef.Var id ) + | Some id -> Ast.ScopeDef.Var id ) | [ s; x ] -> ( let sub_scope_uid = - match Uid.IdentMap.find_opt (Pos.unmark s) scope_ctxt.sub_scopes_idmap with + match Ast.IdentMap.find_opt (Pos.unmark s) scope_ctxt.sub_scopes_idmap with | None -> raise_unknown_identifier "for a subscope of this scope" s | Some id -> id in - let real_sub_scope_uid = Uid.SubScopeMap.find sub_scope_uid scope_ctxt.sub_scopes in - let sub_scope_ctx = Uid.ScopeMap.find real_sub_scope_uid ctxt.scopes in - match Uid.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with + let real_sub_scope_uid = Scopelang.Ast.SubScopeMap.find sub_scope_uid scope_ctxt.sub_scopes in + let sub_scope_ctx = Scopelang.Ast.ScopeMap.find real_sub_scope_uid ctxt.scopes in + match Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with | None -> raise_unknown_identifier "for a var of this subscope" x - | Some id -> Uid.ScopeDef.SubScopeVar (sub_scope_uid, id) ) + | Some id -> Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) | _ -> raise_unsupported_feature "wrong qident" (Pos.get_position id) let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = let scope_uid = - match Uid.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with + match Ast.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with | None -> raise_unknown_identifier "for a scope" use.scope_use_name | Some id -> id in @@ -204,24 +208,24 @@ let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = (fun ctxt use_item -> match Pos.unmark use_item with | Surface.Ast.Definition def -> - let scope_ctxt = Uid.ScopeMap.find scope_uid ctxt.scopes in + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let def_uid = qident_to_scope_def ctxt scope_uid def.definition_name in let def_ctxt = { var_idmap = ( match def.definition_parameter with - | None -> Uid.IdentMap.empty - | Some param -> Uid.IdentMap.singleton (Pos.unmark param) (Uid.LocalVar.fresh param) + | None -> Ast.IdentMap.empty + | Some param -> Ast.IdentMap.singleton (Pos.unmark param) (Ast.LocalVar.fresh param) ); } in let scope_ctxt = { scope_ctxt with - definitions = Uid.ScopeDefMap.add def_uid def_ctxt scope_ctxt.definitions; + definitions = Ast.ScopeDefMap.add def_uid def_ctxt scope_ctxt.definitions; } in - { ctxt with scopes = Uid.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } + { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } | _ -> raise_unsupported_feature "unsupported item" (Pos.get_position use_item)) ctxt use.scope_use_items @@ -268,7 +272,11 @@ let process_program_item (ctxt : context) (item : Surface.Ast.program_item) (** Derive the context from metadata, in two passes *) let form_context (prgm : Surface.Ast.program) : context = let empty_ctxt = - { scope_idmap = Uid.IdentMap.empty; scopes = Uid.ScopeMap.empty; var_typs = Uid.VarMap.empty } + { + scope_idmap = Ast.IdentMap.empty; + scopes = Scopelang.Ast.ScopeMap.empty; + var_typs = Ast.VarMap.empty; + } in let ctxt = List.fold_left @@ -280,30 +288,30 @@ let form_context (prgm : Surface.Ast.program) : context = ctxt prgm.program_items (** Get the variable uid inside the scope given in argument *) -let get_var_uid (scope_uid : Uid.Scope.t) (ctxt : context) ((x, pos) : ident Pos.marked) : Uid.Var.t - = - let scope = Uid.ScopeMap.find scope_uid ctxt.scopes in - match Uid.IdentMap.find_opt x scope.var_idmap with +let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) + ((x, pos) : ident Pos.marked) : Ast.Var.t = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + match Ast.IdentMap.find_opt x scope.var_idmap with | None -> raise_unknown_identifier "for a var of this scope" (x, pos) | Some uid -> uid (** Get the subscope uid inside the scope given in argument *) -let get_subscope_uid (scope_uid : Uid.Scope.t) (ctxt : context) ((y, pos) : ident Pos.marked) : - Uid.SubScope.t = - let scope = Uid.ScopeMap.find scope_uid ctxt.scopes in - match Uid.IdentMap.find_opt y scope.sub_scopes_idmap with +let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) + ((y, pos) : ident Pos.marked) : Scopelang.Ast.SubScopeName.t = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + match Ast.IdentMap.find_opt y scope.sub_scopes_idmap with | None -> raise_unknown_identifier "for a subscope of this scope" (y, pos) | Some sub_uid -> sub_uid (** Checks if the var_uid belongs to the scope scope_uid *) -let belongs_to (ctxt : context) (uid : Uid.Var.t) (scope_uid : Uid.Scope.t) : bool = - let scope = Uid.ScopeMap.find scope_uid ctxt.scopes in - Uid.IdentMap.exists (fun _ var_uid -> Uid.Var.compare uid var_uid = 0) scope.var_idmap +let belongs_to (ctxt : context) (uid : Ast.Var.t) (scope_uid : Scopelang.Ast.ScopeName.t) : bool = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + Ast.IdentMap.exists (fun _ var_uid -> Ast.Var.compare uid var_uid = 0) scope.var_idmap -let get_def_typ (ctxt : context) (def : Uid.ScopeDef.t) : typ = +let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ = match def with - | Uid.ScopeDef.SubScopeVar (_, x) + | Ast.ScopeDef.SubScopeVar (_, x) (* we don't need to look at the subscope prefix because [x] is already the uid referring back to the original subscope *) - | Uid.ScopeDef.Var x -> - Uid.VarMap.find x ctxt.var_typs + | Ast.ScopeDef.Var x -> + Ast.VarMap.find x ctxt.var_typs diff --git a/src/catala/desugared/uid.ml b/src/catala/desugared/uid.ml deleted file mode 100644 index 3107be91..00000000 --- a/src/catala/desugared/uid.ml +++ /dev/null @@ -1,54 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux - - - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the License - is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - or implied. See the License for the specific language governing permissions and limitations under - the License. *) - -open Utils.Uid -module Pos = Utils.Pos -module Orig = Utils.Uid -module IdentMap = Map.Make (String) -module Scope = Make (MarkedString) -module ScopeSet = Set.Make (Scope) -module ScopeMap = Map.Make (Scope) -module Var = Make (MarkedString) -module VarSet = Set.Make (Var) -module VarMap = Map.Make (Var) -module LocalVar = Make (MarkedString) -module LocalVarSet = Set.Make (LocalVar) -module LocalVarMap = Map.Make (LocalVar) -module SubScope = Make (MarkedString) -module SubScopeSet = Set.Make (SubScope) -module SubScopeMap = Map.Make (SubScope) - -(** Inside a scope, a definition can refer either to a scope def, or a subscope def *) -module ScopeDef = struct - type t = - | Var of Var.t - | SubScopeVar of SubScope.t * Var.t - (** In this case, the [Uid.Var.t] lives inside the context of the subscope's original - declaration *) - - let compare x y = - match (x, y) with - | Var x, Var y | Var x, SubScopeVar (_, y) | SubScopeVar (_, x), Var y -> Var.compare x y - | SubScopeVar (_, x), SubScopeVar (_, y) -> SubScope.compare x y - - let format_t x = - match x with - | Var v -> Var.format_t v - | SubScopeVar (s, v) -> Printf.sprintf "%s.%s" (SubScope.format_t s) (Var.format_t v) - - let hash x = match x with Var v -> Var.hash v | SubScopeVar (_, v) -> Var.hash v -end - -module ScopeDefMap = Map.Make (ScopeDef) -module ScopeDefSet = Set.Make (ScopeDef) diff --git a/src/catala/desugared/uid.mli b/src/catala/desugared/uid.mli deleted file mode 100644 index e897de35..00000000 --- a/src/catala/desugared/uid.mli +++ /dev/null @@ -1,60 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux - - - 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. *) - -module Pos = Utils.Pos -module Orig = Utils.Uid - -module IdentMap : Map.S with type key = String.t - -module Scope : Orig.Id with type info = Orig.MarkedString.info - -module ScopeSet : Set.S with type elt = Scope.t - -module ScopeMap : Map.S with type key = Scope.t - -module Var : Orig.Id with type info = Orig.MarkedString.info - -module VarSet : Set.S with type elt = Var.t - -module VarMap : Map.S with type key = Var.t - -module LocalVar : Orig.Id with type info = Orig.MarkedString.info - -module LocalVarSet : Set.S with type elt = LocalVar.t - -module LocalVarMap : Map.S with type key = LocalVar.t - -module SubScope : Orig.Id with type info = Orig.MarkedString.info - -module SubScopeSet : Set.S with type elt = SubScope.t - -module SubScopeMap : Map.S with type key = SubScope.t - -module ScopeDef : sig - type t = - | Var of Var.t - | SubScopeVar of SubScope.t * Var.t - (** In this case, the [Uid.Var.t] lives inside the context of the subscope's original - declaration *) - - val compare : t -> t -> int - - val format_t : t -> string - - val hash : t -> int -end - -module ScopeDefMap : Map.S with type key = ScopeDef.t - -module ScopeDefSet : Set.S with type elt = ScopeDef.t diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 91d44658..fd44497a 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -101,7 +101,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ match ex_scope with | None -> Errors.raise_error "No scope was provided for execution." | Some name -> ( - match Desugared.Uid.IdentMap.find_opt name ctxt.scope_idmap with + match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with | None -> Errors.raise_error (Printf.sprintf "There is no scope %s inside the program." name) @@ -109,10 +109,10 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ in let prgm = Desugared.Desugaring.translate_program_to_scope ctxt program in let _scope = - match Desugared.Uid.ScopeMap.find_opt scope_uid prgm with + match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with | Some scope -> scope | None -> - let scope_info = Desugared.Uid.Scope.get_info scope_uid in + let scope_info = Scopelang.Ast.ScopeName.get_info scope_uid in Errors.raise_spanned_error (Printf.sprintf "Scope %s does not define anything, and therefore cannot be executed" diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 7139d599..a8ba1f1c 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -13,3 +13,10 @@ the License. *) module Pos = Utils.Pos +module Uid = Utils.Uid +module ScopeName = Uid.Make (Uid.MarkedString) +module ScopeNameSet = Set.Make (ScopeName) +module ScopeMap = Map.Make (ScopeName) +module SubScopeName = Uid.Make (Uid.MarkedString) +module SubScopeNameSet = Set.Make (SubScopeName) +module SubScopeMap = Map.Make (SubScopeName) diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune index f4d9414d..d0e89810 100644 --- a/src/catala/scope_language/dune +++ b/src/catala/scope_language/dune @@ -1,4 +1,4 @@ (library - (name scope) - (public_name catala.scope) + (name scopelang) + (public_name catala.scopelang) (libraries utils dcalc)) From 35dcd57b2be6ad8aedf08853bef583cf6dd573d8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 16:12:45 +0100 Subject: [PATCH 011/142] Added tuples to default calculus --- src/catala/default_calculus/ast.ml | 8 +- src/catala/default_calculus/interpreter.ml | 117 +++++++++++--------- src/catala/default_calculus/typing.ml | 51 +++++++++ src/catala/desugared/ast.ml | 21 ++-- src/catala/desugared/interpreter.ml | 19 ++-- src/catala/desugared/name_resolution.ml | 29 +++-- src/catala/scope_language/ast.ml | 19 ++++ src/catala/scope_language/scope_to_dcalc.ml | 32 ++++++ 8 files changed, 217 insertions(+), 79 deletions(-) create mode 100644 src/catala/scope_language/scope_to_dcalc.ml diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index e105180c..a0cd9dc6 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -14,12 +14,18 @@ module Pos = Utils.Pos -type typ = TBool | TUnit | TArrow of typ Pos.marked * typ Pos.marked +type typ = + | TBool + | TUnit + | TTuple of typ Pos.marked list + | TArrow of typ Pos.marked * typ Pos.marked type lit = LTrue | LFalse | LEmptyError type expr = | EVar of expr Pos.marked Bindlib.var + | ETuple of expr Pos.marked list + | ETupleAccess of expr Pos.marked * int | ELit of lit | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * typ | EApp of expr Pos.marked * expr Pos.marked diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 558f3150..adab99d6 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -16,58 +16,73 @@ module Pos = Utils.Pos module Errors = Utils.Errors module A = Ast -let is_value (e : A.expr Pos.marked) : bool = - match Pos.unmark e with A.EAbs _ | ELit _ -> true | _ -> false - let is_empty_error (e : A.expr Pos.marked) : bool = match Pos.unmark e with ELit LEmptyError -> true | _ -> false let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = - if is_value e then e - else - match Pos.unmark e with - | EVar _ -> - Errors.raise_spanned_error - "Free variable found at evaluation (should not happen if term was well-typed" - (Pos.get_position e) - | EApp (e1, e2) -> ( - let e1 = evaluate_expr e1 in - let e2 = evaluate_expr e2 in - match Pos.unmark e1 with - | EAbs (_, binder, _) -> evaluate_expr (Bindlib.subst binder e2) - | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e - | _ -> - Errors.raise_spanned_error - "Function has not been reduced to a lambda at evaluation (should not happen if the \ - term was well-typed" - (Pos.get_position e) ) - | EAbs _ | ELit _ -> assert false (* should not happen because the remaining cases are values *) - | EDefault (just, cons, subs) -> ( - let just = evaluate_expr just in - match Pos.unmark just with - | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e - | ELit LTrue -> evaluate_expr cons - | ELit LFalse -> ( - let subs = List.map evaluate_expr subs in - let empty_count = List.length (List.filter is_empty_error subs) in - match List.length subs - empty_count with - | 0 -> Pos.same_pos_as (A.ELit LEmptyError) e - | 1 -> List.find (fun sub -> not (is_empty_error sub)) subs - | _ -> - Errors.raise_multispanned_error - "There is a conflict between multiple rules for assigning a single value." - ( [ - ( Some "This rule is not triggered, so we consider rules of lower priority:", - Pos.get_position e ); - ] - @ List.map - (fun sub -> - ( Some - "This value is available because the justification of its rule is true:", - Pos.get_position sub )) - (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) - | _ -> - Errors.raise_spanned_error - "Default justification has not been reduced to a boolean at evaluation (should not \ - happen if the term was well-typed" - (Pos.get_position e) ) + match Pos.unmark e with + | EVar _ -> + Errors.raise_spanned_error + "free variable found at evaluation (should not happen if term was well-typed" + (Pos.get_position e) + | EApp (e1, e2) -> ( + let e1 = evaluate_expr e1 in + let e2 = evaluate_expr e2 in + match Pos.unmark e1 with + | EAbs (_, binder, _) -> evaluate_expr (Bindlib.subst binder e2) + | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e + | _ -> + Errors.raise_spanned_error + "function has not been reduced to a lambda at evaluation (should not happen if the \ + term was well-typed" + (Pos.get_position e) ) + | EAbs _ | ELit _ -> e (* thse are values *) + | ETuple es -> Pos.same_pos_as (A.ETuple (List.map evaluate_expr es)) e + | ETupleAccess (e1, n) -> ( + let e1 = evaluate_expr e1 in + match Pos.unmark e1 with + | ETuple es -> ( + match List.nth_opt es n with + | Some e' -> e' + | None -> + Errors.raise_spanned_error + (Format.asprintf + "the tuple has %d components but the %i-th element was requested (should not \ + happen if the term was well-type)" + (List.length es) n) + (Pos.get_position e1) ) + | _ -> + Errors.raise_spanned_error + (Format.asprintf + "the expression should be a tuple with %d components but is not (should not happen \ + if the term was well-typed)" + n) + (Pos.get_position e1) ) + | EDefault (just, cons, subs) -> ( + let just = evaluate_expr just in + match Pos.unmark just with + | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e + | ELit LTrue -> evaluate_expr cons + | ELit LFalse -> ( + let subs = List.map evaluate_expr subs in + let empty_count = List.length (List.filter is_empty_error subs) in + match List.length subs - empty_count with + | 0 -> Pos.same_pos_as (A.ELit LEmptyError) e + | 1 -> List.find (fun sub -> not (is_empty_error sub)) subs + | _ -> + Errors.raise_multispanned_error + "there is a conflict between multiple rules for assigning a single value." + ( [ + ( Some "This rule is not triggered, so we consider rules of lower priority:", + Pos.get_position e ); + ] + @ List.map + (fun sub -> + ( Some "This value is available because the justification of its rule is true:", + Pos.get_position sub )) + (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) + | _ -> + Errors.raise_spanned_error + "Default justification has not been reduced to a boolean at evaluation (should not \ + happen if the term was well-typed" + (Pos.get_position e) ) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index a27dbeb0..e91e61af 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -23,6 +23,7 @@ type typ = | TUnit | TBool | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem + | TTuple of typ Pos.marked UnionFind.elem list | TAny let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = @@ -31,6 +32,10 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TAny -> Format.fprintf fmt "any" + | TTuple ts -> + Format.fprintf fmt "(%a)" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) + ts | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = @@ -41,6 +46,7 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> unify t11 t21; unify t12 t22 + | (TTuple ts1, _), (TTuple ts2, _) -> List.iter2 unify ts1 ts2 | (TAny, _), (TAny, _) -> ignore (UnionFind.union t1 t2) | (TAny, _), t_repr | t_repr, (TAny, _) -> let t_union = UnionFind.union t1 t2 in @@ -62,6 +68,7 @@ let rec ast_to_typ (ty : A.typ) : typ = TArrow ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), UnionFind.make (Pos.map_under_mark ast_to_typ t2) ) + | A.TTuple ts -> TTuple (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = Pos.map_under_mark @@ -69,6 +76,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = match ty with | TUnit -> A.TUnit | TBool -> A.TBool + | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) | TAny -> A.TUnit) (UnionFind.get (UnionFind.find ty)) @@ -86,6 +94,25 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m (Pos.get_position e) ) | ELit (LTrue | LFalse) -> UnionFind.make (Pos.same_pos_as TBool e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) + | ETuple es -> + let ts = List.map (typecheck_expr_bottom_up env) es in + UnionFind.make (Pos.same_pos_as (TTuple ts) e) + | ETupleAccess (e1, n) -> ( + let t1 = typecheck_expr_bottom_up env e1 in + match Pos.unmark (UnionFind.get (UnionFind.find t1)) with + | TTuple ts -> ( + match List.nth_opt ts n with + | Some t' -> t' + | None -> + Errors.raise_spanned_error + (Format.asprintf + "expression should have a tuple type with at least %d elements but only has %d" n + (List.length ts)) + (Pos.get_position e1) ) + | _ -> + Errors.raise_spanned_error + (Format.asprintf "exprected a tuple, got a %a" format_typ t1) + (Pos.get_position e1) ) | EAbs (pos_binder, binder, tau) -> let x, body = Bindlib.unbind binder in let env = A.VarMap.add x (ast_to_typ tau, pos_binder) env in @@ -113,6 +140,30 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (Pos.get_position e) ) | ELit (LTrue | LFalse) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) + | ETuple es -> ( + let tau' = UnionFind.get (UnionFind.find tau) in + match Pos.unmark tau' with + | TTuple ts -> List.iter2 (typecheck_expr_top_down env) es ts + | _ -> + Errors.raise_spanned_error + (Format.asprintf "exprected %a, got a tuple" format_typ tau) + (Pos.get_position e) ) + | ETupleAccess (e1, n) -> ( + let t1 = typecheck_expr_bottom_up env e1 in + match Pos.unmark (UnionFind.get (UnionFind.find t1)) with + | TTuple t1s -> ( + match List.nth_opt t1s n with + | Some t1n -> unify t1n tau + | None -> + Errors.raise_spanned_error + (Format.asprintf + "expression should have a tuple type with at least %d elements but only has %d" n + (List.length t1s)) + (Pos.get_position e1) ) + | _ -> + Errors.raise_spanned_error + (Format.asprintf "exprected a tuple , got %a" format_typ tau) + (Pos.get_position e) ) | EAbs (pos_binder, binder, t_arg) -> let x, body = Bindlib.unbind binder in let env = A.VarMap.add x (ast_to_typ t_arg, pos_binder) env in diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index d328385d..73d52ded 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -15,9 +15,6 @@ module Pos = Utils.Pos module Uid = Utils.Uid module IdentMap = Map.Make (String) -module Var = Uid.Make (Uid.MarkedString) -module VarSet = Set.Make (Var) -module VarMap = Map.Make (Var) module LocalVar = Uid.Make (Uid.MarkedString) module LocalVarSet = Set.Make (LocalVar) module LocalVarMap = Map.Make (LocalVar) @@ -25,23 +22,29 @@ module LocalVarMap = Map.Make (LocalVar) (** Inside a scope, a definition can refer either to a scope def, or a subscope def *) module ScopeDef = struct type t = - | Var of Var.t - | SubScopeVar of Scopelang.Ast.SubScopeName.t * Var.t + | Var of Scopelang.Ast.ScopeVar.t + | SubScopeVar of Scopelang.Ast.SubScopeName.t * Scopelang.Ast.ScopeVar.t (** In this case, the [Uid.Var.t] lives inside the context of the subscope's original declaration *) let compare x y = match (x, y) with - | Var x, Var y | Var x, SubScopeVar (_, y) | SubScopeVar (_, x), Var y -> Var.compare x y + | Var x, Var y | Var x, SubScopeVar (_, y) | SubScopeVar (_, x), Var y -> + Scopelang.Ast.ScopeVar.compare x y | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.SubScopeName.compare x y let format_t x = match x with - | Var v -> Var.format_t v + | Var v -> Scopelang.Ast.ScopeVar.format_t v | SubScopeVar (s, v) -> - Printf.sprintf "%s.%s" (Scopelang.Ast.SubScopeName.format_t s) (Var.format_t v) + Printf.sprintf "%s.%s" + (Scopelang.Ast.SubScopeName.format_t s) + (Scopelang.Ast.ScopeVar.format_t v) - let hash x = match x with Var v -> Var.hash v | SubScopeVar (_, v) -> Var.hash v + let hash x = + match x with + | Var v -> Scopelang.Ast.ScopeVar.hash v + | SubScopeVar (_, v) -> Scopelang.Ast.ScopeVar.hash v end module ScopeDefMap = Map.Make (ScopeDef) diff --git a/src/catala/desugared/interpreter.ml b/src/catala/desugared/interpreter.ml index 1acbeafd..66b5e10a 100644 --- a/src/catala/desugared/interpreter.ml +++ b/src/catala/desugared/interpreter.ml @@ -25,21 +25,25 @@ module Errors = Utils.Errors In the graph, x -> y if x is used in the definition of y. *) module Vertex = struct - type t = Var of Ast.Var.t | SubScope of Scopelang.Ast.SubScopeName.t + type t = Var of Scopelang.Ast.ScopeVar.t | SubScope of Scopelang.Ast.SubScopeName.t let hash x = - match x with Var x -> Ast.Var.hash x | SubScope x -> Scopelang.Ast.SubScopeName.hash x + match x with + | Var x -> Scopelang.Ast.ScopeVar.hash x + | SubScope x -> Scopelang.Ast.SubScopeName.hash x let compare = compare let equal x y = match (x, y) with - | Var x, Var y -> Ast.Var.compare x y = 0 + | Var x, Var y -> Scopelang.Ast.ScopeVar.compare x y = 0 | SubScope x, SubScope y -> Scopelang.Ast.SubScopeName.compare x y = 0 | _ -> false let format_t (x : t) : string = - match x with Var v -> Ast.Var.format_t v | SubScope v -> Scopelang.Ast.SubScopeName.format_t v + match x with + | Var v -> Scopelang.Ast.ScopeVar.format_t v + | SubScope v -> Scopelang.Ast.SubScopeName.format_t v end (** On the edges, the label is the expression responsible for the use of the variable *) @@ -69,7 +73,8 @@ let check_for_cycle (g : ScopeDependencies.t) : unit = (fun v -> let var_str, var_info = match v with - | Vertex.Var v -> (Ast.Var.format_t v, Ast.Var.get_info v) + | Vertex.Var v -> + (Scopelang.Ast.ScopeVar.format_t v, Scopelang.Ast.ScopeVar.get_info v) | Vertex.SubScope v -> (Scopelang.Ast.SubScopeName.format_t v, Scopelang.Ast.SubScopeName.get_info v) in @@ -77,7 +82,7 @@ let check_for_cycle (g : ScopeDependencies.t) : unit = let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in let succ_str = match succ with - | Vertex.Var v -> Ast.Var.format_t v + | Vertex.Var v -> Scopelang.Ast.ScopeVar.format_t v | Vertex.SubScope v -> Scopelang.Ast.SubScopeName.format_t v in [ @@ -95,7 +100,7 @@ let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let g = Ast.IdentMap.fold - (fun _ (v : Ast.Var.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) + (fun _ (v : Scopelang.Ast.ScopeVar.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) scope_ctxt.var_idmap g in let g = diff --git a/src/catala/desugared/name_resolution.ml b/src/catala/desugared/name_resolution.ml index e7ea5593..7fc3b447 100644 --- a/src/catala/desugared/name_resolution.ml +++ b/src/catala/desugared/name_resolution.ml @@ -27,7 +27,7 @@ type def_context = { var_idmap : Ast.LocalVar.t Ast.IdentMap.t } matching *) type scope_context = { - var_idmap : Ast.Var.t Ast.IdentMap.t; + var_idmap : Scopelang.Ast.ScopeVar.t Ast.IdentMap.t; sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Ast.IdentMap.t; sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; definitions : def_context Ast.ScopeDefMap.t; @@ -38,7 +38,7 @@ type scope_context = { type context = { scope_idmap : Scopelang.Ast.ScopeName.t Ast.IdentMap.t; scopes : scope_context Scopelang.Ast.ScopeMap.t; - var_typs : typ Ast.VarMap.t; + var_typs : typ Scopelang.Ast.ScopeVarMap.t; } let raise_unsupported_feature (msg : string) (pos : Pos.t) = @@ -50,7 +50,8 @@ let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = (Pos.get_position ident) (** Get the type associated to an uid *) -let get_var_typ (ctxt : context) (uid : Ast.Var.t) : typ = Ast.VarMap.find uid ctxt.var_typs +let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ = + Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs (** Process a subscope declaration *) let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) @@ -112,16 +113,19 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) match Ast.IdentMap.find_opt name scope_ctxt.var_idmap with | Some use -> Errors.raise_multispanned_error "var name already used" - [ (Some "first use", Pos.get_position (Ast.Var.get_info use)); (Some "second use", pos) ] + [ + (Some "first use", Pos.get_position (Scopelang.Ast.ScopeVar.get_info use)); + (Some "second use", pos); + ] | None -> - let uid = Ast.Var.fresh (name, pos) in + let uid = Scopelang.Ast.ScopeVar.fresh (name, pos) in let scope_ctxt = { scope_ctxt with var_idmap = Ast.IdentMap.add name uid scope_ctxt.var_idmap } in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes; - var_typs = assert false (* Ast.VarMap.add uid data_typ ctxt.var_typs *); + var_typs = assert false (* Scopelang.Ast.ScopeVarMap.add uid data_typ ctxt.var_typs *); } (** Process an item declaration *) @@ -275,7 +279,7 @@ let form_context (prgm : Surface.Ast.program) : context = { scope_idmap = Ast.IdentMap.empty; scopes = Scopelang.Ast.ScopeMap.empty; - var_typs = Ast.VarMap.empty; + var_typs = Scopelang.Ast.ScopeVarMap.empty; } in let ctxt = @@ -289,7 +293,7 @@ let form_context (prgm : Surface.Ast.program) : context = (** Get the variable uid inside the scope given in argument *) let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) - ((x, pos) : ident Pos.marked) : Ast.Var.t = + ((x, pos) : ident Pos.marked) : Scopelang.Ast.ScopeVar.t = let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in match Ast.IdentMap.find_opt x scope.var_idmap with | None -> raise_unknown_identifier "for a var of this scope" (x, pos) @@ -304,9 +308,12 @@ let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) | Some sub_uid -> sub_uid (** Checks if the var_uid belongs to the scope scope_uid *) -let belongs_to (ctxt : context) (uid : Ast.Var.t) (scope_uid : Scopelang.Ast.ScopeName.t) : bool = +let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) + (scope_uid : Scopelang.Ast.ScopeName.t) : bool = let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - Ast.IdentMap.exists (fun _ var_uid -> Ast.Var.compare uid var_uid = 0) scope.var_idmap + Ast.IdentMap.exists + (fun _ var_uid -> Scopelang.Ast.ScopeVar.compare uid var_uid = 0) + scope.var_idmap let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ = match def with @@ -314,4 +321,4 @@ let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ = (* we don't need to look at the subscope prefix because [x] is already the uid referring back to the original subscope *) | Ast.ScopeDef.Var x -> - Ast.VarMap.find x ctxt.var_typs + Scopelang.Ast.ScopeVarMap.find x ctxt.var_typs diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index a8ba1f1c..7e8c7438 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -20,3 +20,22 @@ module ScopeMap = Map.Make (ScopeName) module SubScopeName = Uid.Make (Uid.MarkedString) module SubScopeNameSet = Set.Make (SubScopeName) module SubScopeMap = Map.Make (SubScopeName) +module ScopeVar = Uid.Make (Uid.MarkedString) +module ScopeVarSet = Set.Make (ScopeVar) +module ScopeVarMap = Map.Make (ScopeVar) + +type location = ScopeVar of ScopeVar.t | SubScopeVar of ScopeName.t * SubScopeName.t * ScopeVar.t + +type expr = + | ELocation of location + | EVar of expr Pos.marked Bindlib.var + | ELit of Dcalc.Ast.lit + | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * Dcalc.Ast.typ + | EApp of expr Pos.marked * expr Pos.marked + | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + +type rule = Definition of location * Dcalc.Ast.typ * expr | Call of ScopeName.t * SubScopeName.t + +type scope_decl = { scope_decl_name : ScopeName.t; scope_decl_rules : rule list } + +type program = scope_decl ScopeMap.t diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml new file mode 100644 index 00000000..9fb8a0ff --- /dev/null +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -0,0 +1,32 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module Pos = Utils.Pos + +type ctx = Ast.location list + +type scope_ctx = Dcalc.Ast.Var.t Ast.ScopeMap.t + +let hole_var : Dcalc.Ast.Var.t = Bindlib.new_var (fun x -> (Dcalc.Ast.EVar x, Pos.no_pos)) "hole" + +let translate_rules (_p : scope_ctx) (_ctx : ctx) (_rules : Ast.rule list) : Dcalc.Ast.expr * ctx = + assert false + +let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr = + let ctx = [] in + let _defs, ctx = translate_rules p ctx sigma.scope_decl_rules in + let _scope_variables = + List.filter_map (fun l -> match l with Ast.ScopeVar v -> Some v | _ -> None) ctx + in + assert false From 6232dd9f02b9f9cb546b856e0e85db5d469a0b28 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 18:51:06 +0100 Subject: [PATCH 012/142] Git added translation (missing subs-scope-related rules) --- src/catala/default_calculus/ast.ml | 13 +++ src/catala/scope_language/ast.ml | 19 +++- src/catala/scope_language/scope_to_dcalc.ml | 117 ++++++++++++++++++-- 3 files changed, 137 insertions(+), 12 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index a0cd9dc6..abd7e06f 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -34,9 +34,22 @@ type expr = module Var = struct type t = expr Pos.marked Bindlib.var + let make (s : string Pos.marked) = + Bindlib.new_var (fun x -> (EVar x, Pos.get_position s)) (Pos.unmark s) + let compare x y = Bindlib.compare_vars x y end module VarMap = Map.Make (Var) +let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x + +let make_abs (x : Var.t) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (tau : typ) + (pos : Pos.t) : expr Pos.marked Bindlib.box = + Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, tau), pos)) (Bindlib.bind_var x e) + +let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box) (pos : Pos.t) : + expr Pos.marked Bindlib.box = + Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e u + type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 7e8c7438..903afce8 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -24,7 +24,9 @@ module ScopeVar = Uid.Make (Uid.MarkedString) module ScopeVarSet = Set.Make (ScopeVar) module ScopeVarMap = Map.Make (ScopeVar) -type location = ScopeVar of ScopeVar.t | SubScopeVar of ScopeName.t * SubScopeName.t * ScopeVar.t +type location = + | ScopeVar of ScopeVar.t Pos.marked + | SubScopeVar of ScopeName.t * SubScopeName.t Pos.marked * ScopeVar.t Pos.marked type expr = | ELocation of location @@ -34,7 +36,20 @@ type expr = | EApp of expr Pos.marked * expr Pos.marked | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list -type rule = Definition of location * Dcalc.Ast.typ * expr | Call of ScopeName.t * SubScopeName.t +module Var = struct + type t = expr Pos.marked Bindlib.var + + let make (s : string Pos.marked) = + Bindlib.new_var (fun x -> (EVar x, Pos.get_position s)) (Pos.unmark s) + + let compare x y = Bindlib.compare_vars x y +end + +module VarMap = Map.Make (Var) + +type rule = + | Definition of location * Dcalc.Ast.typ * expr Pos.marked + | Call of ScopeName.t * SubScopeName.t type scope_decl = { scope_decl_name : ScopeName.t; scope_decl_rules : rule list } diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 9fb8a0ff..9daaf970 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -13,20 +13,117 @@ the License. *) module Pos = Utils.Pos +module Errors = Utils.Errors -type ctx = Ast.location list +type ctx = { + scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; + subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; + local_vars : Dcalc.Ast.Var.t Ast.VarMap.t; +} + +let empty_ctx = + { + scope_vars = Ast.ScopeVarMap.empty; + subscope_vars = Ast.SubScopeMap.empty; + local_vars = Ast.VarMap.empty; + } type scope_ctx = Dcalc.Ast.Var.t Ast.ScopeMap.t -let hole_var : Dcalc.Ast.Var.t = Bindlib.new_var (fun x -> (Dcalc.Ast.EVar x, Pos.no_pos)) "hole" +let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("hole", Pos.no_pos) -let translate_rules (_p : scope_ctx) (_ctx : ctx) (_rules : Ast.rule list) : Dcalc.Ast.expr * ctx = - assert false +let merge_operator_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("merge", Pos.no_pos) -let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr = - let ctx = [] in - let _defs, ctx = translate_rules p ctx sigma.scope_decl_rules in - let _scope_variables = - List.filter_map (fun l -> match l with Ast.ScopeVar v -> Some v | _ -> None) ctx +let merge_operator_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var merge_operator_var + +let hole_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var hole_var + +let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked = + Pos.same_pos_as + ( match Pos.unmark e with + | EVar v -> Dcalc.Ast.EVar (Ast.VarMap.find v ctx.local_vars) + | ELit l -> Dcalc.Ast.ELit l + | EApp (e1, e2) -> Dcalc.Ast.EApp (translate_expr ctx e1, translate_expr ctx e2) + | EAbs (pos_binder, binder, typ) -> + let x, body = Bindlib.unbind binder in + let new_x = Dcalc.Ast.Var.make (Bindlib.name_of x, pos_binder) in + let body = + translate_expr { ctx with local_vars = Ast.VarMap.add x new_x ctx.local_vars } body + in + let binder = Bindlib.unbox (Bindlib.bind_var new_x (Bindlib.box body)) in + Dcalc.Ast.EAbs (pos_binder, binder, typ) + | EDefault (just, cons, subs) -> + Dcalc.Ast.EDefault + (translate_expr ctx just, translate_expr ctx cons, List.map (translate_expr ctx) subs) + | ELocation (ScopeVar a) -> + Dcalc.Ast.EVar (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars)) + | ELocation (SubScopeVar (_, s, a)) -> + Dcalc.Ast.EVar + (fst + (Ast.ScopeVarMap.find (Pos.unmark a) + (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) ) + e + +let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : + Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = + match rule with + | Definition (ScopeVar a, tau, e) -> + let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in + let a_var = Dcalc.Ast.Var.make a_name in + let next_e = + Dcalc.Ast.make_abs a_var hole_expr (Pos.get_position a) tau (Pos.get_position e) + in + let silent1 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in + let silent2 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in + let wrapped_e = + Dcalc.Ast.make_abs silent1 + (Bindlib.box (translate_expr ctx e)) + (Pos.get_position e) Dcalc.Ast.TUnit (Pos.get_position e) + in + let a_expr = Dcalc.Ast.make_var a_var in + let merged_expr = Dcalc.Ast.make_app merge_operator_expr a_expr (Pos.get_position e) in + let merged_expr = Dcalc.Ast.make_app merged_expr wrapped_e (Pos.get_position e) in + let merged_thunked = + Dcalc.Ast.make_abs silent2 merged_expr (Pos.get_position e) Dcalc.Ast.TUnit + (Pos.get_position e) + in + let final_e = Dcalc.Ast.make_app merged_thunked next_e (Pos.get_position e) in + let new_ctx = + { ctx with scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, tau) ctx.scope_vars } + in + (final_e, new_ctx) + | Definition (SubScopeVar _, _tau, _e) -> + Errors.raise_error "translation of subscope vars definitions unimplemented" + | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" + +let translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) : + Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = + let acc = hole_expr in + List.fold_left + (fun (acc, ctx) rule -> + let new_e, ctx = translate_rule p ctx rule in + let acc = Bindlib.unbox (Bindlib.bind_var hole_var acc) in + let new_acc = Bindlib.subst acc (Bindlib.unbox new_e) in + (Bindlib.box new_acc, ctx)) + (acc, ctx) rules + +let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked = + let ctx = empty_ctx in + let rules, ctx = translate_rules p ctx sigma.scope_decl_rules in + let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in + let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in + let return_exp = + Dcalc.Ast.ETuple + (List.map (fun (_, (dcalc_var, _)) -> (Dcalc.Ast.EVar dcalc_var, pos_sigma)) scope_variables) in - assert false + let func_acc = rules in + let func_acc = + List.fold_right + (fun (_, (dcalc_var, tau)) func_acc -> + Dcalc.Ast.make_abs dcalc_var func_acc pos_sigma + (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma))) + pos_sigma) + scope_variables func_acc + in + let func_acc = Bindlib.unbox (Bindlib.bind_var hole_var func_acc) in + Bindlib.subst func_acc (return_exp, pos_sigma) From b386549cf21aed309b3864490532f58bf4e85bd8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 22:26:26 +0100 Subject: [PATCH 013/142] Enriched default calculus --- src/catala/default_calculus/ast.ml | 1 + src/catala/default_calculus/interpreter.ml | 9 +++ src/catala/default_calculus/typing.ml | 9 +++ src/catala/desugared/ast.ml | 11 +++- .../{interpreter.ml => dependency.ml} | 0 src/catala/desugared/desugaring.ml | 62 +++++++++---------- src/catala/desugared/name_resolution.ml | 12 ++-- src/catala/scope_language/ast.ml | 1 + src/catala/scope_language/scope_to_dcalc.ml | 5 +- 9 files changed, 68 insertions(+), 42 deletions(-) rename src/catala/desugared/{interpreter.ml => dependency.ml} (100%) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index abd7e06f..73ae2e5f 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -30,6 +30,7 @@ type expr = | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * typ | EApp of expr Pos.marked * expr Pos.marked | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked module Var = struct type t = expr Pos.marked Bindlib.var diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index adab99d6..5027190a 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -86,3 +86,12 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = "Default justification has not been reduced to a boolean at evaluation (should not \ happen if the term was well-typed" (Pos.get_position e) ) + | EIfThenElse (cond, et, ef) -> ( + match Pos.unmark (evaluate_expr cond) with + | ELit LTrue -> evaluate_expr et + | ELit LFalse -> evaluate_expr ef + | _ -> + Errors.raise_spanned_error + "expected a boolean literal for the result of this condition (should not happen if the \ + term was well-typed)" + (Pos.get_position cond) ) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index e91e61af..9107bea0 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -128,6 +128,11 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m let tcons = typecheck_expr_bottom_up env cons in List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; tcons + | EIfThenElse (cond, et, ef) -> + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + let tt = typecheck_expr_bottom_up env et in + typecheck_expr_top_down env ef tt; + tt and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = @@ -182,6 +187,10 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); typecheck_expr_top_down env cons tau; List.iter (fun sub -> typecheck_expr_top_down env sub tau) subs + | EIfThenElse (cond, et, ef) -> + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + typecheck_expr_top_down env et tau; + typecheck_expr_top_down env ef tau let infer_type (e : A.expr Pos.marked) : A.typ Pos.marked = let ty = typecheck_expr_bottom_up A.VarMap.empty e in diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 73d52ded..983f6095 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -53,11 +53,16 @@ module ScopeDefSet = Set.Make (ScopeDef) (* Scopes *) type binder = LocalVar.t -type definition = unit +type definition = Scopelang.Ast.expr Pos.marked -let empty_def (_pos : Pos.t) (_typ : Dcalc.Ast.typ) : definition = assert false +let empty_def (pos : Pos.t) : definition = + ( Scopelang.Ast.EDefault + ( (Scopelang.Ast.ELit Dcalc.Ast.LFalse, pos), + (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos), + [] ), + pos ) -type assertion = unit +type assertion = Scopelang.Ast.expr Pos.marked type variation_typ = Increasing | Decreasing diff --git a/src/catala/desugared/interpreter.ml b/src/catala/desugared/dependency.ml similarity index 100% rename from src/catala/desugared/interpreter.ml rename to src/catala/desugared/dependency.ml diff --git a/src/catala/desugared/desugaring.ml b/src/catala/desugared/desugaring.ml index 18f99445..4ec27dda 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/desugared/desugaring.ml @@ -19,41 +19,40 @@ module Errors = Utils.Errors a redefinition of a subvariable *) (* let rec expr_to_lambda (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t option) - (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : 'a = let - scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in let rec_helper = expr_to_lambda - scope def_key ctxt in match expr with | IfThenElse (e_if, e_then, e_else) -> ((EIfThenElse - (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos), TDummy) | Binop (op, e1, e2) -> - let op_term = (Pos.same_pos_as (EOp (Binop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ - rec_helper e1; rec_helper e2 ]), pos), TDummy) | Unop (op, e) -> let op_term = (Pos.same_pos_as - (EOp (Unop (Pos.unmark op))) op, TDummy) in ((EApp (op_term, [ rec_helper e ]), pos), TDummy) | - Literal l -> let untyped_term = match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec - (i, f), _), _) -> EDec (i, f) | Bool b -> EBool b | _ -> - Name_resolution.raise_unsupported_feature "literal" pos in ((untyped_term, pos), TDummy) | Ident - x -> ( (* first we check whether this is a local var, then we resort to scope-wide variables *) - match def_key with | Some def_key -> ( let def_ctxt = Ast.ScopeDefMap.find def_key - scope_ctxt.definitions in match Ast.IdentMap.find_opt x def_ctxt.var_idmap with | None -> ( match - Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), - TDummy) | None -> Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" - (x, pos) ) | Some uid -> ((ELocalVar uid, pos), TDummy) ) | None -> ( match Ast.IdentMap.find_opt - x scope_ctxt.var_idmap with | Some uid -> ((EVar (NoPrefix, uid), pos), TDummy) | None -> - Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | Dotted (e, x) - -> ( (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) match - Pos.unmark e with | Ident y -> let subscope_uid : Scopelang.Ast.SubScopeName.t = - Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in let subscope_real_uid : + (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : + Scopelang.Ast.expr Pos.marked = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in + let rec_helper = expr_to_lambda scope def_key ctxt in match expr with | IfThenElse (e_if, e_then, + e_else) -> (EIfThenElse (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos) | Binop + (op, e1, e2) -> let op_term = Pos.same_pos_as (EOp (Binop (Pos.unmark op))) op in (EApp (op_term, + [ rec_helper e1; rec_helper e2 ]), pos) | Unop (op, e) -> let op_term = Pos.same_pos_as (EOp + (Unop (Pos.unmark op))) op in (EApp (op_term, [ rec_helper e ]), pos) | Literal l -> let + untyped_term = match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec (i, f), _), _) -> + EDec (i, f) | Bool b -> EBool b | _ -> Name_resolution.raise_unsupported_feature "literal" pos in + (untyped_term, pos) | Ident x -> ( (* first we check whether this is a local var, then we resort + to scope-wide variables *) match def_key with | Some def_key -> ( let def_ctxt = + Ast.ScopeDefMap.find def_key scope_ctxt.definitions in match Ast.IdentMap.find_opt x + def_ctxt.var_idmap with | None -> ( match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | + Some uid -> (EVar (NoPrefix, uid), pos) | None -> Name_resolution.raise_unknown_identifier "for a + local or scope-wide variable" (x, pos) ) | Some uid -> (ELocalVar uid, pos) ) | None -> ( match + Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> (EVar (NoPrefix, uid), pos) | + None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | + Dotted (e, x) -> ( (* For now we only accept dotted identifiers of the type y.x where y is a + sub-scope *) match Pos.unmark e with | Ident y -> let subscope_uid : Scopelang.Ast.SubScopeName.t + = Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in let subscope_real_uid : Scopelang.Ast.ScopeName.t = Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in - let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in ((EVar - (SubScopePrefix subscope_uid, subscope_var_uid), pos), TDummy) | _ -> - Name_resolution.raise_unsupported_feature "left hand side of a dotted expression should be an - identifier" pos ) | FunCall (f, arg) -> ((EApp (rec_helper f, [ rec_helper arg ]), pos), TDummy) - | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos *) + let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in (EVar + (SubScopePrefix subscope_uid, subscope_var_uid), pos) | _ -> + Name_resolution.raise_unsupported_feature "left hand side of a dotted expression should be an\n + identifier" pos ) | FunCall (f, arg) -> (EApp (rec_helper f, [ rec_helper arg ]), pos) | _ -> + Name_resolution.raise_unsupported_feature "unsupported expression" pos *) (* Translation from the parsed ast to the scope language *) (* let merge_conditions (precond : Dcalc.Ast.term option) (cond : Dcalc.Ast.term option) (default_pos : Pos.t) : Dcalc.Ast.term = match (precond, cond) with | Some precond, Some cond -> - let op_term = ((EOp (Binop And), Pos.get_position (fst precond)), TDummy) in ((EApp (op_term, [ - precond; cond ]), Pos.get_position (fst precond)), TDummy) | Some cond, None | None, Some cond -> - cond | None, None -> ((EBool true, default_pos), TBool) + let op_term = ((EOp (Binop And), Pos.get_position (fst precond))) in ((EApp (op_term, [ precond; + cond ]), Pos.get_position (fst precond))) | Some cond, None | None, Some cond -> cond | None, + None -> ((EBool true, default_pos), TBool) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t) (def : Dcalc.Ast.default_term) (param_uid : Ast.LocalVar.t option) (precond : @@ -63,9 +62,8 @@ module Errors = Utils.Errors merge_conditions precond just (Pos.get_position body) in let body = expr_to_lambda scope (Some def_key) ctxt body in (* if there's a parameter, we have to wrap the justifiction and the body in a func *) let condition, body = match param_uid with | None -> (condition, body) | Some param_uid - -> ( ((EFun ([ (param_uid, TDummy) ], condition), Pos.get_position (fst condition)), TDummy), - ((EFun ([ (param_uid, TDummy) ], body), Pos.get_position (fst body)), TDummy) ) in - Dcalc.Ast.add_default condition body def *) + -> ( ((EFun ([ (param_uid) ], condition), Pos.get_position (fst condition))), ((EFun ([ + (param_uid) ], body), Pos.get_position (fst body))) ) in Dcalc.Ast.add_default condition body def *) (* Process a definition *) let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.ScopeName.t) diff --git a/src/catala/desugared/name_resolution.ml b/src/catala/desugared/name_resolution.ml index 7fc3b447..bc4b54a6 100644 --- a/src/catala/desugared/name_resolution.ml +++ b/src/catala/desugared/name_resolution.ml @@ -20,7 +20,7 @@ module Errors = Utils.Errors type ident = string -type typ = unit +type typ = Dcalc.Ast.typ type def_context = { var_idmap : Ast.LocalVar.t Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern @@ -38,7 +38,7 @@ type scope_context = { type context = { scope_idmap : Scopelang.Ast.ScopeName.t Ast.IdentMap.t; scopes : scope_context Scopelang.Ast.ScopeMap.t; - var_typs : typ Scopelang.Ast.ScopeVarMap.t; + var_typs : typ Pos.marked Scopelang.Ast.ScopeVarMap.t; } let raise_unsupported_feature (msg : string) (pos : Pos.t) = @@ -50,7 +50,7 @@ let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = (Pos.get_position ident) (** Get the type associated to an uid *) -let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ = +let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ Pos.marked = Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs (** Process a subscope declaration *) @@ -107,7 +107,7 @@ let process_type ((typ, typ_pos) : Surface.Ast.typ Pos.marked) : Dcalc.Ast.typ P let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Surface.Ast.scope_decl_context_data) : context = (* First check the type of the context data *) - let _data_typ = process_type decl.scope_decl_context_item_typ in + let data_typ = process_type decl.scope_decl_context_item_typ in let name, pos = decl.scope_decl_context_item_name in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in match Ast.IdentMap.find_opt name scope_ctxt.var_idmap with @@ -125,7 +125,7 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes; - var_typs = assert false (* Scopelang.Ast.ScopeVarMap.add uid data_typ ctxt.var_typs *); + var_typs = Scopelang.Ast.ScopeVarMap.add uid data_typ ctxt.var_typs; } (** Process an item declaration *) @@ -315,7 +315,7 @@ let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) (fun _ var_uid -> Scopelang.Ast.ScopeVar.compare uid var_uid = 0) scope.var_idmap -let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ = +let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ Pos.marked = match def with | Ast.ScopeDef.SubScopeVar (_, x) (* we don't need to look at the subscope prefix because [x] is already the uid referring back to diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 903afce8..ffba8b60 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -35,6 +35,7 @@ type expr = | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * Dcalc.Ast.typ | EApp of expr Pos.marked * expr Pos.marked | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked module Var = struct type t = expr Pos.marked Bindlib.var diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 9daaf970..e6fa8e48 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -61,7 +61,10 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po Dcalc.Ast.EVar (fst (Ast.ScopeVarMap.find (Pos.unmark a) - (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) ) + (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) + | EIfThenElse (cond, et, ef) -> + Dcalc.Ast.EIfThenElse (translate_expr ctx cond, translate_expr ctx et, translate_expr ctx ef) + ) e let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : From bda82150236f7ecc5bd36c3b9a837ae9855e8548 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 23 Nov 2020 22:26:53 +0100 Subject: [PATCH 014/142] Restored build --- src/catala/desugared/desugaring.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/catala/desugared/desugaring.ml b/src/catala/desugared/desugaring.ml index 4ec27dda..648d098a 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/desugared/desugaring.ml @@ -101,7 +101,7 @@ let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.Sc | Some def -> def | None -> let _typ = Name_resolution.get_def_typ ctxt def_key in - Ast.empty_def default_pos (assert false (* typ *)) + Ast.empty_def default_pos in let x_def = assert false From 18eb7572320365ec7218d8d652438d37b45eedea Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 24 Nov 2020 10:28:39 +0100 Subject: [PATCH 015/142] Changed bindings to take list of parameters --- src/catala/default_calculus/ast.ml | 16 +++-- src/catala/default_calculus/interpreter.ml | 14 +++- src/catala/default_calculus/typing.ml | 73 +++++++++++++++------ src/catala/scope_language/ast.ml | 4 +- src/catala/scope_language/scope_to_dcalc.ml | 52 +++++++++------ 5 files changed, 108 insertions(+), 51 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 73ae2e5f..eb57a3de 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -27,8 +27,8 @@ type expr = | ETuple of expr Pos.marked list | ETupleAccess of expr Pos.marked * int | ELit of lit - | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * typ - | EApp of expr Pos.marked * expr Pos.marked + | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * typ list + | EApp of expr Pos.marked * expr Pos.marked list | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked @@ -41,16 +41,18 @@ module Var = struct let compare x y = Bindlib.compare_vars x y end +type vars = expr Pos.marked Bindlib.mvar + module VarMap = Map.Make (Var) let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x -let make_abs (x : Var.t) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (tau : typ) +let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (taus : typ list) (pos : Pos.t) : expr Pos.marked Bindlib.box = - Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, tau), pos)) (Bindlib.bind_var x e) + Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, taus), pos)) (Bindlib.bind_mvar xs e) -let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box) (pos : Pos.t) : - expr Pos.marked Bindlib.box = - Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e u +let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box list) (pos : Pos.t) + : expr Pos.marked Bindlib.box = + Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 5027190a..20b11780 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -25,11 +25,19 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = Errors.raise_spanned_error "free variable found at evaluation (should not happen if term was well-typed" (Pos.get_position e) - | EApp (e1, e2) -> ( + | EApp (e1, args) -> ( let e1 = evaluate_expr e1 in - let e2 = evaluate_expr e2 in + let args = List.map evaluate_expr args in + match Pos.unmark e1 with - | EAbs (_, binder, _) -> evaluate_expr (Bindlib.subst binder e2) + | EAbs (_, binder, _) -> + if Bindlib.mbinder_arity binder = List.length args then + evaluate_expr (Bindlib.msubst binder (Array.of_list args)) + else + Errors.raise_spanned_error + (Format.asprintf "wrong function call, expected %d arguments, got %d" + (Bindlib.mbinder_arity binder) (List.length args)) + (Pos.get_position e) | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e | _ -> Errors.raise_spanned_error diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 9107bea0..d92091c9 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -113,14 +113,29 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m Errors.raise_spanned_error (Format.asprintf "exprected a tuple, got a %a" format_typ t1) (Pos.get_position e1) ) - | EAbs (pos_binder, binder, tau) -> - let x, body = Bindlib.unbind binder in - let env = A.VarMap.add x (ast_to_typ tau, pos_binder) env in - typecheck_expr_bottom_up env body - | EApp (e1, e2) -> - let t2 = typecheck_expr_bottom_up env e2 in - let t_arg = UnionFind.make (Pos.same_pos_as TAny e) in - let t_app = UnionFind.make (Pos.same_pos_as (TArrow (t_arg, t2)) e) in + | EAbs (pos_binder, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + if Array.length xs = List.length taus then + let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let env = + List.fold_left + (fun env (x, tau) -> A.VarMap.add x (ast_to_typ tau, pos_binder) env) + env xstaus + in + typecheck_expr_bottom_up env body + else + Errors.raise_spanned_error + (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) + (List.length taus)) + pos_binder + | EApp (e1, args) -> + let t_args = List.map (typecheck_expr_bottom_up env) args in + let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + let t_app = + List.fold_right + (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + t_args t_ret + in typecheck_expr_top_down env e1 t_app; t_app | EDefault (just, cons, subs) -> @@ -169,19 +184,37 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) Errors.raise_spanned_error (Format.asprintf "exprected a tuple , got %a" format_typ tau) (Pos.get_position e) ) - | EAbs (pos_binder, binder, t_arg) -> - let x, body = Bindlib.unbind binder in - let env = A.VarMap.add x (ast_to_typ t_arg, pos_binder) env in - let t_out = typecheck_expr_bottom_up env body in - let t_func = - UnionFind.make - (Pos.same_pos_as (TArrow (UnionFind.make (ast_to_typ t_arg, pos_binder), t_out)) e) - in - unify t_func tau - | EApp (e1, e2) -> - let te2 = typecheck_expr_bottom_up env e2 in + | EAbs (pos_binder, binder, t_args) -> + let xs, body = Bindlib.unmbind binder in + if Array.length xs = List.length t_args then + let xstaus = List.map2 (fun x t_arg -> (x, t_arg)) (Array.to_list xs) t_args in + let env = + List.fold_left + (fun env (x, t_arg) -> A.VarMap.add x (ast_to_typ t_arg, pos_binder) env) + env xstaus + in + let t_out = typecheck_expr_bottom_up env body in + let t_func = + List.fold_right + (fun t_arg acc -> + UnionFind.make + (Pos.same_pos_as (TArrow (UnionFind.make (ast_to_typ t_arg, pos_binder), acc)) e)) + t_args t_out + in + unify t_func tau + else + Errors.raise_spanned_error + (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) + (List.length t_args)) + pos_binder + | EApp (e1, args) -> + let t_args = List.map (typecheck_expr_bottom_up env) args in let te1 = typecheck_expr_bottom_up env e1 in - let t_func = UnionFind.make (Pos.same_pos_as (TArrow (te2, tau)) e) in + let t_func = + List.fold_right + (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + t_args tau + in unify te1 t_func | EDefault (just, cons, subs) -> typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index ffba8b60..b4510371 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -32,8 +32,8 @@ type expr = | ELocation of location | EVar of expr Pos.marked Bindlib.var | ELit of Dcalc.Ast.lit - | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.binder * Dcalc.Ast.typ - | EApp of expr Pos.marked * expr Pos.marked + | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ list + | EApp of expr Pos.marked * expr Pos.marked list | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index e6fa8e48..5fefb2b5 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -43,14 +43,23 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po ( match Pos.unmark e with | EVar v -> Dcalc.Ast.EVar (Ast.VarMap.find v ctx.local_vars) | ELit l -> Dcalc.Ast.ELit l - | EApp (e1, e2) -> Dcalc.Ast.EApp (translate_expr ctx e1, translate_expr ctx e2) + | EApp (e1, args) -> Dcalc.Ast.EApp (translate_expr ctx e1, List.map (translate_expr ctx) args) | EAbs (pos_binder, binder, typ) -> - let x, body = Bindlib.unbind binder in - let new_x = Dcalc.Ast.Var.make (Bindlib.name_of x, pos_binder) in + let xs, body = Bindlib.unmbind binder in + let new_xs = Array.map (fun x -> Dcalc.Ast.Var.make (Bindlib.name_of x, pos_binder)) xs in + let both_xs = Array.map2 (fun x new_x -> (x, new_x)) xs new_xs in let body = - translate_expr { ctx with local_vars = Ast.VarMap.add x new_x ctx.local_vars } body + translate_expr + { + ctx with + local_vars = + Array.fold_left + (fun local_vars (x, new_x) -> Ast.VarMap.add x new_x local_vars) + ctx.local_vars both_xs; + } + body in - let binder = Bindlib.unbox (Bindlib.bind_var new_x (Bindlib.box body)) in + let binder = Bindlib.unbox (Bindlib.bind_mvar new_xs (Bindlib.box body)) in Dcalc.Ast.EAbs (pos_binder, binder, typ) | EDefault (just, cons, subs) -> Dcalc.Ast.EDefault @@ -74,23 +83,27 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in let next_e = - Dcalc.Ast.make_abs a_var hole_expr (Pos.get_position a) tau (Pos.get_position e) + Dcalc.Ast.make_abs + (Array.of_list [ a_var ]) + hole_expr (Pos.get_position a) [ tau ] (Pos.get_position e) in let silent1 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in let silent2 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in let wrapped_e = - Dcalc.Ast.make_abs silent1 + Dcalc.Ast.make_abs + (Array.of_list [ silent1 ]) (Bindlib.box (translate_expr ctx e)) - (Pos.get_position e) Dcalc.Ast.TUnit (Pos.get_position e) + (Pos.get_position e) [ Dcalc.Ast.TUnit ] (Pos.get_position e) in let a_expr = Dcalc.Ast.make_var a_var in - let merged_expr = Dcalc.Ast.make_app merge_operator_expr a_expr (Pos.get_position e) in - let merged_expr = Dcalc.Ast.make_app merged_expr wrapped_e (Pos.get_position e) in + let merged_expr = Dcalc.Ast.make_app merge_operator_expr [ a_expr ] (Pos.get_position e) in + let merged_expr = Dcalc.Ast.make_app merged_expr [ wrapped_e ] (Pos.get_position e) in let merged_thunked = - Dcalc.Ast.make_abs silent2 merged_expr (Pos.get_position e) Dcalc.Ast.TUnit - (Pos.get_position e) + Dcalc.Ast.make_abs + (Array.of_list [ silent2 ]) + merged_expr (Pos.get_position e) [ Dcalc.Ast.TUnit ] (Pos.get_position e) in - let final_e = Dcalc.Ast.make_app merged_thunked next_e (Pos.get_position e) in + let final_e = Dcalc.Ast.make_app merged_thunked [ next_e ] (Pos.get_position e) in let new_ctx = { ctx with scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, tau) ctx.scope_vars } in @@ -121,12 +134,13 @@ let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.ex in let func_acc = rules in let func_acc = - List.fold_right - (fun (_, (dcalc_var, tau)) func_acc -> - Dcalc.Ast.make_abs dcalc_var func_acc pos_sigma - (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma))) - pos_sigma) - scope_variables func_acc + Dcalc.Ast.make_abs + (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) + func_acc pos_sigma + (List.map + (fun (_, (_, tau)) -> Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma))) + scope_variables) + pos_sigma in let func_acc = Bindlib.unbox (Bindlib.bind_var hole_var func_acc) in Bindlib.subst func_acc (return_exp, pos_sigma) From e1dfb520952a27888f518dae47ce50ea87fc5655 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 24 Nov 2020 11:27:23 +0100 Subject: [PATCH 016/142] Added ints and operators to default calculus --- src/catala/default_calculus/ast.ml | 10 ++++- src/catala/default_calculus/interpreter.ml | 47 +++++++++++++++++++--- src/catala/default_calculus/typing.ml | 30 ++++++++++++-- src/catala/desugared/ast.ml | 2 +- 4 files changed, 79 insertions(+), 10 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index eb57a3de..2c142fa4 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -17,10 +17,17 @@ module Pos = Utils.Pos type typ = | TBool | TUnit + | TInt | TTuple of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LTrue | LFalse | LEmptyError +type lit = LBool of bool | LEmptyError | LInt of Int64.t + +type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq + +type unop = Not | Minus + +type operator = Binop of binop | Unop of unop type expr = | EVar of expr Pos.marked Bindlib.var @@ -29,6 +36,7 @@ type expr = | ELit of lit | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * typ list | EApp of expr Pos.marked * expr Pos.marked list + | EOp of operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 20b11780..6d2dbaef 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -19,6 +19,42 @@ module A = Ast let is_empty_error (e : A.expr Pos.marked) : bool = match Pos.unmark e with ELit LEmptyError -> true | _ -> false +let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked list) : + A.expr Pos.marked = + Pos.same_pos_as + ( match (Pos.unmark op, List.map Pos.unmark args) with + | A.Binop A.And, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 && b2)) + | A.Binop A.Or, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 || b2)) + | A.Binop A.Add, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.add i1 i2)) + | A.Binop A.Sub, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.sub i1 i2)) + | A.Binop A.Mult, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.mul i1 i2)) + | A.Binop A.Div, [ ELit (LInt i1); ELit (LInt i2) ] -> + if i2 <> Int64.zero then A.ELit (LInt (Int64.div i1 i2)) + else + Errors.raise_multispanned_error "division by zero at runtime" + [ + (Some "The division operator:", Pos.get_position op); + (Some "The null denominator:", Pos.get_position (List.nth args 2)); + ] + | A.Binop A.Lt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) + | A.Binop A.Lte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) + | A.Binop A.Gt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) + | A.Binop A.Gte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 >= i2)) + | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) + | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) + | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) + | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) + | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) + | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) + | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) + | A.Unop A.Minus, [ ELit (LInt i) ] -> A.ELit (LInt (Int64.sub Int64.zero i)) + | _ -> + Errors.raise_multispanned_error + "operator applied to the wrong arguments (should not happen if the term was well-typed)" + [ (Some "Operator:", Pos.get_position op) ] + @@ List.mapi (fun i arg -> Some ("Argument n°" ^ string_of_int i, Pos.get_position arg)) ) + op + let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = match Pos.unmark e with | EVar _ -> @@ -38,13 +74,14 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = (Format.asprintf "wrong function call, expected %d arguments, got %d" (Bindlib.mbinder_arity binder) (List.length args)) (Pos.get_position e) + | EOp op -> evaluate_operator (Pos.same_pos_as op e1) args | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e | _ -> Errors.raise_spanned_error "function has not been reduced to a lambda at evaluation (should not happen if the \ term was well-typed" (Pos.get_position e) ) - | EAbs _ | ELit _ -> e (* thse are values *) + | EAbs _ | ELit _ | EOp _ -> e (* thse are values *) | ETuple es -> Pos.same_pos_as (A.ETuple (List.map evaluate_expr es)) e | ETupleAccess (e1, n) -> ( let e1 = evaluate_expr e1 in @@ -70,8 +107,8 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = let just = evaluate_expr just in match Pos.unmark just with | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e - | ELit LTrue -> evaluate_expr cons - | ELit LFalse -> ( + | ELit (LBool true) -> evaluate_expr cons + | ELit (LBool false) -> ( let subs = List.map evaluate_expr subs in let empty_count = List.length (List.filter is_empty_error subs) in match List.length subs - empty_count with @@ -96,8 +133,8 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = (Pos.get_position e) ) | EIfThenElse (cond, et, ef) -> ( match Pos.unmark (evaluate_expr cond) with - | ELit LTrue -> evaluate_expr et - | ELit LFalse -> evaluate_expr ef + | ELit (LBool true) -> evaluate_expr et + | ELit (LBool false) -> evaluate_expr ef | _ -> Errors.raise_spanned_error "expected a boolean literal for the result of this condition (should not happen if the \ diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index d92091c9..6163e1f2 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -21,6 +21,7 @@ module A = Ast type typ = | TUnit + | TInt | TBool | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem | TTuple of typ Pos.marked UnionFind.elem list @@ -31,6 +32,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) match Pos.unmark ty_repr with | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" + | TInt -> Format.fprintf fmt "int" | TAny -> Format.fprintf fmt "any" | TTuple ts -> Format.fprintf fmt "(%a)" @@ -42,7 +44,7 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with - | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) -> () + | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) | (TInt, _), (TInt, _) -> () | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> unify t11 t21; unify t12 t22 @@ -60,10 +62,25 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); ] +let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = + let pos = Pos.get_position op in + let bt = UnionFind.make (TBool, pos) in + let it = UnionFind.make (TInt, pos) in + let any = UnionFind.make (TAny, pos) in + let arr x y = UnionFind.make (TArrow (x, y), pos) in + match Pos.unmark op with + | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) + | A.Binop (A.Add | A.Sub | A.Mult | A.Div) -> arr it (arr it it) + | A.Binop (A.Lt | A.Lte | A.Gt | A.Gte) -> arr it (arr it bt) + | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) + | A.Unop A.Minus -> arr it it + | A.Unop A.Not -> arr bt bt + let rec ast_to_typ (ty : A.typ) : typ = match ty with | A.TUnit -> TUnit | A.TBool -> TBool + | A.TInt -> TInt | A.TArrow (t1, t2) -> TArrow ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), @@ -76,6 +93,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = match ty with | TUnit -> A.TUnit | TBool -> A.TBool + | TInt -> A.TInt | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) | TAny -> A.TUnit) @@ -92,7 +110,8 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) - | ELit (LTrue | LFalse) -> UnionFind.make (Pos.same_pos_as TBool e) + | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) + | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> let ts = List.map (typecheck_expr_bottom_up env) es in @@ -138,6 +157,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m in typecheck_expr_top_down env e1 t_app; t_app + | EOp op -> op_type (Pos.same_pos_as op e) | EDefault (just, cons, subs) -> typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); let tcons = typecheck_expr_bottom_up env cons in @@ -158,7 +178,8 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) - | ELit (LTrue | LFalse) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) + | ELit (LBool _) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) + | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as TInt e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | ETuple es -> ( let tau' = UnionFind.get (UnionFind.find tau) in @@ -216,6 +237,9 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) t_args tau in unify te1 t_func + | EOp op -> + let op_typ = op_type (Pos.same_pos_as op e) in + unify op_typ tau | EDefault (just, cons, subs) -> typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); typecheck_expr_top_down env cons tau; diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 983f6095..6609a1a7 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -57,7 +57,7 @@ type definition = Scopelang.Ast.expr Pos.marked let empty_def (pos : Pos.t) : definition = ( Scopelang.Ast.EDefault - ( (Scopelang.Ast.ELit Dcalc.Ast.LFalse, pos), + ( (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos), (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos), [] ), pos ) From bfdffb7b788815e39cab426089bcc4800cb39dd3 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 24 Nov 2020 15:48:57 +0100 Subject: [PATCH 017/142] Progress on desugarin --- src/catala/catala_surface/ast.ml | 4 +- src/catala/catala_surface/lexer.ml | 8 +- src/catala/catala_surface/lexer_en.ml | 8 +- src/catala/catala_surface/lexer_fr.ml | 8 +- src/catala/catala_surface/parser.mly | 8 +- src/catala/default_calculus/ast.ml | 4 +- src/catala/desugared/ast.ml | 4 - src/catala/desugared/desugaring.ml | 168 +++++++++++++++----- src/catala/desugared/name_resolution.ml | 8 +- src/catala/scope_language/ast.ml | 13 ++ src/catala/scope_language/scope_to_dcalc.ml | 2 +- 11 files changed, 163 insertions(+), 72 deletions(-) diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 0fc97640..446c7ea6 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -69,13 +69,13 @@ type literal_date = { literal_date_year : int Pos.marked; } -type literal_number = Int of int | Dec of int * int +type literal_number = Int of Int64.t | Dec of Int64.t * Int64.t type literal_unit = Percent | Year | Month | Day type collection_op = Exists | Forall | Aggregate of aggregate_func -type money_amount = { money_amount_units : int; money_amount_cents : int } +type money_amount = { money_amount_units : Int64.t; money_amount_cents : Int64.t } type literal = | Number of literal_number Pos.marked * literal_unit Pos.marked option diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index b899b3d2..004e973e 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -282,8 +282,8 @@ let rec lex_code (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_commas = R.regexp "," in - let units = int_of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in - let cents = try int_of_string (parts 4) with Not_found -> 0 in + let units = Int64.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in + let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', '.', Star '0' .. '9' -> @@ -291,7 +291,7 @@ let rec lex_code (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) update_acc lexbuf; - DECIMAL_LITERAL (int_of_string (dec_parts 1), int_of_string (dec_parts 2)) + DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) | "->" -> update_acc lexbuf; ARROW @@ -357,7 +357,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) update_acc lexbuf; - INT_LITERAL (int_of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let rec lex_law (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index fdd6a2bc..3c785854 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -254,8 +254,8 @@ let rec lex_code_en (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_commas = R.regexp "," in - let units = int_of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in - let cents = try int_of_string (parts 4) with Not_found -> 0 in + let units = Int64.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in + let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in L.update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', '.', Star '0' .. '9' -> @@ -263,7 +263,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) L.update_acc lexbuf; - DECIMAL_LITERAL (int_of_string (dec_parts 1), int_of_string (dec_parts 2)) + DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) | "->" -> L.update_acc lexbuf; ARROW @@ -329,7 +329,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) L.update_acc lexbuf; - INT_LITERAL (int_of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let rec lex_law_en (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 1b62c4da..63d3832b 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -263,8 +263,8 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_spaces = R.regexp " " in - let units = int_of_string (R.substitute ~rex:remove_spaces ~subst:(fun _ -> "") units) in - let cents = try int_of_string (parts 4) with Not_found -> 0 in + let units = Int64.of_string (R.substitute ~rex:remove_spaces ~subst:(fun _ -> "") units) in + let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in L.update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', ',', Star '0' .. '9' -> @@ -272,7 +272,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) L.update_acc lexbuf; - DECIMAL_LITERAL (int_of_string (dec_parts 1), int_of_string (dec_parts 2)) + DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) | "->" -> L.update_acc lexbuf; ARROW @@ -338,7 +338,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) L.update_acc lexbuf; - INT_LITERAL (int_of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let rec lex_law_fr (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 45207d3b..faea60ae 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -34,10 +34,10 @@ %token LAW_TEXT %token CONSTRUCTOR IDENT %token END_CODE -%token INT_LITERAL +%token INT_LITERAL %token TRUE FALSE -%token DECIMAL_LITERAL -%token MONEY_AMOUNT +%token DECIMAL_LITERAL +%token MONEY_AMOUNT %token BEGIN_CODE TEXT MASTER_FILE %token COLON ALT DATA VERTICAL %token OF INTEGER COLLECTION @@ -154,7 +154,7 @@ unit_literal: | YEAR { (Year, $sloc)} date_int: -| d = INT_LITERAL { (d, $sloc) } +| d = INT_LITERAL { (Int64.to_int d, $sloc) } literal: | l = num_literal u = option(unit_literal) { diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 2c142fa4..f56f0b0b 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -49,10 +49,10 @@ module Var = struct let compare x y = Bindlib.compare_vars x y end -type vars = expr Pos.marked Bindlib.mvar - module VarMap = Map.Make (Var) +type vars = expr Pos.marked Bindlib.mvar + let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (taus : typ list) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 6609a1a7..20aa74b7 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -15,9 +15,6 @@ module Pos = Utils.Pos module Uid = Utils.Uid module IdentMap = Map.Make (String) -module LocalVar = Uid.Make (Uid.MarkedString) -module LocalVarSet = Set.Make (LocalVar) -module LocalVarMap = Map.Make (LocalVar) (** Inside a scope, a definition can refer either to a scope def, or a subscope def *) module ScopeDef = struct @@ -51,7 +48,6 @@ module ScopeDefMap = Map.Make (ScopeDef) module ScopeDefSet = Set.Make (ScopeDef) (* Scopes *) -type binder = LocalVar.t type definition = Scopelang.Ast.expr Pos.marked diff --git a/src/catala/desugared/desugaring.ml b/src/catala/desugared/desugaring.ml index 648d098a..fb3ff48d 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/desugared/desugaring.ml @@ -18,52 +18,134 @@ module Errors = Utils.Errors (** The optional argument subdef allows to choose between differents uids in case the expression is a redefinition of a subvariable *) -(* let rec expr_to_lambda (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t option) - (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : - Scopelang.Ast.expr Pos.marked = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in - let rec_helper = expr_to_lambda scope def_key ctxt in match expr with | IfThenElse (e_if, e_then, - e_else) -> (EIfThenElse (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos) | Binop - (op, e1, e2) -> let op_term = Pos.same_pos_as (EOp (Binop (Pos.unmark op))) op in (EApp (op_term, - [ rec_helper e1; rec_helper e2 ]), pos) | Unop (op, e) -> let op_term = Pos.same_pos_as (EOp - (Unop (Pos.unmark op))) op in (EApp (op_term, [ rec_helper e ]), pos) | Literal l -> let - untyped_term = match l with | Number ((Int i, _), _) -> EInt i | Number ((Dec (i, f), _), _) -> - EDec (i, f) | Bool b -> EBool b | _ -> Name_resolution.raise_unsupported_feature "literal" pos in - (untyped_term, pos) | Ident x -> ( (* first we check whether this is a local var, then we resort - to scope-wide variables *) match def_key with | Some def_key -> ( let def_ctxt = - Ast.ScopeDefMap.find def_key scope_ctxt.definitions in match Ast.IdentMap.find_opt x - def_ctxt.var_idmap with | None -> ( match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | - Some uid -> (EVar (NoPrefix, uid), pos) | None -> Name_resolution.raise_unknown_identifier "for a - local or scope-wide variable" (x, pos) ) | Some uid -> (ELocalVar uid, pos) ) | None -> ( match - Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> (EVar (NoPrefix, uid), pos) | - None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | - Dotted (e, x) -> ( (* For now we only accept dotted identifiers of the type y.x where y is a - sub-scope *) match Pos.unmark e with | Ident y -> let subscope_uid : Scopelang.Ast.SubScopeName.t - = Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in let subscope_real_uid : - Scopelang.Ast.ScopeName.t = Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in - let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in (EVar - (SubScopePrefix subscope_uid, subscope_var_uid), pos) | _ -> - Name_resolution.raise_unsupported_feature "left hand side of a dotted expression should be an\n - identifier" pos ) | FunCall (f, arg) -> (EApp (rec_helper f, [ rec_helper arg ]), pos) | _ -> - Name_resolution.raise_unsupported_feature "unsupported expression" pos *) +let translate_binop (op : Surface.Ast.binop) : Dcalc.Ast.binop = + match op with + | And -> And + | Or -> Or + | Add -> Add + | Sub -> Sub + | Mult -> Mult + | Div -> Div + | Lt -> Lt + | Lte -> Lte + | Gt -> Gt + | Gte -> Gte + | Eq -> Eq + | Neq -> Neq + +let translate_unop (op : Surface.Ast.unop) : Dcalc.Ast.unop = + match op with Not -> Not | Minus -> Minus + +let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t option) + (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : + Scopelang.Ast.expr Pos.marked = + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in + let rec_helper = translate_expr scope def_key ctxt in + match expr with + | IfThenElse (e_if, e_then, e_else) -> + (EIfThenElse (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos) + | Binop (op, e1, e2) -> + let op_term = + Pos.same_pos_as (Scopelang.Ast.EOp (Dcalc.Ast.Binop (translate_binop (Pos.unmark op)))) op + in + (EApp (op_term, [ rec_helper e1; rec_helper e2 ]), pos) + | Unop (op, e) -> + let op_term = + Pos.same_pos_as (Scopelang.Ast.EOp (Dcalc.Ast.Unop (translate_unop (Pos.unmark op)))) op + in + (EApp (op_term, [ rec_helper e ]), pos) + | Literal l -> + let untyped_term = + match l with + | Number ((Int i, _), _) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) + | Number ((Dec (_i, _f), _), _) -> Name_resolution.raise_unsupported_feature "decimal" pos + | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) + | _ -> Name_resolution.raise_unsupported_feature "literal" pos + in + (untyped_term, pos) + | Ident x -> ( + (* first we check whether this is a local var, then we resort to scope-wide variables *) + match def_key with + | Some def_key -> ( + let def_ctxt = Ast.ScopeDefMap.find def_key scope_ctxt.definitions in + match Ast.IdentMap.find_opt x def_ctxt.var_idmap with + | None -> ( + match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with + | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) + | None -> + Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" + (x, pos) ) + | Some uid -> (Scopelang.Ast.EVar uid, pos) ) + | None -> ( + match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with + | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) + | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) + ) + | Dotted (e, x) -> ( + (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) + match Pos.unmark e with + | Ident y -> + let subscope_uid : Scopelang.Ast.SubScopeName.t = + Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) + in + let subscope_real_uid : Scopelang.Ast.ScopeName.t = + Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes + in + let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in + ( Scopelang.Ast.ELocation + (SubScopeVar (assert false, (subscope_uid, pos), (subscope_var_uid, pos))), + pos ) + | _ -> + Name_resolution.raise_unsupported_feature + "left hand side of a dotted expression should be an\n\n identifier" pos ) + | FunCall (f, arg) -> (EApp (rec_helper f, [ rec_helper arg ]), pos) + | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos (* Translation from the parsed ast to the scope language *) -(* let merge_conditions (precond : Dcalc.Ast.term option) (cond : Dcalc.Ast.term option) - (default_pos : Pos.t) : Dcalc.Ast.term = match (precond, cond) with | Some precond, Some cond -> - let op_term = ((EOp (Binop And), Pos.get_position (fst precond))) in ((EApp (op_term, [ precond; - cond ]), Pos.get_position (fst precond))) | Some cond, None | None, Some cond -> cond | None, - None -> ((EBool true, default_pos), TBool) +let merge_conditions (precond : Scopelang.Ast.expr Pos.marked option) + (cond : Scopelang.Ast.expr Pos.marked option) (default_pos : Pos.t) : + Scopelang.Ast.expr Pos.marked = + match (precond, cond) with + | Some precond, Some cond -> + let op_term = (Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.And), Pos.get_position precond) in + (Scopelang.Ast.EApp (op_term, [ precond; cond ]), Pos.get_position precond) + | Some cond, None | None, Some cond -> cond + | None, None -> (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) - let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) (def_key - : Ast.ScopeDef.t) (def : Dcalc.Ast.default_term) (param_uid : Ast.LocalVar.t option) (precond : - Dcalc.Ast.term option) (just : Surface.Ast.expression Pos.marked option) (body : - Surface.Ast.expression Pos.marked) : Dcalc.Ast.default_term = let just = match just with | Some - cond -> Some (expr_to_lambda scope (Some def_key) ctxt cond) | None -> None in let condition = - merge_conditions precond just (Pos.get_position body) in let body = expr_to_lambda scope (Some - def_key) ctxt body in (* if there's a parameter, we have to wrap the justifiction and the body in - a func *) let condition, body = match param_uid with | None -> (condition, body) | Some param_uid - -> ( ((EFun ([ (param_uid) ], condition), Pos.get_position (fst condition))), ((EFun ([ - (param_uid) ], body), Pos.get_position (fst body))) ) in Dcalc.Ast.add_default condition body def *) +let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) + (def_key : Ast.ScopeDef.t) (_ef : Scopelang.Ast.expr Pos.marked) + (param_uid : Scopelang.Ast.Var.t option) (precond : Scopelang.Ast.expr Pos.marked option) + (just : Surface.Ast.expression Pos.marked option) (body : Surface.Ast.expression Pos.marked) : + Scopelang.Ast.expr Pos.marked = + let just = + match just with + | Some cond -> Some (translate_expr scope (Some def_key) ctxt cond) + | None -> None + in + let condition = merge_conditions precond just (Pos.get_position body) in + let body = translate_expr scope (Some def_key) ctxt body in + (* if there's a parameter, we have to wrap the justifiction and the body in a func *) + let _condition, _body = + match param_uid with + | None -> (condition, body) + | Some param_uid -> + ( Bindlib.unbox + (Scopelang.Ast.make_abs + (Array.of_list [ param_uid ]) + (Bindlib.box condition) (Pos.get_position condition) + [ assert false ] + (assert false)), + Bindlib.unbox + (Scopelang.Ast.make_abs + (Array.of_list [ param_uid ]) + (Bindlib.box body) (Pos.get_position body) + [ assert false ] + (assert false)) ) + in + assert false + +(* Dcalc.Ast.add_default condition body def *) (* Process a definition *) let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.ScopeName.t) @@ -72,7 +154,7 @@ let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.Sc let scope : Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in - let _param_uid (def_uid : Ast.ScopeDef.t) : Ast.LocalVar.t option = + let _param_uid (def_uid : Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = match def.definition_parameter with | None -> None | Some param -> diff --git a/src/catala/desugared/name_resolution.ml b/src/catala/desugared/name_resolution.ml index bc4b54a6..4efac009 100644 --- a/src/catala/desugared/name_resolution.ml +++ b/src/catala/desugared/name_resolution.ml @@ -22,7 +22,7 @@ type ident = string type typ = Dcalc.Ast.typ -type def_context = { var_idmap : Ast.LocalVar.t Ast.IdentMap.t } +type def_context = { var_idmap : Scopelang.Ast.Var.t Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern matching *) @@ -140,7 +140,7 @@ let add_def_local_var (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) (def_uid : Ast.ScopeDef.t) (name : ident Pos.marked) : context = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let def_ctx = Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in - let local_var_uid = Ast.LocalVar.fresh name in + let local_var_uid = Scopelang.Ast.Var.make name in let def_ctx = { var_idmap = Ast.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } in @@ -219,8 +219,8 @@ let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = var_idmap = ( match def.definition_parameter with | None -> Ast.IdentMap.empty - | Some param -> Ast.IdentMap.singleton (Pos.unmark param) (Ast.LocalVar.fresh param) - ); + | Some param -> + Ast.IdentMap.singleton (Pos.unmark param) (Scopelang.Ast.Var.make param) ); } in let scope_ctxt = diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index b4510371..d29399bc 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -34,6 +34,7 @@ type expr = | ELit of Dcalc.Ast.lit | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ list | EApp of expr Pos.marked * expr Pos.marked list + | EOp of Dcalc.Ast.operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked @@ -46,6 +47,18 @@ module Var = struct let compare x y = Bindlib.compare_vars x y end +type vars = expr Pos.marked Bindlib.mvar + +let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x + +let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) + (taus : Dcalc.Ast.typ list) (pos : Pos.t) : expr Pos.marked Bindlib.box = + Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, taus), pos)) (Bindlib.bind_mvar xs e) + +let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box list) (pos : Pos.t) + : expr Pos.marked Bindlib.box = + Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) + module VarMap = Map.Make (Var) type rule = diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 5fefb2b5..d1f5de7d 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -73,7 +73,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) | EIfThenElse (cond, et, ef) -> Dcalc.Ast.EIfThenElse (translate_expr ctx cond, translate_expr ctx et, translate_expr ctx ef) - ) + | EOp op -> EOp op ) e let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : From 444d0bdf32d1f89b40044ff07af4998a4b8a65f7 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 10:10:27 +0100 Subject: [PATCH 018/142] Reestablished desugaring --- src/catala/desugared/ast.ml | 22 +++++--- src/catala/desugared/desugaring.ml | 83 ++++++++++++------------------ src/catala/desugared/format.ml | 2 +- 3 files changed, 48 insertions(+), 59 deletions(-) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 20aa74b7..a6663846 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -49,14 +49,20 @@ module ScopeDefSet = Set.Make (ScopeDef) (* Scopes *) -type definition = Scopelang.Ast.expr Pos.marked +type rule = { + just : Scopelang.Ast.expr Pos.marked; + cons : Scopelang.Ast.expr Pos.marked; + parameter : Scopelang.Ast.Var.t option; + priority : int; +} -let empty_def (pos : Pos.t) : definition = - ( Scopelang.Ast.EDefault - ( (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos), - (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos), - [] ), - pos ) +let empty_def (pos : Pos.t) (have_parameter : bool) : rule = + { + just = (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); + cons = (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); + parameter = (if have_parameter then Some (Scopelang.Ast.Var.make ("dummy", pos)) else None); + priority = 0; + } type assertion = Scopelang.Ast.expr Pos.marked @@ -70,7 +76,7 @@ type meta_assertion = type scope = { scope_uid : Scopelang.Ast.ScopeName.t; - scope_defs : definition ScopeDefMap.t; + scope_defs : rule list ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } diff --git a/src/catala/desugared/desugaring.ml b/src/catala/desugared/desugaring.ml index fb3ff48d..c42bd136 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/desugared/desugaring.ml @@ -114,47 +114,28 @@ let merge_conditions (precond : Scopelang.Ast.expr Pos.marked option) | None, None -> (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) - (def_key : Ast.ScopeDef.t) (_ef : Scopelang.Ast.expr Pos.marked) - (param_uid : Scopelang.Ast.Var.t option) (precond : Scopelang.Ast.expr Pos.marked option) - (just : Surface.Ast.expression Pos.marked option) (body : Surface.Ast.expression Pos.marked) : - Scopelang.Ast.expr Pos.marked = + (def_key : Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t option) + (precond : Scopelang.Ast.expr Pos.marked option) + (just : Surface.Ast.expression Pos.marked option) (cons : Surface.Ast.expression Pos.marked) : + Ast.rule = let just = match just with - | Some cond -> Some (translate_expr scope (Some def_key) ctxt cond) + | Some just -> Some (translate_expr scope (Some def_key) ctxt just) | None -> None in - let condition = merge_conditions precond just (Pos.get_position body) in - let body = translate_expr scope (Some def_key) ctxt body in + let just = merge_conditions precond just (Pos.get_position cons) in + let cons = translate_expr scope (Some def_key) ctxt cons in (* if there's a parameter, we have to wrap the justifiction and the body in a func *) - let _condition, _body = - match param_uid with - | None -> (condition, body) - | Some param_uid -> - ( Bindlib.unbox - (Scopelang.Ast.make_abs - (Array.of_list [ param_uid ]) - (Bindlib.box condition) (Pos.get_position condition) - [ assert false ] - (assert false)), - Bindlib.unbox - (Scopelang.Ast.make_abs - (Array.of_list [ param_uid ]) - (Bindlib.box body) (Pos.get_position body) - [ assert false ] - (assert false)) ) - in - assert false - -(* Dcalc.Ast.add_default condition body def *) + { just; cons; parameter = param_uid; priority = 0 } (* Process a definition *) -let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.ScopeName.t) - (ctxt : Name_resolution.context) (prgm : Ast.program) (def : Surface.Ast.definition) : - Ast.program = +let process_def (precond : Scopelang.Ast.expr Pos.marked option) + (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) + (def : Surface.Ast.definition) : Ast.program = let scope : Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in - let _param_uid (def_uid : Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = + let param_uid (def_uid : Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = match def.definition_parameter with | None -> None | Some param -> @@ -178,26 +159,24 @@ let process_def (_precond : Dcalc.Ast.expr option) (scope_uid : Scopelang.Ast.Sc | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos in let scope_updated = - let _x_def = + let x_def = match Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def - | None -> - let _typ = Name_resolution.get_def_typ ctxt def_key in - Ast.empty_def default_pos + | None -> [ Ast.empty_def default_pos (Option.is_some (param_uid def_key)) ] in let x_def = - assert false - (* Dcalc.Ast.map_untype (fun t -> match t with | EDefault default -> EDefault (process_default - ctxt scope_uid def_key default (param_uid def_key) precond def.definition_condition - def.definition_expr) | _ -> assert false (* should not happen *)) x_def *) + process_default ctxt scope_uid def_key (param_uid def_key) precond def.definition_condition + def.definition_expr + :: x_def in { scope with scope_defs = Ast.ScopeDefMap.add def_key x_def scope.scope_defs } in Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm (** Process a rule from the surface language *) -let process_rule (precond : Dcalc.Ast.expr option) (scope : Scopelang.Ast.ScopeName.t) - (ctxt : Name_resolution.context) (prgm : Ast.program) (rule : Surface.Ast.rule) : Ast.program = +let process_rule (precond : Scopelang.Ast.expr Pos.marked option) + (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) + (rule : Surface.Ast.rule) : Ast.program = let _consequence_expr = Surface.Ast.Literal (Surface.Ast.Bool (Pos.unmark rule.rule_consequence)) in @@ -206,12 +185,13 @@ let process_rule (precond : Dcalc.Ast.expr option) (scope : Scopelang.Ast.ScopeN Pos.get_position rule.rule_consequence); } in *) process_def precond scope ctxt prgm (assert false (* def *)) -let process_scope_use_item (cond : Dcalc.Ast.expr option) (scope : Scopelang.Ast.ScopeName.t) - (ctxt : Name_resolution.context) (prgm : Ast.program) +let process_scope_use_item (precond : Surface.Ast.expression Pos.marked option) + (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) (item : Surface.Ast.scope_use_item Pos.marked) : Ast.program = + let precond = Option.map (translate_expr scope None ctxt) precond in match Pos.unmark item with - | Surface.Ast.Rule rule -> process_rule cond scope ctxt prgm rule - | Surface.Ast.Definition def -> process_def cond scope ctxt prgm def + | Surface.Ast.Rule rule -> process_rule precond scope ctxt prgm rule + | Surface.Ast.Definition def -> process_def precond scope ctxt prgm def | _ -> prgm let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) @@ -234,16 +214,19 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) List.fold_left (process_scope_use_item cond scope_uid ctxt) prgm use.scope_use_items (** Scopes processing *) -let translate_program_to_scope (_ctxt : Name_resolution.context) (prgm : Surface.Ast.program) : +let translate_program_to_scope (ctxt : Name_resolution.context) (prgm : Surface.Ast.program) : Ast.program = let empty_prgm = Scopelang.Ast.ScopeMap.empty in let processer_article_item (prgm : Ast.program) (item : Surface.Ast.law_article_item) : Ast.program = match item with - | CodeBlock (_block, _) -> - assert false - (* List.fold_left (fun prgm item -> match Pos.unmark item with ScopeUse use -> - process_scope_use ctxt prgm use | _ -> prgm) prgm block *) + | CodeBlock (block, _) -> + List.fold_left + (fun prgm item -> + match Pos.unmark item with + | Surface.Ast.ScopeUse use -> process_scope_use ctxt prgm use + | _ -> prgm) + prgm block | _ -> prgm in let rec processer_structure (prgm : Ast.program) (item : Surface.Ast.law_structure) : Ast.program diff --git a/src/catala/desugared/format.ml b/src/catala/desugared/format.ml index 76d77002..b2af8230 100644 --- a/src/catala/desugared/format.ml +++ b/src/catala/desugared/format.ml @@ -14,7 +14,7 @@ (** Print a scope program *) let print_scope (scope : Ast.scope) : string = - let print_defs (defs : Ast.definition Ast.ScopeDefMap.t) : string = + let print_defs (defs : Ast.rule list Ast.ScopeDefMap.t) : string = defs |> Ast.ScopeDefMap.bindings |> List.map (fun (uid, _term) -> Printf.sprintf "%s:\n%s" (Ast.ScopeDef.format_t uid) (assert false)) From b21737194f7dd6985387e8de9c5b8cf4de110847 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 10:49:53 +0100 Subject: [PATCH 019/142] Slowly connecting dots, missing a translation --- .../desugaring.ml | 111 ++++++------- src/catala/catala_surface/dune | 2 +- .../name_resolution.ml | 152 +++++++++--------- src/catala/desugared/dependency.ml | 58 +++---- src/catala/desugared/desugared_to_scope.ml | 15 ++ src/catala/desugared/dune | 2 +- src/catala/driver.ml | 20 +-- src/catala/scope_language/scope_to_dcalc.ml | 11 ++ 8 files changed, 181 insertions(+), 190 deletions(-) rename src/catala/{desugared => catala_surface}/desugaring.ml (68%) rename src/catala/{desugared => catala_surface}/name_resolution.ml (65%) create mode 100644 src/catala/desugared/desugared_to_scope.ml diff --git a/src/catala/desugared/desugaring.ml b/src/catala/catala_surface/desugaring.ml similarity index 68% rename from src/catala/desugared/desugaring.ml rename to src/catala/catala_surface/desugaring.ml index c42bd136..5add924b 100644 --- a/src/catala/desugared/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -18,7 +18,7 @@ module Errors = Utils.Errors (** The optional argument subdef allows to choose between differents uids in case the expression is a redefinition of a subvariable *) -let translate_binop (op : Surface.Ast.binop) : Dcalc.Ast.binop = +let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = match op with | And -> And | Or -> Or @@ -33,12 +33,11 @@ let translate_binop (op : Surface.Ast.binop) : Dcalc.Ast.binop = | Eq -> Eq | Neq -> Neq -let translate_unop (op : Surface.Ast.unop) : Dcalc.Ast.unop = - match op with Not -> Not | Minus -> Minus +let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | Minus -> Minus -let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeDef.t option) - (ctxt : Name_resolution.context) ((expr, pos) : Surface.Ast.expression Pos.marked) : - Scopelang.Ast.expr Pos.marked = +let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) + (def_key : Desugared.Ast.ScopeDef.t option) (ctxt : Name_resolution.context) + ((expr, pos) : Ast.expression Pos.marked) : Scopelang.Ast.expr Pos.marked = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in let rec_helper = translate_expr scope def_key ctxt in match expr with @@ -67,17 +66,17 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Ast.ScopeD (* first we check whether this is a local var, then we resort to scope-wide variables *) match def_key with | Some def_key -> ( - let def_ctxt = Ast.ScopeDefMap.find def_key scope_ctxt.definitions in - match Ast.IdentMap.find_opt x def_ctxt.var_idmap with + let def_ctxt = Desugared.Ast.ScopeDefMap.find def_key scope_ctxt.definitions in + match Desugared.Ast.IdentMap.find_opt x def_ctxt.var_idmap with | None -> ( - match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with + match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) | None -> Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" (x, pos) ) | Some uid -> (Scopelang.Ast.EVar uid, pos) ) | None -> ( - match Ast.IdentMap.find_opt x scope_ctxt.var_idmap with + match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) @@ -114,10 +113,9 @@ let merge_conditions (precond : Scopelang.Ast.expr Pos.marked option) | None, None -> (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) - (def_key : Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t option) - (precond : Scopelang.Ast.expr Pos.marked option) - (just : Surface.Ast.expression Pos.marked option) (cons : Surface.Ast.expression Pos.marked) : - Ast.rule = + (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t option) + (precond : Scopelang.Ast.expr Pos.marked option) (just : Ast.expression Pos.marked option) + (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = let just = match just with | Some just -> Some (translate_expr scope (Some def_key) ctxt just) @@ -130,23 +128,23 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop (* Process a definition *) let process_def (precond : Scopelang.Ast.expr Pos.marked option) - (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) - (def : Surface.Ast.definition) : Ast.program = - let scope : Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in + (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) + (prgm : Desugared.Ast.program) (def : Ast.definition) : Desugared.Ast.program = + let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in - let param_uid (def_uid : Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = + let param_uid (def_uid : Desugared.Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = match def.definition_parameter with | None -> None | Some param -> - let def_ctxt = Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in - Some (Ast.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) + let def_ctxt = Desugared.Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in + Some (Desugared.Ast.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) in let def_key = match Pos.unmark def.definition_name with | [ x ] -> let x_uid = Name_resolution.get_var_uid scope_uid ctxt x in - Ast.ScopeDef.Var x_uid + Desugared.Ast.ScopeDef.Var x_uid | [ y; x ] -> let subscope_uid : Scopelang.Ast.SubScopeName.t = Name_resolution.get_subscope_uid scope_uid ctxt y @@ -155,82 +153,78 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in let x_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in - Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid) + Desugared.Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid) | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos in let scope_updated = let x_def = - match Ast.ScopeDefMap.find_opt def_key scope.scope_defs with + match Desugared.Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def - | None -> [ Ast.empty_def default_pos (Option.is_some (param_uid def_key)) ] + | None -> [ Desugared.Ast.empty_def default_pos (Option.is_some (param_uid def_key)) ] in let x_def = process_default ctxt scope_uid def_key (param_uid def_key) precond def.definition_condition def.definition_expr :: x_def in - { scope with scope_defs = Ast.ScopeDefMap.add def_key x_def scope.scope_defs } + { scope with scope_defs = Desugared.Ast.ScopeDefMap.add def_key x_def scope.scope_defs } in Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm (** Process a rule from the surface language *) let process_rule (precond : Scopelang.Ast.expr Pos.marked option) - (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) - (rule : Surface.Ast.rule) : Ast.program = - let _consequence_expr = - Surface.Ast.Literal (Surface.Ast.Bool (Pos.unmark rule.rule_consequence)) + (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) + (prgm : Desugared.Ast.program) (rule : Ast.rule) : Desugared.Ast.program = + let consequence_expr = Ast.Literal (Ast.Bool (Pos.unmark rule.rule_consequence)) in + let def = + { + Ast.definition_name = rule.rule_name; + Ast.definition_parameter = rule.rule_parameter; + Ast.definition_condition = rule.rule_condition; + Ast.definition_expr = (consequence_expr, Pos.get_position rule.rule_consequence); + } in - (* let def = { definition_name = rule.rule_name; definition_parameter = rule.rule_parameter; - definition_condition = rule.rule_condition; definition_expr = (consequence_expr, - Pos.get_position rule.rule_consequence); } in *) - process_def precond scope ctxt prgm (assert false (* def *)) + process_def precond scope ctxt prgm def -let process_scope_use_item (precond : Surface.Ast.expression Pos.marked option) - (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Ast.program) - (item : Surface.Ast.scope_use_item Pos.marked) : Ast.program = +let process_scope_use_item (precond : Ast.expression Pos.marked option) + (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) + (prgm : Desugared.Ast.program) (item : Ast.scope_use_item Pos.marked) : Desugared.Ast.program = let precond = Option.map (translate_expr scope None ctxt) precond in match Pos.unmark item with - | Surface.Ast.Rule rule -> process_rule precond scope ctxt prgm rule - | Surface.Ast.Definition def -> process_def precond scope ctxt prgm def + | Ast.Rule rule -> process_rule precond scope ctxt prgm rule + | Ast.Definition def -> process_def precond scope ctxt prgm def | _ -> prgm -let process_scope_use (ctxt : Name_resolution.context) (prgm : Ast.program) - (use : Surface.Ast.scope_use) : Ast.program = +let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) + (use : Ast.scope_use) : Desugared.Ast.program = let name = fst use.scope_use_name in - let scope_uid = Ast.IdentMap.find name ctxt.scope_idmap in + let scope_uid = Desugared.Ast.IdentMap.find name ctxt.scope_idmap in (* Make sure the scope exists *) let prgm = match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with | Some _ -> prgm - | None -> Scopelang.Ast.ScopeMap.add scope_uid (Ast.empty_scope scope_uid) prgm + | None -> Scopelang.Ast.ScopeMap.add scope_uid (Desugared.Ast.empty_scope scope_uid) prgm in - let cond = - match use.scope_use_condition with - | Some _expr -> - let untyped_term = assert false (* expr_to_lambda scope_uid None ctxt expr *) in - Some untyped_term - | None -> None - in - List.fold_left (process_scope_use_item cond scope_uid ctxt) prgm use.scope_use_items + let precond = use.scope_use_condition in + List.fold_left (process_scope_use_item precond scope_uid ctxt) prgm use.scope_use_items (** Scopes processing *) -let translate_program_to_scope (ctxt : Name_resolution.context) (prgm : Surface.Ast.program) : - Ast.program = +let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desugared.Ast.program = let empty_prgm = Scopelang.Ast.ScopeMap.empty in - let processer_article_item (prgm : Ast.program) (item : Surface.Ast.law_article_item) : - Ast.program = + let processer_article_item (prgm : Desugared.Ast.program) (item : Ast.law_article_item) : + Desugared.Ast.program = match item with | CodeBlock (block, _) -> List.fold_left (fun prgm item -> match Pos.unmark item with - | Surface.Ast.ScopeUse use -> process_scope_use ctxt prgm use + | Ast.ScopeUse use -> process_scope_use ctxt prgm use | _ -> prgm) prgm block | _ -> prgm in - let rec processer_structure (prgm : Ast.program) (item : Surface.Ast.law_structure) : Ast.program - = + let rec processer_structure (prgm : Desugared.Ast.program) (item : Ast.law_structure) : + Desugared.Ast.program = match item with | LawHeading (_, children) -> List.fold_left (fun prgm child -> processer_structure prgm child) prgm children @@ -240,7 +234,8 @@ let translate_program_to_scope (ctxt : Name_resolution.context) (prgm : Surface. | IntermediateText _ -> prgm in - let processer_item (prgm : Ast.program) (item : Surface.Ast.program_item) : Ast.program = + let processer_item (prgm : Desugared.Ast.program) (item : Ast.program_item) : + Desugared.Ast.program = match item with LawStructure s -> processer_structure prgm s in diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index 24fe0376..51311e8d 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -1,6 +1,6 @@ (library (name surface) - (libraries utils menhirLib sedlex re) + (libraries utils menhirLib sedlex re desugared scopelang) (public_name catala.surface) (preprocess (pps sedlex.ppx))) diff --git a/src/catala/desugared/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml similarity index 65% rename from src/catala/desugared/name_resolution.ml rename to src/catala/catala_surface/name_resolution.ml index 4efac009..f69a19c8 100644 --- a/src/catala/desugared/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -22,21 +22,21 @@ type ident = string type typ = Dcalc.Ast.typ -type def_context = { var_idmap : Scopelang.Ast.Var.t Ast.IdentMap.t } +type def_context = { var_idmap : Scopelang.Ast.Var.t Desugared.Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern matching *) type scope_context = { - var_idmap : Scopelang.Ast.ScopeVar.t Ast.IdentMap.t; - sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Ast.IdentMap.t; + var_idmap : Scopelang.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; + sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Desugared.Ast.IdentMap.t; sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; - definitions : def_context Ast.ScopeDefMap.t; + definitions : def_context Desugared.Ast.ScopeDefMap.t; (** Contains the local variables in all the definitions *) } (** Inside a scope, we distinguish between the variables and the subscopes. *) type context = { - scope_idmap : Scopelang.Ast.ScopeName.t Ast.IdentMap.t; + scope_idmap : Scopelang.Ast.ScopeName.t Desugared.Ast.IdentMap.t; scopes : scope_context Scopelang.Ast.ScopeMap.t; var_typs : typ Pos.marked Scopelang.Ast.ScopeVarMap.t; } @@ -55,11 +55,11 @@ let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ Pos.mark (** Process a subscope declaration *) let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) - (decl : Surface.Ast.scope_decl_context_scope) : context = + (decl : 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 = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in - match Ast.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with + match Desugared.Ast.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with | Some use -> Errors.raise_multispanned_error "subscope name already used" [ @@ -69,48 +69,47 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) | None -> let sub_scope_uid = Scopelang.Ast.SubScopeName.fresh (name, name_pos) in let original_subscope_uid = - match Ast.IdentMap.find_opt subscope ctxt.scope_idmap with + match Desugared.Ast.IdentMap.find_opt subscope ctxt.scope_idmap with | None -> raise_unknown_identifier "for a scope" (subscope, s_pos) | Some id -> id in let scope_ctxt = { scope_ctxt with - sub_scopes_idmap = Ast.IdentMap.add name sub_scope_uid scope_ctxt.sub_scopes_idmap; + sub_scopes_idmap = + Desugared.Ast.IdentMap.add name sub_scope_uid scope_ctxt.sub_scopes_idmap; sub_scopes = Scopelang.Ast.SubScopeMap.add sub_scope_uid original_subscope_uid scope_ctxt.sub_scopes; } in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } -let process_base_typ ((typ, typ_pos) : Surface.Ast.base_typ Pos.marked) : Dcalc.Ast.typ Pos.marked = +let process_base_typ ((typ, typ_pos) : Ast.base_typ Pos.marked) : Dcalc.Ast.typ Pos.marked = match typ with - | Surface.Ast.Condition -> (Dcalc.Ast.TBool, typ_pos) - | Surface.Ast.Data (Surface.Ast.Collection _) -> - raise_unsupported_feature "collection type" typ_pos - | Surface.Ast.Data (Surface.Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos - | Surface.Ast.Data (Surface.Ast.Primitive prim) -> ( + | Ast.Condition -> (Dcalc.Ast.TBool, typ_pos) + | Ast.Data (Ast.Collection _) -> raise_unsupported_feature "collection type" typ_pos + | Ast.Data (Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos + | Ast.Data (Ast.Primitive prim) -> ( match prim with - | Surface.Ast.Integer | Surface.Ast.Decimal | Surface.Ast.Money | Surface.Ast.Date -> - assert false - | Surface.Ast.Boolean -> (Dcalc.Ast.TBool, typ_pos) - | Surface.Ast.Text -> raise_unsupported_feature "text type" typ_pos - | Surface.Ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) + | Ast.Integer | Ast.Decimal | Ast.Money | Ast.Date -> assert false + | Ast.Boolean -> (Dcalc.Ast.TBool, typ_pos) + | Ast.Text -> raise_unsupported_feature "text type" typ_pos + | Ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) -let process_type ((typ, typ_pos) : Surface.Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = +let process_type ((typ, typ_pos) : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = match typ with - | Surface.Ast.Base base_typ -> process_base_typ (base_typ, typ_pos) - | Surface.Ast.Func { arg_typ; return_typ } -> + | Ast.Base base_typ -> process_base_typ (base_typ, typ_pos) + | Ast.Func { arg_typ; return_typ } -> (Dcalc.Ast.TArrow (process_base_typ arg_typ, process_base_typ return_typ), typ_pos) (** Process data declaration *) let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) - (decl : Surface.Ast.scope_decl_context_data) : context = + (decl : Ast.scope_decl_context_data) : context = (* First check the type of the context data *) let data_typ = process_type decl.scope_decl_context_item_typ in let name, pos = decl.scope_decl_context_item_name in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in - match Ast.IdentMap.find_opt name scope_ctxt.var_idmap with + match Desugared.Ast.IdentMap.find_opt name scope_ctxt.var_idmap with | Some use -> Errors.raise_multispanned_error "var name already used" [ @@ -120,7 +119,7 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) | None -> let uid = Scopelang.Ast.ScopeVar.fresh (name, pos) in let scope_ctxt = - { scope_ctxt with var_idmap = Ast.IdentMap.add name uid scope_ctxt.var_idmap } + { scope_ctxt with var_idmap = Desugared.Ast.IdentMap.add name uid scope_ctxt.var_idmap } in { ctxt with @@ -130,30 +129,33 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (** Process an item declaration *) let process_item_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) - (decl : Surface.Ast.scope_decl_context_item) : context = + (decl : Ast.scope_decl_context_item) : context = match decl with - | Surface.Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl - | Surface.Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl + | Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl + | Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl (** Adds a binding to the context *) let add_def_local_var (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) - (def_uid : Ast.ScopeDef.t) (name : ident Pos.marked) : context = + (def_uid : Desugared.Ast.ScopeDef.t) (name : ident Pos.marked) : context = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - let def_ctx = Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in + let def_ctx = Desugared.Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in let local_var_uid = Scopelang.Ast.Var.make name in let def_ctx = - { var_idmap = Ast.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } + { var_idmap = Desugared.Ast.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } in let scope_ctxt = - { scope_ctxt with definitions = Ast.ScopeDefMap.add def_uid def_ctx scope_ctxt.definitions } + { + scope_ctxt with + definitions = Desugared.Ast.ScopeDefMap.add def_uid def_ctx scope_ctxt.definitions; + } in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } (** Process a scope declaration *) -let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : context = +let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = let name, pos = decl.scope_decl_name in (* Checks if the name is already used *) - match Ast.IdentMap.find_opt name ctxt.scope_idmap with + match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with | Some use -> Errors.raise_multispanned_error "scope name already used" [ @@ -165,13 +167,13 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : contex let ctxt = { ctxt with - scope_idmap = Ast.IdentMap.add name scope_uid ctxt.scope_idmap; + scope_idmap = Desugared.Ast.IdentMap.add name scope_uid ctxt.scope_idmap; scopes = Scopelang.Ast.ScopeMap.add scope_uid { - var_idmap = Ast.IdentMap.empty; - sub_scopes_idmap = Ast.IdentMap.empty; - definitions = Ast.ScopeDefMap.empty; + var_idmap = Desugared.Ast.IdentMap.empty; + sub_scopes_idmap = Desugared.Ast.IdentMap.empty; + definitions = Desugared.Ast.ScopeDefMap.empty; sub_scopes = Scopelang.Ast.SubScopeMap.empty; } ctxt.scopes; @@ -182,51 +184,52 @@ let process_scope_decl (ctxt : context) (decl : Surface.Ast.scope_decl) : contex ctxt decl.scope_decl_context let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) - (id : Surface.Ast.qident Pos.marked) : Ast.ScopeDef.t = + (id : Ast.qident Pos.marked) : Desugared.Ast.ScopeDef.t = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in match Pos.unmark id with | [ x ] -> ( - match Ast.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with + match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with | None -> raise_unknown_identifier "for a var of the scope" x - | Some id -> Ast.ScopeDef.Var id ) + | Some id -> Desugared.Ast.ScopeDef.Var id ) | [ s; x ] -> ( let sub_scope_uid = - match Ast.IdentMap.find_opt (Pos.unmark s) scope_ctxt.sub_scopes_idmap with + match Desugared.Ast.IdentMap.find_opt (Pos.unmark s) scope_ctxt.sub_scopes_idmap with | None -> raise_unknown_identifier "for a subscope of this scope" s | Some id -> id in let real_sub_scope_uid = Scopelang.Ast.SubScopeMap.find sub_scope_uid scope_ctxt.sub_scopes in let sub_scope_ctx = Scopelang.Ast.ScopeMap.find real_sub_scope_uid ctxt.scopes in - match Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with + match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with | None -> raise_unknown_identifier "for a var of this subscope" x - | Some id -> Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) + | Some id -> Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) | _ -> raise_unsupported_feature "wrong qident" (Pos.get_position id) -let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = +let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = let scope_uid = - match Ast.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with + match Desugared.Ast.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with | None -> raise_unknown_identifier "for a scope" use.scope_use_name | Some id -> id in List.fold_left (fun ctxt use_item -> match Pos.unmark use_item with - | Surface.Ast.Definition def -> + | Ast.Definition def -> let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let def_uid = qident_to_scope_def ctxt scope_uid def.definition_name in let def_ctxt = { var_idmap = ( match def.definition_parameter with - | None -> Ast.IdentMap.empty + | None -> Desugared.Ast.IdentMap.empty | Some param -> - Ast.IdentMap.singleton (Pos.unmark param) (Scopelang.Ast.Var.make param) ); + Desugared.Ast.IdentMap.singleton (Pos.unmark param) + (Scopelang.Ast.Var.make param) ); } in let scope_ctxt = { scope_ctxt with - definitions = Ast.ScopeDefMap.add def_uid def_ctxt scope_ctxt.definitions; + definitions = Desugared.Ast.ScopeDefMap.add def_uid def_ctxt scope_ctxt.definitions; } in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } @@ -234,50 +237,49 @@ let process_scope_use (ctxt : context) (use : Surface.Ast.scope_use) : context = ctxt use.scope_use_items (** Process a code item : for now it only handles scope decls *) -let process_use_item (ctxt : context) (item : Surface.Ast.code_item Pos.marked) : context = +let process_use_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = match Pos.unmark item with | ScopeDecl _ -> ctxt | ScopeUse use -> process_scope_use ctxt use | _ -> raise_unsupported_feature "item not supported" (Pos.get_position item) (** Process a code item : for now it only handles scope decls *) -let process_decl_item (ctxt : context) (item : Surface.Ast.code_item Pos.marked) : context = +let process_decl_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = match Pos.unmark item with ScopeDecl decl -> process_scope_decl ctxt decl | _ -> ctxt (** Process a code block *) -let process_code_block (ctxt : context) (block : Surface.Ast.code_block) - (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = +let process_code_block (ctxt : context) (block : Ast.code_block) + (process_item : context -> Ast.code_item Pos.marked -> context) : context = List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block (** Process a program item *) -let process_law_article_item (ctxt : context) (item : Surface.Ast.law_article_item) - (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = +let process_law_article_item (ctxt : context) (item : Ast.law_article_item) + (process_item : context -> Ast.code_item Pos.marked -> context) : context = match item with CodeBlock (block, _) -> process_code_block ctxt block process_item | _ -> ctxt (** Process a law structure *) -let rec process_law_structure (ctxt : context) (s : Surface.Ast.law_structure) - (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = +let rec process_law_structure (ctxt : context) (s : Ast.law_structure) + (process_item : context -> Ast.code_item Pos.marked -> context) : context = match s with - | Surface.Ast.LawHeading (_, children) -> + | Ast.LawHeading (_, children) -> List.fold_left (fun ctxt child -> process_law_structure ctxt child process_item) ctxt children - | Surface.Ast.LawArticle (_, children) -> + | Ast.LawArticle (_, children) -> List.fold_left (fun ctxt child -> process_law_article_item ctxt child process_item) ctxt children - | Surface.Ast.MetadataBlock (b, c) -> - process_law_article_item ctxt (Surface.Ast.CodeBlock (b, c)) process_item - | Surface.Ast.IntermediateText _ -> ctxt + | Ast.MetadataBlock (b, c) -> process_law_article_item ctxt (Ast.CodeBlock (b, c)) process_item + | Ast.IntermediateText _ -> ctxt (** Process a program item *) -let process_program_item (ctxt : context) (item : Surface.Ast.program_item) - (process_item : context -> Surface.Ast.code_item Pos.marked -> context) : context = - match item with Surface.Ast.LawStructure s -> process_law_structure ctxt s process_item +let process_program_item (ctxt : context) (item : Ast.program_item) + (process_item : context -> Ast.code_item Pos.marked -> context) : context = + match item with Ast.LawStructure s -> process_law_structure ctxt s process_item (** Derive the context from metadata, in two passes *) -let form_context (prgm : Surface.Ast.program) : context = +let form_context (prgm : Ast.program) : context = let empty_ctxt = { - scope_idmap = Ast.IdentMap.empty; + scope_idmap = Desugared.Ast.IdentMap.empty; scopes = Scopelang.Ast.ScopeMap.empty; var_typs = Scopelang.Ast.ScopeVarMap.empty; } @@ -295,7 +297,7 @@ let form_context (prgm : Surface.Ast.program) : context = let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) ((x, pos) : ident Pos.marked) : Scopelang.Ast.ScopeVar.t = let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - match Ast.IdentMap.find_opt x scope.var_idmap with + match Desugared.Ast.IdentMap.find_opt x scope.var_idmap with | None -> raise_unknown_identifier "for a var of this scope" (x, pos) | Some uid -> uid @@ -303,7 +305,7 @@ let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) ((y, pos) : ident Pos.marked) : Scopelang.Ast.SubScopeName.t = let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - match Ast.IdentMap.find_opt y scope.sub_scopes_idmap with + match Desugared.Ast.IdentMap.find_opt y scope.sub_scopes_idmap with | None -> raise_unknown_identifier "for a subscope of this scope" (y, pos) | Some sub_uid -> sub_uid @@ -311,14 +313,14 @@ let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) (scope_uid : Scopelang.Ast.ScopeName.t) : bool = let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - Ast.IdentMap.exists + Desugared.Ast.IdentMap.exists (fun _ var_uid -> Scopelang.Ast.ScopeVar.compare uid var_uid = 0) scope.var_idmap -let get_def_typ (ctxt : context) (def : Ast.ScopeDef.t) : typ Pos.marked = +let get_def_typ (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : typ Pos.marked = match def with - | Ast.ScopeDef.SubScopeVar (_, x) + | Desugared.Ast.ScopeDef.SubScopeVar (_, x) (* we don't need to look at the subscope prefix because [x] is already the uid referring back to the original subscope *) - | Ast.ScopeDef.Var x -> + | Desugared.Ast.ScopeDef.Var x -> Scopelang.Ast.ScopeVarMap.find x ctxt.var_typs diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index 66b5e10a..846a4f3b 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -92,43 +92,21 @@ let check_for_cycle (g : ScopeDependencies.t) : unit = ]) scc)) -let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context) : - ScopeDependencies.t = - let g = ScopeDependencies.empty in - let scope_uid = scope.scope_uid in - (* Add all the vertices to the graph *) - let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - let g = - Ast.IdentMap.fold - (fun _ (v : Scopelang.Ast.ScopeVar.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) - scope_ctxt.var_idmap g - in - let g = - Ast.IdentMap.fold - (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> - ScopeDependencies.add_vertex g (Vertex.SubScope v)) - scope_ctxt.sub_scopes_idmap g - in - let g = - Ast.ScopeDefMap.fold - (fun def_key _def g -> - let fv = assert false (* Dcalc.Ast.term_fv def *) in - Ast.ScopeDefSet.fold - (fun fv_def g -> - match (def_key, fv_def) with - | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> - (* simple case *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) - | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> - (* here we are defining the input of a subscope using a var of the scope *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) - | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar (used, _) -> - (* here we are defining the input of a scope with the output of another subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) - | Ast.ScopeDef.Var defined, Ast.ScopeDef.SubScopeVar (used, _) -> - (* finally we define a scope var with the output of a subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) - fv g) - scope.scope_defs g - in - g +(* let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context) : + ScopeDependencies.t = let g = ScopeDependencies.empty in let scope_uid = scope.scope_uid in (* + Add all the vertices to the graph *) let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid + ctxt.scopes in let g = Ast.IdentMap.fold (fun _ (v : Scopelang.Ast.ScopeVar.t) g -> + ScopeDependencies.add_vertex g (Vertex.Var v)) scope_ctxt.var_idmap g in let g = + Ast.IdentMap.fold (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> ScopeDependencies.add_vertex g + (Vertex.SubScope v)) scope_ctxt.sub_scopes_idmap g in let g = Ast.ScopeDefMap.fold (fun def_key + _def g -> let fv = assert false (* Dcalc.Ast.term_fv def *) in Ast.ScopeDefSet.fold (fun fv_def g + -> match (def_key, fv_def) with | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> (* simple + case *) ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) | + Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> (* here we are defining the input + of a subscope using a var of the scope *) ScopeDependencies.add_edge g (Vertex.Var used) + (Vertex.SubScope defined) | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar + (used, _) -> (* here we are defining the input of a scope with the output of another subscope *) + ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) | Ast.ScopeDef.Var + defined, Ast.ScopeDef.SubScopeVar (used, _) -> (* finally we define a scope var with the output + of a subscope *) ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) fv g) + scope.scope_defs g in g *) diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml new file mode 100644 index 00000000..ab7432a1 --- /dev/null +++ b/src/catala/desugared/desugared_to_scope.ml @@ -0,0 +1,15 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + in compliance with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software distributed under the License + is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the License for the specific language governing permissions and limitations under + the License. *) + +let translate_program (_pgrm : Ast.program) : Scopelang.Ast.program = assert false diff --git a/src/catala/desugared/dune b/src/catala/desugared/dune index 48e8bf21..9faaba52 100644 --- a/src/catala/desugared/dune +++ b/src/catala/desugared/dune @@ -1,4 +1,4 @@ (library (name desugared) (public_name catala.desugared) - (libraries utils dcalc scopelang ocamlgraph surface)) + (libraries utils dcalc scopelang ocamlgraph)) diff --git a/src/catala/driver.ml b/src/catala/driver.ml index fd44497a..567397fc 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -96,7 +96,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ close_out oc; 0 | Cli.Run -> - let ctxt = Desugared.Name_resolution.form_context program in + let ctxt = Surface.Name_resolution.form_context program in let scope_uid = match ex_scope with | None -> Errors.raise_error "No scope was provided for execution." @@ -107,20 +107,10 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ (Printf.sprintf "There is no scope %s inside the program." name) | Some uid -> uid ) in - let prgm = Desugared.Desugaring.translate_program_to_scope ctxt program in - let _scope = - match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with - | Some scope -> scope - | None -> - let scope_info = Scopelang.Ast.ScopeName.get_info scope_uid in - Errors.raise_spanned_error - (Printf.sprintf - "Scope %s does not define anything, and therefore cannot be executed" - (Utils.Pos.unmark scope_info)) - (Utils.Pos.get_position scope_info) - in - (* let exec_ctxt = Desugared.Interpreter.execute_scope ctxt prgm scope in - Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print + let prgm = Surface.Desugaring.desugar_program ctxt program in + let prgm = Desugared.Desugared_to_scope.translate_program prgm in + let _prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in + (* Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) 0 diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index d1f5de7d..1a5236f8 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -125,6 +125,7 @@ let translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) : let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked = let ctx = empty_ctx in + (* TODO: compute dependency order! *) let rules, ctx = translate_rules p ctx sigma.scope_decl_rules in let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in @@ -144,3 +145,13 @@ let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.ex in let func_acc = Bindlib.unbox (Bindlib.bind_var hole_var func_acc) in Bindlib.subst func_acc (return_exp, pos_sigma) + +let translate_program (prgm : Ast.program) (_top_level_scope : Ast.ScopeName.t) : + Dcalc.Ast.expr Pos.marked = + let _scope_ctx = + Ast.ScopeMap.map + (fun scope -> Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) + prgm + in + (* TODO: compute dependency order! *) + assert false From 89ef30b8daba199b01cbaea51ddc1bab0e1606e9 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 11:53:56 +0100 Subject: [PATCH 020/142] Reestablished scope dependency computation --- src/catala/catala_surface/desugaring.ml | 12 +++- src/catala/catala_surface/dune | 3 + src/catala/default_calculus/dune | 3 + src/catala/desugared/ast.ml | 35 ++++++++-- src/catala/desugared/dependency.ml | 77 +++++++++++++-------- src/catala/desugared/dune | 3 + src/catala/desugared/format.ml | 32 --------- src/catala/scope_language/ast.ml | 16 +++++ src/catala/scope_language/dune | 3 + src/catala/scope_language/scope_to_dcalc.ml | 1 - src/catala/utils/uid.ml | 5 +- src/catala/utils/uid.mli | 2 +- 12 files changed, 121 insertions(+), 71 deletions(-) delete mode 100644 src/catala/desugared/format.ml diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 5add924b..b1613684 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -199,11 +199,21 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.pro (use : Ast.scope_use) : Desugared.Ast.program = let name = fst use.scope_use_name in let scope_uid = Desugared.Ast.IdentMap.find name ctxt.scope_idmap in + let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + let scope_vars = + List.fold_left + (fun acc (_, var) -> Scopelang.Ast.ScopeVarSet.add var acc) + Scopelang.Ast.ScopeVarSet.empty + (Desugared.Ast.IdentMap.bindings scope_ctxt.var_idmap) + in (* Make sure the scope exists *) let prgm = match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with | Some _ -> prgm - | None -> Scopelang.Ast.ScopeMap.add scope_uid (Desugared.Ast.empty_scope scope_uid) prgm + | None -> + Scopelang.Ast.ScopeMap.add scope_uid + (Desugared.Ast.empty_scope scope_uid scope_vars scope_ctxt.sub_scopes) + prgm in let precond = use.scope_use_condition in List.fold_left (process_scope_use_item precond scope_uid ctxt) prgm use.scope_use_items diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index 51311e8d..628afd70 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -8,3 +8,6 @@ (menhir (modules parser) (flags --table)) + +(documentation + (package catala)) diff --git a/src/catala/default_calculus/dune b/src/catala/default_calculus/dune index feeb8fd6..1f3b7ee8 100644 --- a/src/catala/default_calculus/dune +++ b/src/catala/default_calculus/dune @@ -2,3 +2,6 @@ (name dcalc) (public_name catala.dcalc) (libraries bindlib unionFind utils)) + +(documentation + (package catala)) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index a6663846..16c58850 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -30,13 +30,12 @@ module ScopeDef = struct Scopelang.Ast.ScopeVar.compare x y | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.SubScopeName.compare x y - let format_t x = + let format_t fmt x = match x with - | Var v -> Scopelang.Ast.ScopeVar.format_t v + | Var v -> Scopelang.Ast.ScopeVar.format_t fmt v | SubScopeVar (s, v) -> - Printf.sprintf "%s.%s" - (Scopelang.Ast.SubScopeName.format_t s) - (Scopelang.Ast.ScopeVar.format_t v) + Format.fprintf fmt "%a.%a" Scopelang.Ast.SubScopeName.format_t s + Scopelang.Ast.ScopeVar.format_t v let hash x = match x with @@ -75,18 +74,40 @@ type meta_assertion = | VariesWith of unit * variation_typ Pos.marked option type scope = { + scope_vars : Scopelang.Ast.ScopeVarSet.t; + scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; scope_uid : Scopelang.Ast.ScopeName.t; scope_defs : rule list ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } -let empty_scope (uid : Scopelang.Ast.ScopeName.t) : scope = +let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang.Ast.ScopeVarSet.t) + (scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t) : scope = { - scope_uid = uid; + scope_uid; + scope_vars; + scope_sub_scopes; scope_defs = ScopeDefMap.empty; scope_assertions = []; scope_meta_assertions = []; } type program = scope Scopelang.Ast.ScopeMap.t + +let free_variables (def : rule list) : ScopeDefSet.t = + let add_locs (acc : ScopeDefSet.t) (locs : Scopelang.Ast.location list) : ScopeDefSet.t = + List.fold_left + (fun acc loc -> + ScopeDefSet.add + ( match loc with + | Scopelang.Ast.ScopeVar v -> ScopeDef.Var (Pos.unmark v) + | _ -> assert false ) + acc) + acc locs + in + List.fold_left + (fun acc rule -> + let locs = Scopelang.Ast.locations_used rule.just @ Scopelang.Ast.locations_used rule.cons in + add_locs acc locs) + ScopeDefSet.empty def diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index 846a4f3b..f073a1c4 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -40,10 +40,10 @@ module Vertex = struct | SubScope x, SubScope y -> Scopelang.Ast.SubScopeName.compare x y = 0 | _ -> false - let format_t (x : t) : string = + let format_t (fmt : Format.formatter) (x : t) : unit = match x with - | Var v -> Scopelang.Ast.ScopeVar.format_t v - | SubScope v -> Scopelang.Ast.SubScopeName.format_t v + | Var v -> Scopelang.Ast.ScopeVar.format_t fmt v + | SubScope v -> Scopelang.Ast.SubScopeName.format_t fmt v end (** On the edges, the label is the expression responsible for the use of the variable *) @@ -62,28 +62,32 @@ module SCC = Graph.Components.Make (ScopeDependencies) (** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) (** Outputs an error in case of cycles. *) -let check_for_cycle (g : ScopeDependencies.t) : unit = +let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) let sccs = SCC.scc_list g in if List.length sccs < ScopeDependencies.nb_vertex g then let scc = List.find (fun scc -> List.length scc > 1) sccs in - Errors.raise_multispanned_error "cyclic dependency dected between variables!" + Errors.raise_multispanned_error + (Format.asprintf "cyclic dependency detected between variables of scope %a !" + Scopelang.Ast.ScopeName.format_t scope.scope_uid) (List.flatten (List.map (fun v -> let var_str, var_info = match v with | Vertex.Var v -> - (Scopelang.Ast.ScopeVar.format_t v, Scopelang.Ast.ScopeVar.get_info v) + ( Format.asprintf "%a" Scopelang.Ast.ScopeVar.format_t v, + Scopelang.Ast.ScopeVar.get_info v ) | Vertex.SubScope v -> - (Scopelang.Ast.SubScopeName.format_t v, Scopelang.Ast.SubScopeName.get_info v) + ( Format.asprintf "%a" Scopelang.Ast.SubScopeName.format_t v, + Scopelang.Ast.SubScopeName.get_info v ) in let succs = ScopeDependencies.succ_e g v in let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in let succ_str = match succ with - | Vertex.Var v -> Scopelang.Ast.ScopeVar.format_t v - | Vertex.SubScope v -> Scopelang.Ast.SubScopeName.format_t v + | Vertex.Var v -> Format.asprintf "%a" Scopelang.Ast.ScopeVar.format_t v + | Vertex.SubScope v -> Format.asprintf "%a" Scopelang.Ast.SubScopeName.format_t v in [ (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); @@ -92,21 +96,40 @@ let check_for_cycle (g : ScopeDependencies.t) : unit = ]) scc)) -(* let build_scope_dependencies (scope : Ast.scope) (ctxt : Name_resolution.context) : - ScopeDependencies.t = let g = ScopeDependencies.empty in let scope_uid = scope.scope_uid in (* - Add all the vertices to the graph *) let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid - ctxt.scopes in let g = Ast.IdentMap.fold (fun _ (v : Scopelang.Ast.ScopeVar.t) g -> - ScopeDependencies.add_vertex g (Vertex.Var v)) scope_ctxt.var_idmap g in let g = - Ast.IdentMap.fold (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> ScopeDependencies.add_vertex g - (Vertex.SubScope v)) scope_ctxt.sub_scopes_idmap g in let g = Ast.ScopeDefMap.fold (fun def_key - _def g -> let fv = assert false (* Dcalc.Ast.term_fv def *) in Ast.ScopeDefSet.fold (fun fv_def g - -> match (def_key, fv_def) with | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> (* simple - case *) ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) | - Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> (* here we are defining the input - of a subscope using a var of the scope *) ScopeDependencies.add_edge g (Vertex.Var used) - (Vertex.SubScope defined) | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar - (used, _) -> (* here we are defining the input of a scope with the output of another subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) | Ast.ScopeDef.Var - defined, Ast.ScopeDef.SubScopeVar (used, _) -> (* finally we define a scope var with the output - of a subscope *) ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) fv g) - scope.scope_defs g in g *) +let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = + let g = ScopeDependencies.empty in + (* Add all the vertices to the graph *) + let g = + Scopelang.Ast.ScopeVarSet.fold + (fun (v : Scopelang.Ast.ScopeVar.t) g -> ScopeDependencies.add_vertex g (Vertex.Var v)) + scope.scope_vars g + in + let g = + Scopelang.Ast.SubScopeMap.fold + (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> + ScopeDependencies.add_vertex g (Vertex.SubScope v)) + scope.scope_sub_scopes g + in + let g = + Ast.ScopeDefMap.fold + (fun def_key def g -> + let fv = Ast.free_variables def in + Ast.ScopeDefSet.fold + (fun fv_def g -> + match (def_key, fv_def) with + | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> + (* simple case *) + ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) + | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> + (* here we are defining the input of a subscope using a var of the scope *) + ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) + | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar (used, _) -> + (* here we are defining the input of a scope with the output of another subscope *) + ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) + | Ast.ScopeDef.Var defined, Ast.ScopeDef.SubScopeVar (used, _) -> + (* finally we define a scope var with the output of a subscope *) + ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) + fv g) + scope.scope_defs g + in + g diff --git a/src/catala/desugared/dune b/src/catala/desugared/dune index 9faaba52..18e8eb47 100644 --- a/src/catala/desugared/dune +++ b/src/catala/desugared/dune @@ -2,3 +2,6 @@ (name desugared) (public_name catala.desugared) (libraries utils dcalc scopelang ocamlgraph)) + +(documentation + (package catala)) diff --git a/src/catala/desugared/format.ml b/src/catala/desugared/format.ml deleted file mode 100644 index b2af8230..00000000 --- a/src/catala/desugared/format.ml +++ /dev/null @@ -1,32 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux - - - 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. *) - -(** Print a scope program *) -let print_scope (scope : Ast.scope) : string = - let print_defs (defs : Ast.rule list Ast.ScopeDefMap.t) : string = - defs |> Ast.ScopeDefMap.bindings - |> List.map (fun (uid, _term) -> - Printf.sprintf "%s:\n%s" (Ast.ScopeDef.format_t uid) (assert false)) - |> String.concat "" - in - "___Variables Definition___\n" ^ print_defs scope.scope_defs ^ "___Subscope (Re)definition___\n" - ^ "\n" - -(** Print the whole program *) -let print_program (prgm : Ast.program) : string = - prgm |> Scopelang.Ast.ScopeMap.bindings - |> List.map (fun (uid, scope) -> - Printf.sprintf "Scope %s:\n%s" (Scopelang.Ast.ScopeName.format_t uid) (print_scope scope)) - |> String.concat "\n" - |> Printf.sprintf "Scope program\n%s" diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index d29399bc..b91072dc 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -38,6 +38,22 @@ type expr = | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked +let rec locations_used (e : expr Pos.marked) : location list = + match Pos.unmark e with + | ELocation l -> [ l ] + | EVar _ | ELit _ | EOp _ -> [] + | EAbs (_, binder, _) -> + let _, body = Bindlib.unmbind binder in + locations_used body + | EApp (e1, args) -> + List.fold_left (fun acc arg -> locations_used arg @ acc) (locations_used e1) args + | EIfThenElse (e1, e2, e3) -> locations_used e1 @ locations_used e2 @ locations_used e3 + | EDefault (just, cons, subs) -> + List.fold_left + (fun acc sub -> locations_used sub @ acc) + (locations_used just @ locations_used cons) + subs + module Var = struct type t = expr Pos.marked Bindlib.var diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune index d0e89810..98d42be7 100644 --- a/src/catala/scope_language/dune +++ b/src/catala/scope_language/dune @@ -2,3 +2,6 @@ (name scopelang) (public_name catala.scopelang) (libraries utils dcalc)) + +(documentation + (package catala)) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 1a5236f8..da94685e 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -125,7 +125,6 @@ let translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) : let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked = let ctx = empty_ctx in - (* TODO: compute dependency order! *) let rules, ctx = translate_rules p ctx sigma.scope_decl_rules in let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in diff --git a/src/catala/utils/uid.ml b/src/catala/utils/uid.ml index e0cce563..49694f06 100644 --- a/src/catala/utils/uid.ml +++ b/src/catala/utils/uid.ml @@ -29,7 +29,7 @@ module type Id = sig val compare : t -> t -> int - val format_t : t -> string + val format_t : Format.formatter -> t -> unit val hash : t -> int end @@ -53,7 +53,8 @@ end) : Id with type info = X.info = struct let compare (x : t) (y : t) : int = compare x.id y.id - let format_t (x : t) : string = Printf.sprintf "%s" (X.format_info x.info) + let format_t (fmt : Format.formatter) (x : t) : unit = + Format.fprintf fmt "%s" (X.format_info x.info) let hash (x : t) : int = x.id end diff --git a/src/catala/utils/uid.mli b/src/catala/utils/uid.mli index c32c1afc..564de761 100644 --- a/src/catala/utils/uid.mli +++ b/src/catala/utils/uid.mli @@ -31,7 +31,7 @@ module type Id = sig val compare : t -> t -> int - val format_t : t -> string + val format_t : Format.formatter -> t -> unit val hash : t -> int end From 91f39a1b405d5cb5895f8de031587690f7117c99 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 14:35:26 +0100 Subject: [PATCH 021/142] Progress: * used generative functors for Uids * priority tree now in Desugared.Ast --- src/catala/catala_surface/desugaring.ml | 33 ++++++--- src/catala/catala_surface/name_resolution.ml | 3 +- src/catala/catala_surface/parser.mly | 2 +- src/catala/desugared/ast.ml | 24 ++++--- src/catala/desugared/dependency.ml | 7 +- src/catala/desugared/desugared_to_scope.ml | 73 +++++++++++++++++++- src/catala/driver.ml | 12 +++- src/catala/scope_language/ast.ml | 12 +++- src/catala/utils/uid.ml | 3 +- src/catala/utils/uid.mli | 2 +- 10 files changed, 139 insertions(+), 32 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index b1613684..ace70d39 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -92,7 +92,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) in let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in ( Scopelang.Ast.ELocation - (SubScopeVar (assert false, (subscope_uid, pos), (subscope_var_uid, pos))), + (SubScopeVar (subscope_real_uid, (subscope_uid, pos), (subscope_var_uid, pos))), pos ) | _ -> Name_resolution.raise_unsupported_feature @@ -123,8 +123,13 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop in let just = merge_conditions precond just (Pos.get_position cons) in let cons = translate_expr scope (Some def_key) ctxt cons in - (* if there's a parameter, we have to wrap the justifiction and the body in a func *) - { just; cons; parameter = param_uid; priority = 0 } + { + just; + cons; + parameter = param_uid; + parent_rule = + None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); + } (* Process a definition *) let process_def (precond : Scopelang.Ast.expr Pos.marked option) @@ -157,17 +162,27 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos in let scope_updated = - let x_def = + let x_def, x_type = match Desugared.Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def - | None -> [ Desugared.Ast.empty_def default_pos (Option.is_some (param_uid def_key)) ] + | None -> (Desugared.Ast.RuleMap.empty, Pos.unmark (Name_resolution.get_def_typ ctxt def_key)) + in + let rule_name = + Desugared.Ast.RuleName.fresh + (Pos.map_under_mark + (fun qident -> String.concat "." (List.map (fun i -> Pos.unmark i) qident)) + def.definition_name) in let x_def = - process_default ctxt scope_uid def_key (param_uid def_key) precond def.definition_condition - def.definition_expr - :: x_def + Desugared.Ast.RuleMap.add rule_name + (process_default ctxt scope_uid def_key (param_uid def_key) precond def.definition_condition + def.definition_expr) + x_def in - { scope with scope_defs = Desugared.Ast.ScopeDefMap.add def_key x_def scope.scope_defs } + { + scope with + scope_defs = Desugared.Ast.ScopeDefMap.add def_key (x_def, x_type) scope.scope_defs; + } in Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index f69a19c8..71dc0f86 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -91,7 +91,8 @@ let process_base_typ ((typ, typ_pos) : Ast.base_typ Pos.marked) : Dcalc.Ast.typ | Ast.Data (Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos | Ast.Data (Ast.Primitive prim) -> ( match prim with - | Ast.Integer | Ast.Decimal | Ast.Money | Ast.Date -> assert false + | Ast.Integer -> (Dcalc.Ast.TInt, typ_pos) + | Ast.Decimal | Ast.Money | Ast.Date -> raise_unsupported_feature "value type" typ_pos | Ast.Boolean -> (Dcalc.Ast.TBool, typ_pos) | Ast.Text -> raise_unsupported_feature "text type" typ_pos | Ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index faea60ae..f1d4a156 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -129,7 +129,7 @@ struct_or_enum_inject: match data with | EnumContent data -> (EnumInject (c, data), $sloc) - | _ -> assert false + | _ -> assert false (* should not happen *) } primitive_expression: diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 16c58850..01ff2c62 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -16,6 +16,10 @@ module Pos = Utils.Pos module Uid = Utils.Uid module IdentMap = Map.Make (String) +module RuleName = Uid.Make (Uid.MarkedString) () + +module RuleMap = Map.Make (RuleName) + (** Inside a scope, a definition can refer either to a scope def, or a subscope def *) module ScopeDef = struct type t = @@ -28,7 +32,7 @@ module ScopeDef = struct match (x, y) with | Var x, Var y | Var x, SubScopeVar (_, y) | SubScopeVar (_, x), Var y -> Scopelang.Ast.ScopeVar.compare x y - | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.SubScopeName.compare x y + | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.ScopeVar.compare x y let format_t fmt x = match x with @@ -52,15 +56,15 @@ type rule = { just : Scopelang.Ast.expr Pos.marked; cons : Scopelang.Ast.expr Pos.marked; parameter : Scopelang.Ast.Var.t option; - priority : int; + parent_rule : RuleName.t option; } -let empty_def (pos : Pos.t) (have_parameter : bool) : rule = +let empty_rule (pos : Pos.t) (have_parameter : bool) (parent_rule : RuleName.t option) : rule = { just = (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); cons = (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); parameter = (if have_parameter then Some (Scopelang.Ast.Var.make ("dummy", pos)) else None); - priority = 0; + parent_rule; } type assertion = Scopelang.Ast.expr Pos.marked @@ -77,7 +81,7 @@ type scope = { scope_vars : Scopelang.Ast.ScopeVarSet.t; scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; scope_uid : Scopelang.Ast.ScopeName.t; - scope_defs : rule list ScopeDefMap.t; + scope_defs : (rule RuleMap.t * Dcalc.Ast.typ) ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } @@ -95,19 +99,19 @@ let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang. type program = scope Scopelang.Ast.ScopeMap.t -let free_variables (def : rule list) : ScopeDefSet.t = +let free_variables (def : rule RuleMap.t) : ScopeDefSet.t = let add_locs (acc : ScopeDefSet.t) (locs : Scopelang.Ast.location list) : ScopeDefSet.t = List.fold_left (fun acc loc -> ScopeDefSet.add ( match loc with | Scopelang.Ast.ScopeVar v -> ScopeDef.Var (Pos.unmark v) - | _ -> assert false ) + | _ -> assert false (*TODO *) ) acc) acc locs in - List.fold_left - (fun acc rule -> + RuleMap.fold + (fun _ rule acc -> let locs = Scopelang.Ast.locations_used rule.just @ Scopelang.Ast.locations_used rule.cons in add_locs acc locs) - ScopeDefSet.empty def + def ScopeDefSet.empty diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index f073a1c4..ccfbb069 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -61,6 +61,9 @@ module TopologicalTraversal = Graph.Topological.Make (ScopeDependencies) module SCC = Graph.Components.Make (ScopeDependencies) (** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) +let correct_computation_ordering (g : ScopeDependencies.t) : Vertex.t list = + List.rev (TopologicalTraversal.fold (fun sd acc -> sd :: acc) g []) + (** Outputs an error in case of cycles. *) let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) @@ -106,13 +109,13 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = in let g = Scopelang.Ast.SubScopeMap.fold - (fun _ (v : Scopelang.Ast.SubScopeName.t) g -> + (fun (v : Scopelang.Ast.SubScopeName.t) _ g -> ScopeDependencies.add_vertex g (Vertex.SubScope v)) scope.scope_sub_scopes g in let g = Ast.ScopeDefMap.fold - (fun def_key def g -> + (fun def_key (def, _) g -> let fv = Ast.free_variables def in Ast.ScopeDefSet.fold (fun fv_def g -> diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index ab7432a1..122e3843 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -12,4 +12,75 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) -let translate_program (_pgrm : Ast.program) : Scopelang.Ast.program = assert false +module Pos = Utils.Pos + +let translate_def (_def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked = + (* Here, we have to transform this list of rules into a default tree. *) + (* TODO *) + assert false + +let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = + let scope_dependencies = Dependency.build_scope_dependencies scope in + Dependency.check_for_cycle scope scope_dependencies; + let scope_ordering = Dependency.correct_computation_ordering scope_dependencies in + let scope_decl_rules = + List.flatten + (List.map + (fun vertex -> + match vertex with + | Dependency.Vertex.Var (var : Scopelang.Ast.ScopeVar.t) -> + let var_def, var_typ = + Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs + in + let expr_def = translate_def var_def in + [ + Scopelang.Ast.Definition + ( Scopelang.Ast.ScopeVar + (var, Pos.get_position (Scopelang.Ast.ScopeVar.get_info var)), + var_typ, + expr_def ); + ] + | 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 = + Scopelang.Ast.SubScopeMap.find sub_scope_index scope.scope_sub_scopes + in + let sub_scope_vars_redefs = + Ast.ScopeDefMap.mapi + (fun def_key (def, def_typ) -> + match def_key with + | Ast.ScopeDef.Var _ -> assert false (* should not happen *) + | Ast.ScopeDef.SubScopeVar (_, sub_scope_var) -> + let expr_def = translate_def def in + let subscop_real_name = + Scopelang.Ast.SubScopeMap.find sub_scope_index scope.scope_sub_scopes + in + let var_pos = + Pos.get_position (Scopelang.Ast.ScopeVar.get_info sub_scope_var) + in + Scopelang.Ast.Definition + ( Scopelang.Ast.SubScopeVar + ( subscop_real_name, + (sub_scope_index, var_pos), + (sub_scope_var, var_pos) ), + def_typ, + expr_def )) + (Ast.ScopeDefMap.filter + (fun def_key _def -> + match def_key with + | Ast.ScopeDef.Var _ -> false + | Ast.ScopeDef.SubScopeVar (sub_scope_index', _) -> + sub_scope_index = sub_scope_index') + scope.scope_defs) + in + let sub_scope_vars_redefs = + List.map snd (Ast.ScopeDefMap.bindings sub_scope_vars_redefs) + in + sub_scope_vars_redefs @ [ Scopelang.Ast.Call (sub_scope, sub_scope_index) ]) + scope_ordering) + in + { Scopelang.Ast.scope_decl_name = scope.scope_uid; Scopelang.Ast.scope_decl_rules } + +let translate_program (pgrm : Ast.program) : Scopelang.Ast.program = + Scopelang.Ast.ScopeMap.map translate_scope pgrm diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 567397fc..e08cc5e5 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -66,13 +66,18 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ let language : Cli.backend_lang = Cli.to_backend_lang language in Cli.debug_print (Printf.sprintf "Weaving literate program into %s" - (match backend with Cli.Latex -> "LaTeX" | Cli.Html -> "HTML" | _ -> assert false)); + ( match backend with + | Cli.Latex -> "LaTeX" + | Cli.Html -> "HTML" + | _ -> assert false (* should not happen *) )); let output_file = match output_file with | Some f -> f | None -> ( Filename.remove_extension source_file - ^ match backend with Cli.Latex -> ".tex" | Cli.Html -> ".html" | _ -> assert false ) + ^ + match backend with Cli.Latex -> ".tex" | Cli.Html -> ".html" | _ -> assert false + (* should not happen *) ) in let oc = open_out output_file in let weave_output = @@ -80,6 +85,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ | Cli.Latex -> Literate.Latex.ast_to_latex language | Cli.Html -> Literate.Html.ast_to_html pygmentize_loc language | _ -> assert false + (* should not happen *) in Cli.debug_print (Printf.sprintf "Writing to %s" output_file); let fmt = Format.formatter_of_out_channel oc in @@ -91,7 +97,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ | Cli.Html -> Literate.Html.wrap_html program.Surface.Ast.program_source_files pygmentize_loc language fmt (fun fmt -> weave_output fmt program) - | _ -> assert false + | _ -> assert false (* should not happen *) else weave_output fmt program; close_out oc; 0 diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index b91072dc..e32f241b 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -14,13 +14,19 @@ module Pos = Utils.Pos module Uid = Utils.Uid -module ScopeName = Uid.Make (Uid.MarkedString) + +module ScopeName = Uid.Make (Uid.MarkedString) () + module ScopeNameSet = Set.Make (ScopeName) module ScopeMap = Map.Make (ScopeName) -module SubScopeName = Uid.Make (Uid.MarkedString) + +module SubScopeName = Uid.Make (Uid.MarkedString) () + module SubScopeNameSet = Set.Make (SubScopeName) module SubScopeMap = Map.Make (SubScopeName) -module ScopeVar = Uid.Make (Uid.MarkedString) + +module ScopeVar = Uid.Make (Uid.MarkedString) () + module ScopeVarSet = Set.Make (ScopeVar) module ScopeVarMap = Map.Make (ScopeVar) diff --git a/src/catala/utils/uid.ml b/src/catala/utils/uid.ml index 49694f06..5c6f1781 100644 --- a/src/catala/utils/uid.ml +++ b/src/catala/utils/uid.ml @@ -38,7 +38,8 @@ module Make (X : sig type info val format_info : info -> string -end) : Id with type info = X.info = struct +end) +() : Id with type info = X.info = struct type t = { id : int; info : X.info } type info = X.info diff --git a/src/catala/utils/uid.mli b/src/catala/utils/uid.mli index 564de761..791a7801 100644 --- a/src/catala/utils/uid.mli +++ b/src/catala/utils/uid.mli @@ -36,4 +36,4 @@ module type Id = sig val hash : t -> int end -module Make (X : Info) : Id with type info = X.info +module Make (X : Info) () : Id with type info = X.info From 90de3c7c7111e40521c006ac133be160b403bcff Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 16:51:19 +0100 Subject: [PATCH 022/142] Completed translation from desugared to scope --- src/catala/catala_surface/desugaring.ml | 14 ++- src/catala/default_calculus/print.ml | 26 +++++ src/catala/desugared/ast.ml | 14 ++- src/catala/desugared/desugared_to_scope.ml | 114 ++++++++++++++++++++- 4 files changed, 159 insertions(+), 9 deletions(-) create mode 100644 src/catala/default_calculus/print.ml diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index ace70d39..239c73f4 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -126,7 +126,19 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop { just; cons; - parameter = param_uid; + parameter = + (let def_key_typ = Name_resolution.get_def_typ ctxt def_key in + match (Pos.unmark def_key_typ, param_uid) with + | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (param_uid, Pos.unmark t_in) + | Dcalc.Ast.TArrow _, None -> + Errors.raise_spanned_error + "this definition has a function type but the parameter is missing" + (Pos.get_position cons) + | _, Some _ -> + Errors.raise_spanned_error + "this definition has a parameter but its type is not a function" + (Pos.get_position cons) + | _ -> None); parent_rule = None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); } diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml new file mode 100644 index 00000000..03df1ad2 --- /dev/null +++ b/src/catala/default_calculus/print.ml @@ -0,0 +1,26 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module Pos = Utils.Pos + +let rec format_typ (fmt : Format.formatter) (typ : Ast.typ Pos.marked) : unit = + match Pos.unmark typ with + | TUnit -> Format.fprintf fmt "unit" + | TBool -> Format.fprintf fmt "bool" + | TInt -> Format.fprintf fmt "int" + | TTuple ts -> + Format.fprintf fmt "(%a)" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) + ts + | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 01ff2c62..c0e4cd68 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -55,16 +55,19 @@ module ScopeDefSet = Set.Make (ScopeDef) type rule = { just : Scopelang.Ast.expr Pos.marked; cons : Scopelang.Ast.expr Pos.marked; - parameter : Scopelang.Ast.Var.t option; + parameter : (Scopelang.Ast.Var.t * Dcalc.Ast.typ) option; parent_rule : RuleName.t option; } -let empty_rule (pos : Pos.t) (have_parameter : bool) (parent_rule : RuleName.t option) : rule = +let empty_rule (pos : Pos.t) (have_parameter : Dcalc.Ast.typ option) : rule = { just = (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); cons = (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); - parameter = (if have_parameter then Some (Scopelang.Ast.Var.make ("dummy", pos)) else None); - parent_rule; + parameter = + ( match have_parameter with + | Some typ -> Some (Scopelang.Ast.Var.make ("dummy", pos), typ) + | None -> None ); + parent_rule = None; } type assertion = Scopelang.Ast.expr Pos.marked @@ -106,7 +109,8 @@ let free_variables (def : rule RuleMap.t) : ScopeDefSet.t = ScopeDefSet.add ( match loc with | Scopelang.Ast.ScopeVar v -> ScopeDef.Var (Pos.unmark v) - | _ -> assert false (*TODO *) ) + | Scopelang.Ast.SubScopeVar (_, sub_index, sub_var) -> + ScopeDef.SubScopeVar (Pos.unmark sub_index, Pos.unmark sub_var) ) acc) acc locs in diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 122e3843..6b65b9cd 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -13,11 +13,119 @@ the License. *) module Pos = Utils.Pos +module Errors = Utils.Errors -let translate_def (_def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked = +type rule_tree = Leaf of Ast.rule | Node of Ast.rule * rule_tree list + +(* invariant: one rule in def does not have any parent rule *) +(* invariant: there are no dandling pointer parents in the rules *) +let rec def_map_to_tree (def : Ast.rule Ast.RuleMap.t) : rule_tree = + (* first we look to the only rule that does not have any parent *) + let has_no_parent _ (r : Ast.rule) = Option.is_none r.Ast.parent_rule in + let no_parent = Ast.RuleMap.filter has_no_parent def in + let no_parent_name, no_parent = + if Ast.RuleMap.cardinal no_parent = 1 then Ast.RuleMap.choose no_parent else assert false + in + let def = Ast.RuleMap.remove no_parent_name def in + (* we look for all the direct children of no_parent *) + let children, rest = + Ast.RuleMap.partition (fun _ r -> r.Ast.parent_rule = Some no_parent_name) def + in + if Ast.RuleMap.cardinal children = 0 then Leaf no_parent + (* it doesn't matter that [rest] contains more rules since each rule in [rest] is supposed to + have a parent rule containted in the original tree, so it will get treated at some point *) + else + let children_no_parent = + Ast.RuleMap.map (fun r -> { r with Ast.parent_rule = None }) children + in + let tree_children = + List.map + (fun (child_no_parent_name, child_no_parent) -> + def_map_to_tree (Ast.RuleMap.add child_no_parent_name child_no_parent rest)) + (Ast.RuleMap.bindings children_no_parent) + in + Node (no_parent, tree_children) + +let rec rule_tree_to_expr (is_func : Scopelang.Ast.Var.t option) (tree : rule_tree) : + Scopelang.Ast.expr Pos.marked = + let rule, children = match tree with Leaf r -> (r, []) | Node (r, child) -> (r, child) in + (* because each rule has its own variable parameter and we want to convert the whole rule tree + into a function, we need to perform some alpha-renaming of all the expressions *) + let substitute_parameter (e : Scopelang.Ast.expr Pos.marked) : Scopelang.Ast.expr Pos.marked = + match (is_func, rule.parameter) with + | Some new_param, Some (old_param, _) -> + let binder = Bindlib.bind_var old_param (Bindlib.box e) in + Bindlib.subst (Bindlib.unbox binder) (Scopelang.Ast.EVar new_param, Pos.no_pos) + | None, None -> e + | _ -> assert false + (* should not happen *) + in + let just = substitute_parameter rule.Ast.just in + let cons = substitute_parameter rule.Ast.cons in + let children = List.map (rule_tree_to_expr is_func) children in + let default = (Scopelang.Ast.EDefault (just, cons, children), Pos.no_pos) in + match (is_func, rule.parameter) with + | None, None -> default + | Some new_param, Some (_, typ) -> + Bindlib.unbox + (Scopelang.Ast.make_abs + (Array.of_list [ new_param ]) + (Bindlib.box default) Pos.no_pos [ typ ] Pos.no_pos) + | _ -> assert false + +(* should not happen *) + +let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked = (* Here, we have to transform this list of rules into a default tree. *) - (* TODO *) - assert false + (* Because we can have multiple rules at the top-level and our syntax does not allow that, we + insert a dummy rule at the top *) + let is_func _ (r : Ast.rule) : bool = Option.is_some r.Ast.parameter in + let all_rules_func = Ast.RuleMap.for_all is_func def in + let all_rules_not_func = Ast.RuleMap.for_all (fun n r -> not (is_func n r)) def in + let is_def_func : Dcalc.Ast.typ option = + if all_rules_func then + let typ = (snd (Ast.RuleMap.choose def)).Ast.parameter in + match typ with + | Some (_, typ) -> + let is_typ _ r = snd (Option.get r.Ast.parameter) = typ in + if Ast.RuleMap.for_all is_typ def then Some typ + else + Errors.raise_multispanned_error + "the type of these parameters should be the same, but they \n are different" + (List.map + (fun (_, r) -> + ( Some + (Format.asprintf "The type of the parameter of this expression is %a" + Dcalc.Print.format_typ (typ, Pos.no_pos)), + Pos.get_position r.Ast.cons )) + (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_typ n r)) def))) + | None -> assert false (* should not happen *) + else if all_rules_not_func then None + else + Errors.raise_multispanned_error + "some definitions of the same variable are functions while others aren't" + ( List.map + (fun (_, r) -> (Some "This definition is a function:", Pos.get_position r.Ast.cons)) + (Ast.RuleMap.bindings (Ast.RuleMap.filter is_func def)) + @ List.map + (fun (_, r) -> (Some "This definition is not a function:", Pos.get_position r.Ast.cons)) + (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_func n r)) def)) ) + in + let dummy_rule = Ast.empty_rule Pos.no_pos is_def_func in + let dummy_rule_name = Ast.RuleName.fresh ("dummy", Pos.no_pos) in + let def = + Ast.RuleMap.add dummy_rule_name dummy_rule + (Ast.RuleMap.map + (fun r -> + match r.Ast.parent_rule with + | Some _ -> r + | None -> { r with parent_rule = Some dummy_rule_name }) + def) + in + let def_tree = def_map_to_tree def in + rule_tree_to_expr + (Option.map (fun _ -> Scopelang.Ast.Var.make ("param", Pos.no_pos)) is_def_func) + def_tree let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = let scope_dependencies = Dependency.build_scope_dependencies scope in From b5e1e48fc88352b54353eddfd9c9681a2ff60f2e Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 25 Nov 2020 18:00:34 +0100 Subject: [PATCH 023/142] Chain completed, onto debugging --- src/catala/default_calculus/ast.ml | 7 ++ src/catala/scope_language/ast.ml | 2 +- src/catala/scope_language/dependency.ml | 89 +++++++++++++++++++++ src/catala/scope_language/dune | 2 +- src/catala/scope_language/scope_to_dcalc.ml | 28 +++++-- 5 files changed, 121 insertions(+), 7 deletions(-) create mode 100644 src/catala/scope_language/dependency.ml diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index f56f0b0b..0d265bc2 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -63,4 +63,11 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box : expr Pos.marked Bindlib.box = Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) +let make_let_in (x : Var.t Pos.marked) (tau : typ) (e1 : expr Pos.marked) + (e2 : expr Pos.marked Bindlib.box) (pos : Pos.t) : expr Pos.marked = + ( EApp + ( Bindlib.unbox (make_abs (Array.of_list [ Pos.unmark x ]) e2 (Pos.get_position x) [ tau ] pos), + [ e1 ] ), + pos ) + type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index e32f241b..3bbe2097 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -63,7 +63,7 @@ let rec locations_used (e : expr Pos.marked) : location list = module Var = struct type t = expr Pos.marked Bindlib.var - let make (s : string Pos.marked) = + let make (s : string Pos.marked) : t = Bindlib.new_var (fun x -> (EVar x, Pos.get_position s)) (Pos.unmark s) let compare x y = Bindlib.compare_vars x y diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml new file mode 100644 index 00000000..9507b390 --- /dev/null +++ b/src/catala/scope_language/dependency.ml @@ -0,0 +1,89 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +(** 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. *) + +module Pos = Utils.Pos +module Errors = Utils.Errors + +module Vertex = struct + type t = Ast.ScopeName.t + + let hash x = Ast.ScopeName.hash x + + let compare = compare + + let equal x y = Ast.ScopeName.compare x y = 0 + + let format_t (fmt : Format.formatter) (x : t) : unit = Ast.ScopeName.format_t fmt x +end + +(** On the edges, the label is the expression responsible for the use of the function *) +module Edge = struct + type t = Pos.t + + let compare = compare + + let default = Pos.no_pos +end + +module Dependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge) +module TopologicalTraversal = Graph.Topological.Make (Dependencies) + +module SCC = Graph.Components.Make (Dependencies) +(** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) + +let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = + let g = Dependencies.empty in + let g = Ast.ScopeMap.fold (fun v _ g -> Dependencies.add_vertex g v) prgm g in + Ast.ScopeMap.fold + (fun scope_name scope g -> + let subscopes = + List.fold_left + (fun acc r -> + match r with + | Ast.Definition _ -> acc + | Ast.Call (subscope, _) -> Ast.ScopeNameSet.add subscope acc) + Ast.ScopeNameSet.empty scope.Ast.scope_decl_rules + in + Ast.ScopeNameSet.fold + (fun subscope g -> Dependencies.add_edge g subscope scope_name) + subscopes g) + prgm g + +let check_for_cycle (g : Dependencies.t) : unit = + (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) + let sccs = SCC.scc_list g in + if List.length sccs < Dependencies.nb_vertex g then + let scc = List.find (fun scc -> List.length scc > 1) sccs in + Errors.raise_multispanned_error "cyclic dependency detected between scopes!" + (List.flatten + (List.map + (fun v -> + let var_str, var_info = + (Format.asprintf "%a" Ast.ScopeName.format_t v, Ast.ScopeName.get_info v) + in + let succs = Dependencies.succ_e g v in + let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in + let succ_str = Format.asprintf "%a" Ast.ScopeName.format_t succ in + [ + (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); + ( Some ("used here in the definition of another cycle variable " ^ succ_str ^ ":"), + edge_pos ); + ]) + scc)) + +let get_scope_ordering (g : Dependencies.t) : Ast.ScopeName.t list = + List.rev (TopologicalTraversal.fold (fun sd acc -> sd :: acc) g []) diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune index 98d42be7..4e462492 100644 --- a/src/catala/scope_language/dune +++ b/src/catala/scope_language/dune @@ -1,7 +1,7 @@ (library (name scopelang) (public_name catala.scopelang) - (libraries utils dcalc)) + (libraries utils dcalc ocamlgraph)) (documentation (package catala)) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index da94685e..7f970ee2 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -145,12 +145,30 @@ let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.ex let func_acc = Bindlib.unbox (Bindlib.bind_var hole_var func_acc) in Bindlib.subst func_acc (return_exp, pos_sigma) -let translate_program (prgm : Ast.program) (_top_level_scope : Ast.ScopeName.t) : +let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = - let _scope_ctx = + let scope_ctx = Ast.ScopeMap.map - (fun scope -> Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) + (fun scope -> Dcalc.Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) prgm in - (* TODO: compute dependency order! *) - assert false + let scope_dependencies = Dependency.build_program_dep_graph prgm in + Dependency.check_for_cycle scope_dependencies; + let scope_ordering = Dependency.get_scope_ordering scope_dependencies in + let top_level_scope = Ast.ScopeMap.find top_level_scope_name prgm in + let acc = translate_scope_decl scope_ctx top_level_scope in + + (* the resulting expression is the list of definitions of all the scopes, ending with the + top-level scope. *) + List.fold_right + (fun scope_name (acc : Dcalc.Ast.expr Pos.marked) -> + if scope_name = top_level_scope_name then acc + else + let scope = Ast.ScopeMap.find scope_name prgm in + let scope_expr = translate_scope_decl scope_ctx scope in + (* here we perform type-checking, incidentally *) + let scope_typ = Dcalc.Typing.infer_type scope_expr in + Dcalc.Ast.make_let_in + (Ast.ScopeMap.find scope_name scope_ctx, Pos.get_position scope_typ) + (Pos.unmark scope_typ) scope_expr (Bindlib.box acc) Pos.no_pos) + scope_ordering acc From e0f7baaa2b099de65361b9df5469abec6e521247 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 10:38:13 +0100 Subject: [PATCH 024/142] Pretty printer --- src/catala/catala_surface/desugaring.ml | 4 +- src/catala/default_calculus/ast.ml | 8 +-- src/catala/default_calculus/print.ml | 64 ++++++++++++++++++++- src/catala/default_calculus/typing.ml | 10 +++- src/catala/desugared/ast.ml | 6 +- src/catala/desugared/desugared_to_scope.ml | 18 +++--- src/catala/scope_language/ast.ml | 7 ++- src/catala/scope_language/scope_to_dcalc.ml | 23 +++++--- 8 files changed, 108 insertions(+), 32 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 239c73f4..49a3bcc8 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -129,7 +129,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop parameter = (let def_key_typ = Name_resolution.get_def_typ ctxt def_key in match (Pos.unmark def_key_typ, param_uid) with - | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (param_uid, Pos.unmark t_in) + | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (param_uid, t_in) | Dcalc.Ast.TArrow _, None -> Errors.raise_spanned_error "this definition has a function type but the parameter is missing" @@ -177,7 +177,7 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) let x_def, x_type = match Desugared.Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def - | None -> (Desugared.Ast.RuleMap.empty, Pos.unmark (Name_resolution.get_def_typ ctxt def_key)) + | None -> (Desugared.Ast.RuleMap.empty, Name_resolution.get_def_typ ctxt def_key) in let rule_name = Desugared.Ast.RuleName.fresh diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 0d265bc2..f39535cf 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -34,7 +34,7 @@ type expr = | ETuple of expr Pos.marked list | ETupleAccess of expr Pos.marked * int | ELit of lit - | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * typ list + | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list @@ -55,15 +55,15 @@ type vars = expr Pos.marked Bindlib.mvar let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x -let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (taus : typ list) - (pos : Pos.t) : expr Pos.marked Bindlib.box = +let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) + (taus : typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, taus), pos)) (Bindlib.bind_mvar xs e) let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box list) (pos : Pos.t) : expr Pos.marked Bindlib.box = Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) -let make_let_in (x : Var.t Pos.marked) (tau : typ) (e1 : expr Pos.marked) +let make_let_in (x : Var.t Pos.marked) (tau : typ Pos.marked) (e1 : expr Pos.marked) (e2 : expr Pos.marked Bindlib.box) (pos : Pos.t) : expr Pos.marked = ( EApp ( Bindlib.unbox (make_abs (Array.of_list [ Pos.unmark x ]) e2 (Pos.get_position x) [ tau ] pos), diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 03df1ad2..9bef1d69 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -13,8 +13,9 @@ the License. *) module Pos = Utils.Pos +open Ast -let rec format_typ (fmt : Format.formatter) (typ : Ast.typ Pos.marked) : unit = +let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = match Pos.unmark typ with | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" @@ -24,3 +25,64 @@ let rec format_typ (fmt : Format.formatter) (typ : Ast.typ Pos.marked) : unit = (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) ts | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 + +let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = + match Pos.unmark l with + | LBool b -> Format.fprintf fmt "%b" b + | LInt i -> Format.fprintf fmt "%s" (Int64.to_string i) + | LEmptyError -> Format.fprintf fmt "∅" + +let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = + Format.fprintf fmt "%s" + ( match Pos.unmark op with + | Add -> "+" + | Sub -> "-" + | Mult -> "*" + | Div -> "/" + | And -> "&&" + | Or -> "||" + | Eq -> "==" + | Neq -> "!=" + | Lt -> "<" + | Lte -> "<=" + | Gt -> ">" + | Gte -> ">=" ) + +let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = + Format.fprintf fmt "%s" (match Pos.unmark op with Minus -> "-" | Not -> "~") + +let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = + match Pos.unmark e with + | EVar v -> Format.fprintf fmt "%s" (Bindlib.name_of v) + | ETuple es -> + Format.fprintf fmt "(%a)" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") format_expr) + es + | ETupleAccess (e1, n) -> Format.fprintf fmt "%a.%d" format_expr e1 n + | ELit l -> Format.fprintf fmt "%a" format_lit (Pos.same_pos_as l e) + | EAbs (_, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + Format.fprintf fmt "λ %a -> @\n@[ %a@]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + (fun fmt (x, tau) -> Format.fprintf fmt "(%s: %a)" (Bindlib.name_of x) format_typ tau)) + xs_tau format_expr body + | EApp ((EOp (Binop op), _), [ arg1; arg2 ]) -> + Format.fprintf fmt "@[%a %a %a@]" format_expr arg1 format_binop (op, Pos.no_pos) format_expr + arg2 + | EApp ((EOp (Unop op), _), [ arg1 ]) -> + Format.fprintf fmt "@[%a %a@]" format_unop (op, Pos.no_pos) format_expr arg1 + | EApp (f, args) -> + Format.fprintf fmt "@[%a %a@]" format_expr f + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") format_expr) + args + | EIfThenElse (e1, e2, e3) -> + Format.fprintf fmt "if @[%a@] then @[%a@] else @[%a@]" format_expr e1 + format_expr e2 format_expr e3 + | EOp (Binop op) -> Format.fprintf fmt "%a" format_binop (op, Pos.no_pos) + | EOp (Unop op) -> Format.fprintf fmt "%a" format_unop (op, Pos.no_pos) + | EDefault (just, cons, subs) -> + Format.fprintf fmt "⟨ %a ⊢ %a | %a 〉" format_expr just format_expr cons + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_expr) + subs diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 6163e1f2..00ac9663 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -54,6 +54,8 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t_union = UnionFind.union t1 t2 in ignore (UnionFind.set t_union t_repr) | (_, t1_pos), (_, t2_pos) -> + (* TODO: if we get weird error messages, then it means that we should use the persistent + version of the union-find data structure. *) Errors.raise_multispanned_error (Format.asprintf "Error during typechecking, type mismatch: cannot unify %a and %a" format_typ t1 format_typ t2) @@ -138,7 +140,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in let env = List.fold_left - (fun env (x, tau) -> A.VarMap.add x (ast_to_typ tau, pos_binder) env) + (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) env xstaus in typecheck_expr_bottom_up env body @@ -211,7 +213,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) let xstaus = List.map2 (fun x t_arg -> (x, t_arg)) (Array.to_list xs) t_args in let env = List.fold_left - (fun env (x, t_arg) -> A.VarMap.add x (ast_to_typ t_arg, pos_binder) env) + (fun env (x, t_arg) -> A.VarMap.add x (ast_to_typ (Pos.unmark t_arg), pos_binder) env) env xstaus in let t_out = typecheck_expr_bottom_up env body in @@ -219,7 +221,9 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) List.fold_right (fun t_arg acc -> UnionFind.make - (Pos.same_pos_as (TArrow (UnionFind.make (ast_to_typ t_arg, pos_binder), acc)) e)) + (Pos.same_pos_as + (TArrow (UnionFind.make (ast_to_typ (Pos.unmark t_arg), pos_binder), acc)) + e)) t_args t_out in unify t_func tau diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index c0e4cd68..ef59bca4 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -55,11 +55,11 @@ module ScopeDefSet = Set.Make (ScopeDef) type rule = { just : Scopelang.Ast.expr Pos.marked; cons : Scopelang.Ast.expr Pos.marked; - parameter : (Scopelang.Ast.Var.t * Dcalc.Ast.typ) option; + parameter : (Scopelang.Ast.Var.t * Dcalc.Ast.typ Pos.marked) option; parent_rule : RuleName.t option; } -let empty_rule (pos : Pos.t) (have_parameter : Dcalc.Ast.typ option) : rule = +let empty_rule (pos : Pos.t) (have_parameter : Dcalc.Ast.typ Pos.marked option) : rule = { just = (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); cons = (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); @@ -84,7 +84,7 @@ type scope = { scope_vars : Scopelang.Ast.ScopeVarSet.t; scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; scope_uid : Scopelang.Ast.ScopeName.t; - scope_defs : (rule RuleMap.t * Dcalc.Ast.typ) ScopeDefMap.t; + scope_defs : (rule RuleMap.t * Dcalc.Ast.typ Pos.marked) ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 6b65b9cd..b2515cc5 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -82,7 +82,7 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked let is_func _ (r : Ast.rule) : bool = Option.is_some r.Ast.parameter in let all_rules_func = Ast.RuleMap.for_all is_func def in let all_rules_not_func = Ast.RuleMap.for_all (fun n r -> not (is_func n r)) def in - let is_def_func : Dcalc.Ast.typ option = + let is_def_func : Dcalc.Ast.typ Pos.marked option = if all_rules_func then let typ = (snd (Ast.RuleMap.choose def)).Ast.parameter in match typ with @@ -96,7 +96,7 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked (fun (_, r) -> ( Some (Format.asprintf "The type of the parameter of this expression is %a" - Dcalc.Print.format_typ (typ, Pos.no_pos)), + Dcalc.Print.format_typ typ), Pos.get_position r.Ast.cons )) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_typ n r)) def))) | None -> assert false (* should not happen *) @@ -143,8 +143,9 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = let expr_def = translate_def var_def in [ Scopelang.Ast.Definition - ( Scopelang.Ast.ScopeVar - (var, Pos.get_position (Scopelang.Ast.ScopeVar.get_info var)), + ( ( Scopelang.Ast.ScopeVar + (var, Pos.get_position (Scopelang.Ast.ScopeVar.get_info var)), + Pos.get_position (Scopelang.Ast.ScopeVar.get_info var) ), var_typ, expr_def ); ] @@ -168,10 +169,11 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = Pos.get_position (Scopelang.Ast.ScopeVar.get_info sub_scope_var) in Scopelang.Ast.Definition - ( Scopelang.Ast.SubScopeVar - ( subscop_real_name, - (sub_scope_index, var_pos), - (sub_scope_var, var_pos) ), + ( ( Scopelang.Ast.SubScopeVar + ( subscop_real_name, + (sub_scope_index, var_pos), + (sub_scope_var, var_pos) ), + var_pos ), def_typ, expr_def )) (Ast.ScopeDefMap.filter diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 3bbe2097..30683db3 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -38,7 +38,8 @@ type expr = | ELocation of location | EVar of expr Pos.marked Bindlib.var | ELit of Dcalc.Ast.lit - | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ list + | EAbs of + Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of Dcalc.Ast.operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list @@ -74,7 +75,7 @@ type vars = expr Pos.marked Bindlib.mvar let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) - (taus : Dcalc.Ast.typ list) (pos : Pos.t) : expr Pos.marked Bindlib.box = + (taus : Dcalc.Ast.typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, taus), pos)) (Bindlib.bind_mvar xs e) let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box list) (pos : Pos.t) @@ -84,7 +85,7 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box module VarMap = Map.Make (Var) type rule = - | Definition of location * Dcalc.Ast.typ * expr Pos.marked + | Definition of location Pos.marked * Dcalc.Ast.typ Pos.marked * expr Pos.marked | Call of ScopeName.t * SubScopeName.t type scope_decl = { scope_decl_name : ScopeName.t; scope_decl_rules : rule list } diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 7f970ee2..db355e2b 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -79,7 +79,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rule with - | Definition (ScopeVar a, tau, e) -> + | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in let next_e = @@ -93,7 +93,9 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : Dcalc.Ast.make_abs (Array.of_list [ silent1 ]) (Bindlib.box (translate_expr ctx e)) - (Pos.get_position e) [ Dcalc.Ast.TUnit ] (Pos.get_position e) + (Pos.get_position e) + [ (Dcalc.Ast.TUnit, var_def_pos) ] + var_def_pos in let a_expr = Dcalc.Ast.make_var a_var in let merged_expr = Dcalc.Ast.make_app merge_operator_expr [ a_expr ] (Pos.get_position e) in @@ -101,14 +103,19 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : let merged_thunked = Dcalc.Ast.make_abs (Array.of_list [ silent2 ]) - merged_expr (Pos.get_position e) [ Dcalc.Ast.TUnit ] (Pos.get_position e) + merged_expr (Pos.get_position e) + [ (Dcalc.Ast.TUnit, var_def_pos) ] + var_def_pos in let final_e = Dcalc.Ast.make_app merged_thunked [ next_e ] (Pos.get_position e) in let new_ctx = - { ctx with scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, tau) ctx.scope_vars } + { + ctx with + scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; + } in (final_e, new_ctx) - | Definition (SubScopeVar _, _tau, _e) -> + | Definition ((SubScopeVar _, _), _tau, _e) -> Errors.raise_error "translation of subscope vars definitions unimplemented" | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" @@ -138,7 +145,8 @@ let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.ex (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) func_acc pos_sigma (List.map - (fun (_, (_, tau)) -> Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma))) + (fun (_, (_, tau)) -> + (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) scope_variables) pos_sigma in @@ -157,7 +165,6 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let scope_ordering = Dependency.get_scope_ordering scope_dependencies in let top_level_scope = Ast.ScopeMap.find top_level_scope_name prgm in let acc = translate_scope_decl scope_ctx top_level_scope in - (* the resulting expression is the list of definitions of all the scopes, ending with the top-level scope. *) List.fold_right @@ -170,5 +177,5 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let scope_typ = Dcalc.Typing.infer_type scope_expr in Dcalc.Ast.make_let_in (Ast.ScopeMap.find scope_name scope_ctx, Pos.get_position scope_typ) - (Pos.unmark scope_typ) scope_expr (Bindlib.box acc) Pos.no_pos) + scope_typ scope_expr (Bindlib.box acc) Pos.no_pos) scope_ordering acc From d3fe18aa184bc0d91f14df8d4a4f247a25376557 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 13:38:42 +0100 Subject: [PATCH 025/142] Pretty-printing, fixing bugs in scope_to_dcalc --- src/catala/default_calculus/ast.ml | 14 +- src/catala/default_calculus/print.ml | 53 ++++++-- src/catala/default_calculus/typing.ml | 2 + src/catala/driver.ml | 7 +- src/catala/scope_language/scope_to_dcalc.ml | 143 ++++++++++++-------- tests/test_bool/test_bool.catala | 2 +- 6 files changed, 144 insertions(+), 77 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index f39535cf..7b11dfd9 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -21,7 +21,7 @@ type typ = | TTuple of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LBool of bool | LEmptyError | LInt of Int64.t +type lit = LBool of bool | LEmptyError | LInt of Int64.t | LUnit type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq @@ -63,11 +63,11 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box : expr Pos.marked Bindlib.box = Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) -let make_let_in (x : Var.t Pos.marked) (tau : typ Pos.marked) (e1 : expr Pos.marked) - (e2 : expr Pos.marked Bindlib.box) (pos : Pos.t) : expr Pos.marked = - ( EApp - ( Bindlib.unbox (make_abs (Array.of_list [ Pos.unmark x ]) e2 (Pos.get_position x) [ tau ] pos), - [ e1 ] ), - pos ) +let make_let_in (x : Var.t Pos.marked) (tau : typ Pos.marked) (e1 : expr Pos.marked Bindlib.box) + (e2 : expr Pos.marked Bindlib.box) (pos : Pos.t) : expr Pos.marked Bindlib.box = + Bindlib.box_apply2 + (fun e u -> (EApp (e, u), pos)) + (make_abs (Array.of_list [ Pos.unmark x ]) e2 (Pos.get_position x) [ tau ] pos) + (Bindlib.box_list [ e1 ]) type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 9bef1d69..744743dc 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -24,13 +24,14 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with | LBool b -> Format.fprintf fmt "%b" b | LInt i -> Format.fprintf fmt "%s" (Int64.to_string i) | LEmptyError -> Format.fprintf fmt "∅" + | LUnit -> Format.fprintf fmt "()" let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = Format.fprintf fmt "%s" @@ -51,38 +52,62 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" (match Pos.unmark op with Minus -> "-" | Not -> "~") +let needs_parens (e : expr Pos.marked) : bool = + match Pos.unmark e with EAbs _ -> true | _ -> false + +let format_var (fmt : Format.formatter) (v : Var.t) : unit = + Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v) + let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = + let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = + if needs_parens e then Format.fprintf fmt "(%a)" format_expr e + else Format.fprintf fmt "%a" format_expr e + in match Pos.unmark e with - | EVar v -> Format.fprintf fmt "%s" (Bindlib.name_of v) + | EVar v -> Format.fprintf fmt "%a" format_var v | ETuple es -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") format_expr) es | ETupleAccess (e1, n) -> Format.fprintf fmt "%a.%d" format_expr e1 n | ELit l -> Format.fprintf fmt "%a" format_lit (Pos.same_pos_as l e) + | EApp ((EAbs (_, binder, taus), _), args) -> + let xs, body = Bindlib.unmbind binder in + let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let xs_tau_arg = List.map2 (fun (x, tau) arg -> (x, tau, arg)) xs_tau args in + Format.fprintf fmt "@[%a%a@]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + (fun fmt (x, tau, arg) -> + Format.fprintf fmt "@[@[let@ %a@ :@ %a@ =@ %a@]@ in@\n@]" format_var x + format_typ tau format_expr arg)) + xs_tau_arg format_expr body | EAbs (_, binder, taus) -> let xs, body = Bindlib.unmbind binder in let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - Format.fprintf fmt "λ %a -> @\n@[ %a@]" + Format.fprintf fmt "@[λ@ %a@ →@ %a@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") - (fun fmt (x, tau) -> Format.fprintf fmt "(%s: %a)" (Bindlib.name_of x) format_typ tau)) + (fun fmt (x, tau) -> Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau)) xs_tau format_expr body | EApp ((EOp (Binop op), _), [ arg1; arg2 ]) -> - Format.fprintf fmt "@[%a %a %a@]" format_expr arg1 format_binop (op, Pos.no_pos) format_expr - arg2 + Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 format_binop (op, Pos.no_pos) + format_with_parens arg2 | EApp ((EOp (Unop op), _), [ arg1 ]) -> - Format.fprintf fmt "@[%a %a@]" format_unop (op, Pos.no_pos) format_expr arg1 + Format.fprintf fmt "@[%a@ %a@]" format_unop (op, Pos.no_pos) format_with_parens arg1 | EApp (f, args) -> - Format.fprintf fmt "@[%a %a@]" format_expr f - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") format_expr) + Format.fprintf fmt "@[%a@ %a@]" format_expr f + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") format_with_parens) args | EIfThenElse (e1, e2, e3) -> - Format.fprintf fmt "if @[%a@] then @[%a@] else @[%a@]" format_expr e1 - format_expr e2 format_expr e3 + Format.fprintf fmt "if@ @[%a@]@ then@ @[%a@]@ else@ @[%a@]" format_expr + e1 format_expr e2 format_expr e3 | EOp (Binop op) -> Format.fprintf fmt "%a" format_binop (op, Pos.no_pos) | EOp (Unop op) -> Format.fprintf fmt "%a" format_unop (op, Pos.no_pos) | EDefault (just, cons, subs) -> - Format.fprintf fmt "⟨ %a ⊢ %a | %a 〉" format_expr just format_expr cons - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_expr) - subs + if List.length subs = 0 then + Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons + else + Format.fprintf fmt "@[⟨%a ⊢ %a | %a⟩@]" format_expr just format_expr cons + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) + subs diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 00ac9663..1d4c63d8 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -114,6 +114,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m (Pos.get_position e) ) | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) + | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> let ts = List.map (typecheck_expr_bottom_up env) es in @@ -182,6 +183,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (Pos.get_position e) ) | ELit (LBool _) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as TInt e)) + | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as TUnit e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | ETuple es -> ( let tau' = UnionFind.get (UnionFind.find tau) in diff --git a/src/catala/driver.ml b/src/catala/driver.ml index e08cc5e5..afa7ea58 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -102,6 +102,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ close_out oc; 0 | Cli.Run -> + Cli.debug_print "Name resolution..."; let ctxt = Surface.Name_resolution.form_context program in let scope_uid = match ex_scope with @@ -113,9 +114,13 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ (Printf.sprintf "There is no scope %s inside the program." name) | Some uid -> uid ) in + Cli.debug_print "Desugaring..."; let prgm = Surface.Desugaring.desugar_program ctxt program in + Cli.debug_print "Collecting rules..."; let prgm = Desugared.Desugared_to_scope.translate_program prgm in - let _prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in + Cli.debug_print "Translating to default calculus..."; + let prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in + Cli.result_print (Format.asprintf "Resulting program:@\n%a" Dcalc.Print.format_expr prgm); (* Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index db355e2b..5b81f4db 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -14,6 +14,7 @@ module Pos = Utils.Pos module Errors = Utils.Errors +module Cli = Utils.Cli type ctx = { scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; @@ -30,20 +31,29 @@ let empty_ctx = type scope_ctx = Dcalc.Ast.Var.t Ast.ScopeMap.t -let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("hole", Pos.no_pos) +let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("·", Pos.no_pos) -let merge_operator_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("merge", Pos.no_pos) +let merge_operator_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("(++)", Pos.no_pos) let merge_operator_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var merge_operator_var let hole_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var hole_var -let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked = - Pos.same_pos_as +let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked Bindlib.box + = + Bindlib.box_apply + (fun (x : Dcalc.Ast.expr) -> Pos.same_pos_as x e) ( match Pos.unmark e with - | EVar v -> Dcalc.Ast.EVar (Ast.VarMap.find v ctx.local_vars) - | ELit l -> Dcalc.Ast.ELit l - | EApp (e1, args) -> Dcalc.Ast.EApp (translate_expr ctx e1, List.map (translate_expr ctx) args) + | EVar v -> + Bindlib.box_apply + (fun e -> Pos.unmark e) + (Bindlib.box_var (Ast.VarMap.find v ctx.local_vars)) + | ELit l -> Bindlib.box (Dcalc.Ast.ELit l) + | EApp (e1, args) -> + Bindlib.box_apply2 + (fun e u -> Dcalc.Ast.EApp (e, u)) + (translate_expr ctx e1) + (Bindlib.box_list (List.map (translate_expr ctx) args)) | EAbs (pos_binder, binder, typ) -> let xs, body = Bindlib.unmbind binder in let new_xs = Array.map (fun x -> Dcalc.Ast.Var.make (Bindlib.name_of x, pos_binder)) xs in @@ -59,22 +69,26 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po } body in - let binder = Bindlib.unbox (Bindlib.bind_mvar new_xs (Bindlib.box body)) in - Dcalc.Ast.EAbs (pos_binder, binder, typ) + let binder = Bindlib.bind_mvar new_xs body in + Bindlib.box_apply (fun b -> Dcalc.Ast.EAbs (pos_binder, b, typ)) binder | EDefault (just, cons, subs) -> - Dcalc.Ast.EDefault - (translate_expr ctx just, translate_expr ctx cons, List.map (translate_expr ctx) subs) + Bindlib.box_apply3 + (fun j c s -> Dcalc.Ast.EDefault (j, c, s)) + (translate_expr ctx just) (translate_expr ctx cons) + (Bindlib.box_list (List.map (translate_expr ctx) subs)) | ELocation (ScopeVar a) -> - Dcalc.Ast.EVar (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars)) + Bindlib.box (Dcalc.Ast.EVar (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars))) | ELocation (SubScopeVar (_, s, a)) -> - Dcalc.Ast.EVar - (fst - (Ast.ScopeVarMap.find (Pos.unmark a) - (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) + Bindlib.box + (Dcalc.Ast.EVar + (fst + (Ast.ScopeVarMap.find (Pos.unmark a) + (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars)))) | EIfThenElse (cond, et, ef) -> - Dcalc.Ast.EIfThenElse (translate_expr ctx cond, translate_expr ctx et, translate_expr ctx ef) - | EOp op -> EOp op ) - e + Bindlib.box_apply3 + (fun c t f -> Dcalc.Ast.EIfThenElse (c, t, f)) + (translate_expr ctx cond) (translate_expr ctx et) (translate_expr ctx ef) + | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) ) let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = @@ -82,18 +96,12 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in - let next_e = - Dcalc.Ast.make_abs - (Array.of_list [ a_var ]) - hole_expr (Pos.get_position a) [ tau ] (Pos.get_position e) - in - let silent1 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in - let silent2 = Dcalc.Ast.Var.make ("silent", Pos.get_position e) in + let silent1 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in + let silent2 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in let wrapped_e = Dcalc.Ast.make_abs (Array.of_list [ silent1 ]) - (Bindlib.box (translate_expr ctx e)) - (Pos.get_position e) + (translate_expr ctx e) (Pos.get_position e) [ (Dcalc.Ast.TUnit, var_def_pos) ] var_def_pos in @@ -107,14 +115,30 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : [ (Dcalc.Ast.TUnit, var_def_pos) ] var_def_pos in - let final_e = Dcalc.Ast.make_app merged_thunked [ next_e ] (Pos.get_position e) in + let apply_thunked = + Bindlib.box_apply2 + (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) + (Bindlib.box_var a_var) + (Bindlib.box_list [ Bindlib.box (Dcalc.Ast.ELit LUnit, var_def_pos) ]) + in + let next_e = + Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked hole_expr (Pos.get_position a) + in + let intermediate_e = + Dcalc.Ast.make_abs + (Array.of_list [ a_var ]) + next_e (Pos.get_position a) + [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] + (Pos.get_position e) + in + let out_e = Dcalc.Ast.make_app intermediate_e [ merged_thunked ] (Pos.get_position e) in let new_ctx = { ctx with scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; } in - (final_e, new_ctx) + (out_e, new_ctx) | Definition ((SubScopeVar _, _), _tau, _e) -> Errors.raise_error "translation of subscope vars definitions unimplemented" | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" @@ -122,22 +146,30 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : let translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = let acc = hole_expr in - List.fold_left - (fun (acc, ctx) rule -> - let new_e, ctx = translate_rule p ctx rule in - let acc = Bindlib.unbox (Bindlib.bind_var hole_var acc) in - let new_acc = Bindlib.subst acc (Bindlib.unbox new_e) in - (Bindlib.box new_acc, ctx)) - (acc, ctx) rules + let out = + List.fold_left + (fun (acc, ctx) rule -> + let new_e, ctx = translate_rule p ctx rule in + Cli.debug_print + (Format.asprintf "Translating rule:@\n%a" Dcalc.Print.format_expr (Bindlib.unbox new_e)); + let acc = Bindlib.bind_var hole_var acc in + let new_acc = Bindlib.box_apply2 (fun acc new_e -> Bindlib.subst acc new_e) acc new_e in + (new_acc, ctx)) + (acc, ctx) rules + in + out -let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked = +let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : + Dcalc.Ast.expr Pos.marked Bindlib.box = let ctx = empty_ctx in let rules, ctx = translate_rules p ctx sigma.scope_decl_rules in let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in let return_exp = - Dcalc.Ast.ETuple - (List.map (fun (_, (dcalc_var, _)) -> (Dcalc.Ast.EVar dcalc_var, pos_sigma)) scope_variables) + Bindlib.box_apply + (fun args -> (Dcalc.Ast.ETuple args, pos_sigma)) + (Bindlib.box_list + (List.map (fun (_, (dcalc_var, _)) -> Bindlib.box_var dcalc_var) scope_variables)) in let func_acc = rules in let func_acc = @@ -150,8 +182,10 @@ let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.ex scope_variables) pos_sigma in - let func_acc = Bindlib.unbox (Bindlib.bind_var hole_var func_acc) in - Bindlib.subst func_acc (return_exp, pos_sigma) + let func_acc = Bindlib.bind_var hole_var func_acc in + Bindlib.box_apply2 + (fun func_acc return_exp -> Bindlib.subst func_acc return_exp) + func_acc return_exp let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = @@ -167,15 +201,16 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let acc = translate_scope_decl scope_ctx top_level_scope in (* the resulting expression is the list of definitions of all the scopes, ending with the top-level scope. *) - List.fold_right - (fun scope_name (acc : Dcalc.Ast.expr Pos.marked) -> - if scope_name = top_level_scope_name then acc - else - let scope = Ast.ScopeMap.find scope_name prgm in - let scope_expr = translate_scope_decl scope_ctx scope in - (* here we perform type-checking, incidentally *) - let scope_typ = Dcalc.Typing.infer_type scope_expr in - Dcalc.Ast.make_let_in - (Ast.ScopeMap.find scope_name scope_ctx, Pos.get_position scope_typ) - scope_typ scope_expr (Bindlib.box acc) Pos.no_pos) - scope_ordering acc + Bindlib.unbox + (List.fold_right + (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> + if scope_name = top_level_scope_name then acc + else + let scope = Ast.ScopeMap.find scope_name prgm in + let scope_expr = translate_scope_decl scope_ctx scope in + (* here we perform type-checking, incidentally *) + let scope_typ = Dcalc.Typing.infer_type (Bindlib.unbox scope_expr) in + Dcalc.Ast.make_let_in + (Ast.ScopeMap.find scope_name scope_ctx, Pos.get_position scope_typ) + scope_typ scope_expr acc Pos.no_pos) + scope_ordering acc) diff --git a/tests/test_bool/test_bool.catala b/tests/test_bool/test_bool.catala index a565daef..4d7e6edf 100644 --- a/tests/test_bool/test_bool.catala +++ b/tests/test_bool/test_bool.catala @@ -8,5 +8,5 @@ new scope TestBool : scope TestBool : def bar := 1 def foo [ bar >= 0 ] := true - def foo [ bar < 0 ] := false + def foo [ bar < 0 ] := false */ From 69f0751037e0ecf523b4d9ba0edf84af362567bd Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 15:48:26 +0100 Subject: [PATCH 026/142] Translate and typechecking simple exemple --- src/catala/catala_surface/parser.messages | 158 ++++++++++---------- src/catala/default_calculus/print.ml | 9 +- src/catala/default_calculus/typing.ml | 143 ++++++++++-------- src/catala/driver.ml | 4 +- src/catala/scope_language/scope_to_dcalc.ml | 140 ++++++++--------- tests/Makefile | 2 +- 6 files changed, 231 insertions(+), 225 deletions(-) diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 867218e3..cf35b0ba 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -416,16 +416,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 204, spurious reduction of production assertion_base -> expression -## In state 205, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 206, spurious reduction of production scope_item -> ASSERTION assertion +## In state 44, spurious reduction of production primitive_expression -> CARDINAL +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression +## In state 204, spurious reduction of production assertion_base -> expression +## In state 205, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 206, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item @@ -455,8 +455,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed @@ -498,14 +498,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 165, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 44, spurious reduction of production primitive_expression -> CARDINAL +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression +## In state 165, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition @@ -535,8 +535,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with @@ -554,8 +554,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item @@ -645,8 +645,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable @@ -736,8 +736,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule @@ -818,13 +818,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 104, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 44, spurious reduction of production primitive_expression -> CARDINAL +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 104, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another field of the struct or the end of the struct literal @@ -954,7 +954,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test @@ -1020,7 +1020,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test @@ -1086,13 +1086,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete @@ -1122,13 +1122,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete @@ -1182,13 +1182,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here @@ -1218,7 +1218,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression @@ -1236,13 +1236,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 103, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 149, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 103, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 149, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete @@ -1393,7 +1393,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate @@ -1471,15 +1471,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 157, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 158, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 86, spurious reduction of production mult_expression -> base_expression +## In state 81, spurious reduction of production sum_expression -> mult_expression +## In state 73, spurious reduction of production compare_expression -> sum_expression +## In state 105, spurious reduction of production logical_expression -> compare_expression +## In state 112, spurious reduction of production expression -> logical_expression +## In state 157, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 158, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition @@ -1522,8 +1522,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left @@ -1604,7 +1604,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 48, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 744743dc..dbee9429 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -15,7 +15,14 @@ module Pos = Utils.Pos open Ast +let typ_needs_parens (e : typ Pos.marked) : bool = + match Pos.unmark e with TArrow _ -> true | _ -> false + let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = + let format_typ_with_parens (fmt : Format.formatter) (t : typ Pos.marked) = + if typ_needs_parens t then Format.fprintf fmt "(%a)" format_typ t + else Format.fprintf fmt "%a" format_typ t + in match Pos.unmark typ with | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" @@ -24,7 +31,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ_with_parens t1 format_typ t2 let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 1d4c63d8..a0dc928d 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -18,6 +18,7 @@ module Pos = Utils.Pos module Errors = Utils.Errors module A = Ast +module Cli = Utils.Cli type typ = | TUnit @@ -33,7 +34,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TInt -> Format.fprintf fmt "int" - | TAny -> Format.fprintf fmt "any" + | TAny -> Format.fprintf fmt "α" | TTuple ts -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) @@ -41,6 +42,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = + (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with @@ -105,75 +107,86 @@ type env = typ Pos.marked A.VarMap.t let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem = - match Pos.unmark e with - | EVar v -> ( - match A.VarMap.find_opt v env with - | Some t -> UnionFind.make t - | None -> - Errors.raise_spanned_error "Variable not found in the current context" - (Pos.get_position e) ) - | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) - | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) - | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) - | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) - | ETuple es -> - let ts = List.map (typecheck_expr_bottom_up env) es in - UnionFind.make (Pos.same_pos_as (TTuple ts) e) - | ETupleAccess (e1, n) -> ( - let t1 = typecheck_expr_bottom_up env e1 in - match Pos.unmark (UnionFind.get (UnionFind.find t1)) with - | TTuple ts -> ( - match List.nth_opt ts n with - | Some t' -> t' - | None -> - Errors.raise_spanned_error - (Format.asprintf - "expression should have a tuple type with at least %d elements but only has %d" n - (List.length ts)) - (Pos.get_position e1) ) - | _ -> + (* Cli.debug_print (Format.asprintf "Up begin: %a" Print.format_expr e); *) + let out = + match Pos.unmark e with + | EVar v -> ( + match A.VarMap.find_opt v env with + | Some t -> UnionFind.make t + | None -> + Errors.raise_spanned_error "Variable not found in the current context" + (Pos.get_position e) ) + | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) + | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) + | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) + | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) + | ETuple es -> + let ts = List.map (typecheck_expr_bottom_up env) es in + UnionFind.make (Pos.same_pos_as (TTuple ts) e) + | ETupleAccess (e1, n) -> ( + let t1 = typecheck_expr_bottom_up env e1 in + match Pos.unmark (UnionFind.get (UnionFind.find t1)) with + | TTuple ts -> ( + match List.nth_opt ts n with + | Some t' -> t' + | None -> + Errors.raise_spanned_error + (Format.asprintf + "expression should have a tuple type with at least %d elements but only has %d" + n (List.length ts)) + (Pos.get_position e1) ) + | _ -> + Errors.raise_spanned_error + (Format.asprintf "exprected a tuple, got a %a" format_typ t1) + (Pos.get_position e1) ) + | EAbs (pos_binder, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + if Array.length xs = List.length taus then + let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let env = + List.fold_left + (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) + env xstaus + in + List.fold_right + (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> + UnionFind.make + (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) + taus + (typecheck_expr_bottom_up env body) + else Errors.raise_spanned_error - (Format.asprintf "exprected a tuple, got a %a" format_typ t1) - (Pos.get_position e1) ) - | EAbs (pos_binder, binder, taus) -> - let xs, body = Bindlib.unmbind binder in - if Array.length xs = List.length taus then - let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - let env = - List.fold_left - (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) - env xstaus + (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) + (List.length taus)) + pos_binder + | EApp (e1, args) -> + let t_args = List.map (typecheck_expr_bottom_up env) args in + let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + let t_app = + List.fold_right + (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + t_args t_ret in - typecheck_expr_bottom_up env body - else - Errors.raise_spanned_error - (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) - (List.length taus)) - pos_binder - | EApp (e1, args) -> - let t_args = List.map (typecheck_expr_bottom_up env) args in - let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in - let t_app = - List.fold_right - (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) - t_args t_ret - in - typecheck_expr_top_down env e1 t_app; - t_app - | EOp op -> op_type (Pos.same_pos_as op e) - | EDefault (just, cons, subs) -> - typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); - let tcons = typecheck_expr_bottom_up env cons in - List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; - tcons - | EIfThenElse (cond, et, ef) -> - typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); - let tt = typecheck_expr_bottom_up env et in - typecheck_expr_top_down env ef tt; - tt + typecheck_expr_top_down env e1 t_app; + t_ret + | EOp op -> op_type (Pos.same_pos_as op e) + | EDefault (just, cons, subs) -> + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + let tcons = typecheck_expr_bottom_up env cons in + List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; + tcons + | EIfThenElse (cond, et, ef) -> + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + let tt = typecheck_expr_bottom_up env et in + typecheck_expr_top_down env ef tt; + tt + in + (* Cli.debug_print (Format.asprintf "Up result: %a | %a" Print.format_expr e format_typ out); *) + out and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = + (* Cli.debug_print (Format.asprintf "Down: %a | %a" Print.format_expr e format_typ tau); *) match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt v env with diff --git a/src/catala/driver.ml b/src/catala/driver.ml index afa7ea58..4a0ed91e 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -38,7 +38,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ if backend = "Makefile" then Cli.Makefile else if backend = "LaTeX" then Cli.Latex else if backend = "HTML" then Cli.Html - else if backend = "run" then Cli.Run + else if backend = "Interpret" then Cli.Run else Errors.raise_error (Printf.sprintf "The selected backend (%s) is not supported by Catala" backend) @@ -121,6 +121,8 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ Cli.debug_print "Translating to default calculus..."; let prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in Cli.result_print (Format.asprintf "Resulting program:@\n%a" Dcalc.Print.format_expr prgm); + let typ = Dcalc.Typing.infer_type prgm in + Cli.result_print (Format.asprintf "Inferred_type:@\n%a" Dcalc.Print.format_typ typ); (* Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 5b81f4db..15028ac9 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -33,21 +33,32 @@ type scope_ctx = Dcalc.Ast.Var.t Ast.ScopeMap.t let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("·", Pos.no_pos) -let merge_operator_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("(++)", Pos.no_pos) - -let merge_operator_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var merge_operator_var - -let hole_expr : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_var hole_var +let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) + (callee : Dcalc.Ast.expr Pos.marked Bindlib.box) : Dcalc.Ast.expr Pos.marked Bindlib.box = + let caller = + Dcalc.Ast.make_app caller + [ Bindlib.box (Dcalc.Ast.ELit Dcalc.Ast.LUnit, Pos.no_pos) ] + Pos.no_pos + in + let body = + Bindlib.box_apply2 + (fun caller callee -> + ( Dcalc.Ast.EDefault + ((Dcalc.Ast.ELit (Dcalc.Ast.LBool true), Pos.no_pos), caller, [ callee ]), + Pos.no_pos )) + caller callee + in + let silent = Dcalc.Ast.Var.make ("_", Pos.no_pos) in + Dcalc.Ast.make_abs + (Array.of_list [ silent ]) + body Pos.no_pos [ (Dcalc.Ast.TUnit, Pos.no_pos) ] Pos.no_pos let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked Bindlib.box = Bindlib.box_apply (fun (x : Dcalc.Ast.expr) -> Pos.same_pos_as x e) ( match Pos.unmark e with - | EVar v -> - Bindlib.box_apply - (fun e -> Pos.unmark e) - (Bindlib.box_var (Ast.VarMap.find v ctx.local_vars)) + | EVar v -> Bindlib.box_apply Pos.unmark (Bindlib.box_var (Ast.VarMap.find v ctx.local_vars)) | ELit l -> Bindlib.box (Dcalc.Ast.ELit l) | EApp (e1, args) -> Bindlib.box_apply2 @@ -77,10 +88,11 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (translate_expr ctx just) (translate_expr ctx cons) (Bindlib.box_list (List.map (translate_expr ctx) subs)) | ELocation (ScopeVar a) -> - Bindlib.box (Dcalc.Ast.EVar (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars))) + Bindlib.box_apply Pos.unmark + (Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars))) | ELocation (SubScopeVar (_, s, a)) -> - Bindlib.box - (Dcalc.Ast.EVar + Bindlib.box_apply Pos.unmark + (Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars)))) @@ -90,39 +102,29 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (translate_expr ctx cond) (translate_expr ctx et) (translate_expr ctx ef) | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) ) -let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : - Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = +let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) + (pos_sigma : Pos.t) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rule with | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in - let silent1 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in - let silent2 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in - let wrapped_e = - Dcalc.Ast.make_abs - (Array.of_list [ silent1 ]) - (translate_expr ctx e) (Pos.get_position e) - [ (Dcalc.Ast.TUnit, var_def_pos) ] - var_def_pos - in - let a_expr = Dcalc.Ast.make_var a_var in - let merged_expr = Dcalc.Ast.make_app merge_operator_expr [ a_expr ] (Pos.get_position e) in - let merged_expr = Dcalc.Ast.make_app merged_expr [ wrapped_e ] (Pos.get_position e) in - let merged_thunked = - Dcalc.Ast.make_abs - (Array.of_list [ silent2 ]) - merged_expr (Pos.get_position e) - [ (Dcalc.Ast.TUnit, var_def_pos) ] - var_def_pos - in + let _silent1 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in + let _silent2 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in let apply_thunked = Bindlib.box_apply2 (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) (Bindlib.box_var a_var) (Bindlib.box_list [ Bindlib.box (Dcalc.Ast.ELit LUnit, var_def_pos) ]) in + let new_ctx = + { + ctx with + scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; + } + in + let next_e, new_ctx = translate_rules p new_ctx rest pos_sigma in let next_e = - Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked hole_expr (Pos.get_position a) + Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked next_e (Pos.get_position a) in let intermediate_e = Dcalc.Ast.make_abs @@ -131,61 +133,43 @@ let translate_rule (_p : scope_ctx) (ctx : ctx) (rule : Ast.rule) : [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] (Pos.get_position e) in - let out_e = Dcalc.Ast.make_app intermediate_e [ merged_thunked ] (Pos.get_position e) in - let new_ctx = - { - ctx with - scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; - } - in + let new_e = translate_expr ctx e in + let a_expr = Dcalc.Ast.make_var a_var in + let merged_expr = merge_defaults a_expr new_e in + let out_e = Dcalc.Ast.make_app intermediate_e [ merged_expr ] (Pos.get_position e) in (out_e, new_ctx) | Definition ((SubScopeVar _, _), _tau, _e) -> Errors.raise_error "translation of subscope vars definitions unimplemented" | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" -let translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) : +and translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = - let acc = hole_expr in - let out = - List.fold_left - (fun (acc, ctx) rule -> - let new_e, ctx = translate_rule p ctx rule in - Cli.debug_print - (Format.asprintf "Translating rule:@\n%a" Dcalc.Print.format_expr (Bindlib.unbox new_e)); - let acc = Bindlib.bind_var hole_var acc in - let new_acc = Bindlib.box_apply2 (fun acc new_e -> Bindlib.subst acc new_e) acc new_e in - (new_acc, ctx)) - (acc, ctx) rules - in - out + match rules with + | [] -> + let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in + let return_exp = + Bindlib.box_apply + (fun args -> (Dcalc.Ast.ETuple args, pos_sigma)) + (Bindlib.box_list + (List.map (fun (_, (dcalc_var, _)) -> Bindlib.box_var dcalc_var) scope_variables)) + in + (return_exp, ctx) + | hd :: tl -> translate_rule p ctx hd tl pos_sigma let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = let ctx = empty_ctx in - let rules, ctx = translate_rules p ctx sigma.scope_decl_rules in - let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in - let return_exp = - Bindlib.box_apply - (fun args -> (Dcalc.Ast.ETuple args, pos_sigma)) - (Bindlib.box_list - (List.map (fun (_, (dcalc_var, _)) -> Bindlib.box_var dcalc_var) scope_variables)) - in - let func_acc = rules in - let func_acc = - Dcalc.Ast.make_abs - (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) - func_acc pos_sigma - (List.map - (fun (_, (_, tau)) -> - (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) - scope_variables) - pos_sigma - in - let func_acc = Bindlib.bind_var hole_var func_acc in - Bindlib.box_apply2 - (fun func_acc return_exp -> Bindlib.subst func_acc return_exp) - func_acc return_exp + let rules, ctx = translate_rules p ctx sigma.scope_decl_rules pos_sigma in + let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in + Dcalc.Ast.make_abs + (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) + rules pos_sigma + (List.map + (fun (_, (_, tau)) -> + (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) + scope_variables) + pos_sigma let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = diff --git a/tests/Makefile b/tests/Makefile index 9f3e5388..bf22b58f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,7 +2,7 @@ # Preamble ############################################ -CATALA=dune exec --no-print-director ../src/catala.exe -- run +CATALA=dune exec --no-print-director ../src/catala.exe -- Interpret tests: $(wildcard */*.catala) From 4a181ab4b7c167b4a2c2b1d65dad22825c71d122 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 16:22:08 +0100 Subject: [PATCH 027/142] First test passing --- src/catala/default_calculus/interpreter.ml | 34 ++++++++++++++++++- src/catala/driver.ml | 17 +++++++--- tests/test_bool/test_bool.catala.TestBool.out | 2 +- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 6d2dbaef..d167215a 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -107,7 +107,14 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = let just = evaluate_expr just in match Pos.unmark just with | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e - | ELit (LBool true) -> evaluate_expr cons + | ELit (LBool true) -> ( + match evaluate_expr cons with + | ELit LEmptyError, pos -> + evaluate_expr + (Pos.same_pos_as + (Ast.EDefault ((ELit (LBool false), pos), (Ast.ELit LEmptyError, pos), subs)) + e) + | e' -> e' ) | ELit (LBool false) -> ( let subs = List.map evaluate_expr subs in let empty_count = List.length (List.filter is_empty_error subs) in @@ -140,3 +147,28 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = "expected a boolean literal for the result of this condition (should not happen if the \ term was well-typed)" (Pos.get_position cond) ) + +let empty_thunked_term : Ast.expr Pos.marked = + let silent = Ast.Var.make ("silent", Pos.no_pos) in + Bindlib.unbox + (Ast.make_abs + (Array.of_list [ silent ]) + (Bindlib.box (Ast.ELit Ast.LEmptyError, Pos.no_pos)) + Pos.no_pos [ (Ast.TUnit, Pos.no_pos) ] Pos.no_pos) + +let interpret_program (e : Ast.expr Pos.marked) : (Ast.Var.t * Ast.expr Pos.marked) list = + match Pos.unmark e with + | Ast.EAbs (_, binder, taus) -> ( + let application_term = List.map (fun _ -> empty_thunked_term) taus in + let to_interpret = (Ast.EApp (e, application_term), Pos.no_pos) in + match Pos.unmark (evaluate_expr to_interpret) with + | Ast.ETuple args -> + let vars, _ = Bindlib.unmbind binder in + List.map2 (fun arg var -> (var, arg)) args (Array.to_list vars) + | _ -> + Errors.raise_spanned_error "The interpretation of a program should always yield a tuple" + (Pos.get_position e) ) + | _ -> + Errors.raise_spanned_error + "The interpreter can only interpret terms starting with functions having thunked arguments" + (Pos.get_position e) diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 4a0ed91e..fae6d0a6 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -120,12 +120,19 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ let prgm = Desugared.Desugared_to_scope.translate_program prgm in Cli.debug_print "Translating to default calculus..."; let prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in - Cli.result_print (Format.asprintf "Resulting program:@\n%a" Dcalc.Print.format_expr prgm); let typ = Dcalc.Typing.infer_type prgm in - Cli.result_print (Format.asprintf "Inferred_type:@\n%a" Dcalc.Print.format_typ typ); - (* Lambda_interpreter.ExecContext.iter (fun context_key value -> Cli.result_print - (Printf.sprintf "%s -> %s" (Lambda_interpreter.ExecContextKey.format_t context_key) - (Format_lambda.print_term ((value, Pos.no_pos), TDummy)))) exec_ctxt; *) + Cli.debug_print (Format.asprintf "Typechecking results :@\n%a" Dcalc.Print.format_typ typ); + let results = Dcalc.Interpreter.interpret_program prgm in + let results = + List.sort + (fun (v1, _) (v2, _) -> String.compare (Bindlib.name_of v1) (Bindlib.name_of v2)) + results + in + List.iter + (fun (var, result) -> + Cli.result_print + (Format.asprintf "%s -> %a" (Bindlib.name_of var) Dcalc.Print.format_expr result)) + results; 0 with Errors.StructuredError (msg, pos) -> Cli.error_print (Errors.print_structured_error msg pos); diff --git a/tests/test_bool/test_bool.catala.TestBool.out b/tests/test_bool/test_bool.catala.TestBool.out index 418a3841..7b15996f 100644 --- a/tests/test_bool/test_bool.catala.TestBool.out +++ b/tests/test_bool/test_bool.catala.TestBool.out @@ -1,2 +1,2 @@ -[RESULT] foo -> true [RESULT] bar -> 1 +[RESULT] foo -> true From 453c3afc9123fdff28f4f250477f26d57efef027 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 16:32:52 +0100 Subject: [PATCH 028/142] Another example passing --- src/catala/default_calculus/interpreter.ml | 18 +++++++++------- tests/test_scope/scope.catala | 2 +- tests/test_scope/scope.catala.A.out | 24 ++++++++-------------- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index d167215a..5c21da95 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -123,14 +123,18 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = | 1 -> List.find (fun sub -> not (is_empty_error sub)) subs | _ -> Errors.raise_multispanned_error - "there is a conflict between multiple rules for assigning a single value." - ( [ - ( Some "This rule is not triggered, so we consider rules of lower priority:", - Pos.get_position e ); - ] + "There is a conflict between multiple rules for assigning the same variable." + ( ( if Pos.get_position e = Pos.no_pos then [] + else + [ + ( Some "This rule is not triggered, so we consider rules of lower priority:", + Pos.get_position e ); + ] ) @ List.map (fun sub -> - ( Some "This value is available because the justification of its rule is true:", + ( Some + "This value is available because the justification of its definition is \ + true:", Pos.get_position sub )) (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) | _ -> @@ -144,7 +148,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = | ELit (LBool false) -> evaluate_expr ef | _ -> Errors.raise_spanned_error - "expected a boolean literal for the result of this condition (should not happen if the \ + "Expected a boolean literal for the result of this condition (should not happen if the \ term was well-typed)" (Pos.get_position cond) ) diff --git a/tests/test_scope/scope.catala b/tests/test_scope/scope.catala index 9fe51cbe..d2bd8eb7 100644 --- a/tests/test_scope/scope.catala +++ b/tests/test_scope/scope.catala @@ -3,7 +3,7 @@ /* new scope A: param a type int - param b type dec + param b type int param c type bool scope A: diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index a26f2577..b7a8f8e3 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -1,19 +1,13 @@ -[ERROR] Default logic conflict, multiple justifications are true but are not related by a precedence -[ERROR] -[ERROR] The conflict concerns this variable b -[ERROR] --> test_scope/scope.catala -[ERROR] | -[ERROR] 6 | param b type dec -[ERROR] | ^ -[ERROR] -[ERROR] This justification is true: +[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] +[ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/scope.catala -[ERROR] | +[ERROR] | [ERROR] 13 | def b [ not c ] := 1337 -[ERROR] | ^^^^^ -[ERROR] -[ERROR] This justification is true: +[ERROR] | ^^^^ +[ERROR] +[ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/scope.catala -[ERROR] | +[ERROR] | [ERROR] 14 | def b [ not c ] := 0 -[ERROR] | ^^^^^ +[ERROR] | ^ From 3869f60669b9856c90ab41284a9ece4d718e9892 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 26 Nov 2020 17:06:32 +0100 Subject: [PATCH 029/142] WIP --- src/catala/driver.ml | 1 + src/catala/scope_language/scope_to_dcalc.ml | 75 ++++++++++++++++----- 2 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/catala/driver.ml b/src/catala/driver.ml index fae6d0a6..da54148a 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -120,6 +120,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ let prgm = Desugared.Desugared_to_scope.translate_program prgm in Cli.debug_print "Translating to default calculus..."; let prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in + Cli.debug_print (Format.asprintf "Output program:@\n%a" Dcalc.Print.format_expr prgm); let typ = Dcalc.Typing.infer_type prgm in Cli.debug_print (Format.asprintf "Typechecking results :@\n%a" Dcalc.Print.format_typ typ); let results = Dcalc.Interpreter.interpret_program prgm in diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 15028ac9..68eb05f0 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -16,14 +16,18 @@ module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli +type scopes_ctx = Ast.ScopeVar.t list Ast.ScopeMap.t + type ctx = { + scopes_parameters : scopes_ctx; scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; local_vars : Dcalc.Ast.Var.t Ast.VarMap.t; } -let empty_ctx = +let empty_ctx (scopes_ctx : scopes_ctx) = { + scopes_parameters = scopes_ctx; scope_vars = Ast.ScopeVarMap.empty; subscope_vars = Ast.SubScopeMap.empty; local_vars = Ast.VarMap.empty; @@ -108,8 +112,6 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in - let _silent1 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in - let _silent2 = Dcalc.Ast.Var.make ("_", Pos.get_position e) in let apply_thunked = Bindlib.box_apply2 (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) @@ -138,8 +140,47 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast let merged_expr = merge_defaults a_expr new_e in let out_e = Dcalc.Ast.make_app intermediate_e [ merged_expr ] (Pos.get_position e) in (out_e, new_ctx) - | Definition ((SubScopeVar _, _), _tau, _e) -> - Errors.raise_error "translation of subscope vars definitions unimplemented" + | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> + let a_name = + Pos.map_under_mark + (fun str -> str ^ "_" ^ Pos.unmark (Ast.SubScopeName.get_info (Pos.unmark subs_index))) + (Ast.ScopeVar.get_info (Pos.unmark subs_var)) + in + let a_var = Dcalc.Ast.Var.make a_name in + let apply_thunked = + Bindlib.box_apply2 + (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) + (Bindlib.box_var a_var) + (Bindlib.box_list [ Bindlib.box (Dcalc.Ast.ELit LUnit, var_def_pos) ]) + in + let new_ctx = + { + ctx with + subscope_vars = + Ast.SubScopeMap.update (Pos.unmark subs_index) + (fun map -> + match map with + | Some map -> + Some (Ast.ScopeVarMap.add (Pos.unmark subs_var) (a_var, Pos.unmark tau) map) + | None -> + Some (Ast.ScopeVarMap.singleton (Pos.unmark subs_var) (a_var, Pos.unmark tau))) + ctx.subscope_vars; + } + in + let next_e, new_ctx = translate_rules p new_ctx rest pos_sigma in + let next_e = + Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked next_e var_def_pos + in + let intermediate_e = + Dcalc.Ast.make_abs + (Array.of_list [ a_var ]) + next_e var_def_pos + [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] + (Pos.get_position e) + in + let new_e = translate_expr ctx e in + let out_e = Dcalc.Ast.make_app intermediate_e [ new_e ] (Pos.get_position e) in + (out_e, new_ctx) | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" and translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : @@ -156,20 +197,22 @@ and translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) (pos_sig (return_exp, ctx) | hd :: tl -> translate_rule p ctx hd tl pos_sigma -let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) : - Dcalc.Ast.expr Pos.marked Bindlib.box = - let ctx = empty_ctx in +let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) (sctx : scopes_ctx) : + Dcalc.Ast.expr Pos.marked Bindlib.box * scopes_ctx = + let ctx = empty_ctx ctx in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in let rules, ctx = translate_rules p ctx sigma.scope_decl_rules pos_sigma in let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in - Dcalc.Ast.make_abs - (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) - rules pos_sigma - (List.map - (fun (_, (_, tau)) -> - (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) - scope_variables) - pos_sigma + let scope_parameters : Ast.ScopeVar.t list = (List.map (fun (x, (_, _)) -> x)) scope_variables in + ( Dcalc.Ast.make_abs + (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) + rules pos_sigma + (List.map + (fun (_, (_, tau)) -> + (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) + scope_variables) + pos_sigma, + Ast.ScopeMap.add sigma.scope_decl_name scope_parameters sctx ) let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = From 341ee710d88830a52d1ab00bd5c9c9dd7220b2b0 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 11:37:21 +0100 Subject: [PATCH 030/142] Fixed translation bug --- src/catala/default_calculus/interpreter.ml | 2 +- src/catala/default_calculus/print.ml | 2 +- src/catala/default_calculus/typing.ml | 2 +- src/catala/desugared/ast.ml | 13 +- src/catala/desugared/dependency.ml | 24 ++- src/catala/desugared/desugared_to_scope.ml | 13 +- src/catala/scope_language/ast.ml | 10 +- src/catala/scope_language/dependency.ml | 8 +- src/catala/scope_language/scope_to_dcalc.ml | 215 ++++++++++++++------ tests/test_scope/sub_sub_scope.catala | 9 +- 10 files changed, 215 insertions(+), 83 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 5c21da95..013457e4 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -153,7 +153,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = (Pos.get_position cond) ) let empty_thunked_term : Ast.expr Pos.marked = - let silent = Ast.Var.make ("silent", Pos.no_pos) in + let silent = Ast.Var.make ("_", Pos.no_pos) in Bindlib.unbox (Ast.make_abs (Array.of_list [ silent ]) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index dbee9429..20bc2261 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -63,7 +63,7 @@ let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ -> true | _ -> false let format_var (fmt : Format.formatter) (v : Var.t) : unit = - Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v) + Format.fprintf fmt "%s" (Bindlib.name_of v) let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index a0dc928d..b33c507b 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -39,7 +39,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a -> %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index ef59bca4..ed361ccc 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -102,20 +102,21 @@ let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang. type program = scope Scopelang.Ast.ScopeMap.t -let free_variables (def : rule RuleMap.t) : ScopeDefSet.t = - let add_locs (acc : ScopeDefSet.t) (locs : Scopelang.Ast.location list) : ScopeDefSet.t = +let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t = + let add_locs (acc : Pos.t ScopeDefMap.t) (locs : Scopelang.Ast.location Pos.marked list) : + Pos.t ScopeDefMap.t = List.fold_left - (fun acc loc -> - ScopeDefSet.add + (fun acc (loc, loc_pos) -> + ScopeDefMap.add ( match loc with | Scopelang.Ast.ScopeVar v -> ScopeDef.Var (Pos.unmark v) | Scopelang.Ast.SubScopeVar (_, sub_index, sub_var) -> ScopeDef.SubScopeVar (Pos.unmark sub_index, Pos.unmark sub_var) ) - acc) + loc_pos acc) acc locs in RuleMap.fold (fun _ rule acc -> let locs = Scopelang.Ast.locations_used rule.just @ Scopelang.Ast.locations_used rule.cons in add_locs acc locs) - def ScopeDefSet.empty + def ScopeDefMap.empty diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index ccfbb069..249ad953 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -117,18 +117,34 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = Ast.ScopeDefMap.fold (fun def_key (def, _) g -> let fv = Ast.free_variables def in - Ast.ScopeDefSet.fold - (fun fv_def g -> + Ast.ScopeDefMap.fold + (fun fv_def fv_def_pos g -> match (def_key, fv_def) with | Ast.ScopeDef.Var defined, Ast.ScopeDef.Var used -> (* simple case *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) + if used = defined then + (* variable definitions cannot be recursive *) + Errors.raise_spanned_error + (Format.asprintf + "The variable %a is used in one of its definitions, but recursion is \ + forbidden in Catala" + Scopelang.Ast.ScopeVar.format_t defined) + fv_def_pos + else ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> (* here we are defining the input of a subscope using a var of the scope *) ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar (used, _) -> (* here we are defining the input of a scope with the output of another subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) + if used = defined then + (* subscopes are not recursive functions *) + Errors.raise_spanned_error + (Format.asprintf + "The subscope %a is used when defining one of its inputs, but recursion is \ + forbidden in Catala" + Scopelang.Ast.SubScopeName.format_t defined) + fv_def_pos + else ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) | Ast.ScopeDef.Var defined, Ast.ScopeDef.SubScopeVar (used, _) -> (* finally we define a scope var with the output of a subscope *) ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index b2515cc5..589a9e03 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -190,7 +190,18 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = sub_scope_vars_redefs @ [ Scopelang.Ast.Call (sub_scope, sub_scope_index) ]) scope_ordering) in - { Scopelang.Ast.scope_decl_name = scope.scope_uid; Scopelang.Ast.scope_decl_rules } + let scope_sig = + Scopelang.Ast.ScopeVarSet.fold + (fun var acc -> + let _, typ = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in + Scopelang.Ast.ScopeVarMap.add var typ acc) + scope.scope_vars Scopelang.Ast.ScopeVarMap.empty + in + { + Scopelang.Ast.scope_decl_name = scope.scope_uid; + Scopelang.Ast.scope_decl_rules; + Scopelang.Ast.scope_sig; + } let translate_program (pgrm : Ast.program) : Scopelang.Ast.program = Scopelang.Ast.ScopeMap.map translate_scope pgrm diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 30683db3..acb2a72b 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -45,9 +45,9 @@ type expr = | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked -let rec locations_used (e : expr Pos.marked) : location list = +let rec locations_used (e : expr Pos.marked) : location Pos.marked list = match Pos.unmark e with - | ELocation l -> [ l ] + | ELocation l -> [ (l, Pos.get_position e) ] | EVar _ | ELit _ | EOp _ -> [] | EAbs (_, binder, _) -> let _, body = Bindlib.unmbind binder in @@ -88,6 +88,10 @@ type rule = | Definition of location Pos.marked * Dcalc.Ast.typ Pos.marked * expr Pos.marked | Call of ScopeName.t * SubScopeName.t -type scope_decl = { scope_decl_name : ScopeName.t; scope_decl_rules : rule list } +type scope_decl = { + scope_decl_name : ScopeName.t; + scope_sig : Dcalc.Ast.typ Pos.marked ScopeVarMap.t; + scope_decl_rules : rule list; +} type program = scope_decl ScopeMap.t diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 9507b390..90600188 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -55,7 +55,13 @@ let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = (fun acc r -> match r with | Ast.Definition _ -> acc - | Ast.Call (subscope, _) -> Ast.ScopeNameSet.add subscope acc) + | Ast.Call (subscope, _) -> + if subscope = scope_name then + Errors.raise_spanned_error + "The scope %a is calling into itself as a subscope, which is forbidden since \ + Catala does not provide recursion" + (Pos.get_position (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) + else Ast.ScopeNameSet.add subscope acc) Ast.ScopeNameSet.empty scope.Ast.scope_decl_rules in Ast.ScopeNameSet.fold diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 68eb05f0..f4739c6e 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -16,16 +16,16 @@ module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli -type scopes_ctx = Ast.ScopeVar.t list Ast.ScopeMap.t +type scope_sigs_ctx = ((Ast.ScopeVar.t * Dcalc.Ast.typ) list * Dcalc.Ast.Var.t) Ast.ScopeMap.t type ctx = { - scopes_parameters : scopes_ctx; + scopes_parameters : scope_sigs_ctx; scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; local_vars : Dcalc.Ast.Var.t Ast.VarMap.t; } -let empty_ctx (scopes_ctx : scopes_ctx) = +let empty_ctx (scopes_ctx : scope_sigs_ctx) = { scopes_parameters = scopes_ctx; scope_vars = Ast.ScopeVarMap.empty; @@ -94,20 +94,29 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po | ELocation (ScopeVar a) -> Bindlib.box_apply Pos.unmark (Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars))) - | ELocation (SubScopeVar (_, s, a)) -> - Bindlib.box_apply Pos.unmark - (Bindlib.box_var - (fst - (Ast.ScopeVarMap.find (Pos.unmark a) - (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars)))) + | ELocation (SubScopeVar (_, s, a)) -> ( + try + Bindlib.box_apply Pos.unmark + (Bindlib.box_var + (fst + (Ast.ScopeVarMap.find (Pos.unmark a) + (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars)))) + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf + "The variable %a.%a cannot be used here, as subscope %a's results will not have \ + been computed yet" + Ast.SubScopeName.format_t (Pos.unmark s) Ast.ScopeVar.format_t (Pos.unmark a) + Ast.SubScopeName.format_t (Pos.unmark s)) + (Pos.get_position e) ) | EIfThenElse (cond, et, ef) -> Bindlib.box_apply3 (fun c t f -> Dcalc.Ast.EIfThenElse (c, t, f)) (translate_expr ctx cond) (translate_expr ctx et) (translate_expr ctx ef) | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) ) -let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) - (pos_sigma : Pos.t) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = +let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos_sigma : Pos.t) : + Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rule with | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in @@ -124,7 +133,7 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; } in - let next_e, new_ctx = translate_rules p new_ctx rest pos_sigma in + let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let next_e = Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked next_e (Pos.get_position a) in @@ -143,16 +152,10 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> let a_name = Pos.map_under_mark - (fun str -> str ^ "_" ^ Pos.unmark (Ast.SubScopeName.get_info (Pos.unmark subs_index))) - (Ast.ScopeVar.get_info (Pos.unmark subs_var)) + (fun str -> str ^ "." ^ Pos.unmark (Ast.ScopeVar.get_info (Pos.unmark subs_var))) + (Ast.SubScopeName.get_info (Pos.unmark subs_index)) in let a_var = Dcalc.Ast.Var.make a_name in - let apply_thunked = - Bindlib.box_apply2 - (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) - (Bindlib.box_var a_var) - (Bindlib.box_list [ Bindlib.box (Dcalc.Ast.ELit LUnit, var_def_pos) ]) - in let new_ctx = { ctx with @@ -167,10 +170,7 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast ctx.subscope_vars; } in - let next_e, new_ctx = translate_rules p new_ctx rest pos_sigma in - let next_e = - Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked next_e var_def_pos - in + let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let intermediate_e = Dcalc.Ast.make_abs (Array.of_list [ a_var ]) @@ -179,11 +179,85 @@ let rec translate_rule (p : scope_ctx) (ctx : ctx) (rule : Ast.rule) (rest : Ast (Pos.get_position e) in let new_e = translate_expr ctx e in - let out_e = Dcalc.Ast.make_app intermediate_e [ new_e ] (Pos.get_position e) in + let silent_var = Dcalc.Ast.Var.make ("_", Pos.no_pos) in + let thunked_new_e = + Dcalc.Ast.make_abs + (Array.of_list [ silent_var ]) + new_e var_def_pos + [ (Dcalc.Ast.TUnit, var_def_pos) ] + var_def_pos + in + let out_e = Dcalc.Ast.make_app intermediate_e [ thunked_new_e ] (Pos.get_position e) in (out_e, new_ctx) - | Call _ -> Errors.raise_error "translation of subscope calls unimplemented" + | Call (subname, subindex) -> + let all_subscope_vars, scope_dcalc_var = Ast.ScopeMap.find subname ctx.scopes_parameters in + let subscope_vars_defined = + try Ast.SubScopeMap.find subindex ctx.subscope_vars + with Not_found -> Ast.ScopeVarMap.empty + in + let subscope_var_not_yet_defined subvar = + not (Ast.ScopeVarMap.mem subvar subscope_vars_defined) + in + let subscope_args = + List.map + (fun (subvar, _) -> + if subscope_var_not_yet_defined subvar then + Bindlib.box Dcalc.Interpreter.empty_thunked_term + else + let a_var, _ = Ast.ScopeVarMap.find subvar subscope_vars_defined in + Bindlib.box_var a_var) + all_subscope_vars + in + let all_subscope_vars_dcalc = + List.map + (fun (subvar, tau) -> + let sub_dcalc_var = + Dcalc.Ast.Var.make + (Pos.map_under_mark + (fun s -> Pos.unmark (Ast.SubScopeName.get_info subindex) ^ "." ^ s) + (Ast.ScopeVar.get_info subvar)) + in + (subvar, tau, sub_dcalc_var)) + all_subscope_vars + in + let new_ctx = + { + ctx with + subscope_vars = + Ast.SubScopeMap.add subindex + (List.fold_left + (fun acc (var, tau, dvar) -> Ast.ScopeVarMap.add var (dvar, tau) acc) + Ast.ScopeVarMap.empty all_subscope_vars_dcalc) + ctx.subscope_vars; + } + in + let call_expr = + Bindlib.box_apply2 + (fun e u -> (Dcalc.Ast.EApp (e, u), Pos.no_pos)) + (Bindlib.box_var scope_dcalc_var) (Bindlib.box_list subscope_args) + in + let result_tuple_var = Dcalc.Ast.Var.make ("result", Pos.no_pos) in + let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in + let results_bindings, _ = + List.fold_right + (fun (_, tau, dvar) (acc, i) -> + let result_access = + Bindlib.box_apply + (fun r -> (Dcalc.Ast.ETupleAccess (r, i), pos_sigma)) + (Bindlib.box_var result_tuple_var) + in + ( Dcalc.Ast.make_let_in (dvar, pos_sigma) (tau, pos_sigma) result_access acc pos_sigma, + i - 1 )) + all_subscope_vars_dcalc + (next_e, List.length all_subscope_vars_dcalc - 1) + in + ( Dcalc.Ast.make_let_in (result_tuple_var, pos_sigma) + ( Dcalc.Ast.TTuple (List.map (fun (_, tau, _) -> (tau, pos_sigma)) all_subscope_vars_dcalc), + pos_sigma ) + call_expr results_bindings pos_sigma, + new_ctx ) -and translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : +and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rules with | [] -> @@ -195,49 +269,68 @@ and translate_rules (p : scope_ctx) (ctx : ctx) (rules : Ast.rule list) (pos_sig (List.map (fun (_, (dcalc_var, _)) -> Bindlib.box_var dcalc_var) scope_variables)) in (return_exp, ctx) - | hd :: tl -> translate_rule p ctx hd tl pos_sigma + | hd :: tl -> translate_rule ctx hd tl pos_sigma -let translate_scope_decl (p : scope_ctx) (sigma : Ast.scope_decl) (sctx : scopes_ctx) : - Dcalc.Ast.expr Pos.marked Bindlib.box * scopes_ctx = - let ctx = empty_ctx ctx in +let translate_scope_decl (sctx : scope_sigs_ctx) (sigma : Ast.scope_decl) : + Dcalc.Ast.expr Pos.marked Bindlib.box = + let ctx = empty_ctx sctx in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in - let rules, ctx = translate_rules p ctx sigma.scope_decl_rules pos_sigma in - let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in - let scope_parameters : Ast.ScopeVar.t list = (List.map (fun (x, (_, _)) -> x)) scope_variables in - ( Dcalc.Ast.make_abs - (Array.of_list ((List.map (fun (_, (x, _)) -> x)) scope_variables)) - rules pos_sigma - (List.map - (fun (_, (_, tau)) -> - (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) - scope_variables) - pos_sigma, - Ast.ScopeMap.add sigma.scope_decl_name scope_parameters sctx ) + let rules, ctx = translate_rules ctx sigma.scope_decl_rules pos_sigma in + let scope_variables, _ = Ast.ScopeMap.find sigma.scope_decl_name sctx in + let scope_variables = + List.map + (fun (x, tau) -> + let dcalc_x, _ = Ast.ScopeVarMap.find x ctx.scope_vars in + (x, tau, dcalc_x)) + scope_variables + in + Dcalc.Ast.make_abs + (Array.of_list ((List.map (fun (_, _, x) -> x)) scope_variables)) + rules pos_sigma + (List.map + (fun (_, tau, _) -> + (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) + scope_variables) + pos_sigma + +let build_scope_typ_from_sig (scope_sig : (Ast.ScopeVar.t * Dcalc.Ast.typ) list) (pos : Pos.t) : + Dcalc.Ast.typ Pos.marked = + let result_typ = (Dcalc.Ast.TTuple (List.map (fun (_, tau) -> (tau, pos)) scope_sig), pos) in + List.fold_right + (fun (_, arg_t) acc -> + (Dcalc.Ast.TArrow ((Dcalc.Ast.TArrow ((TUnit, pos), (arg_t, pos)), pos), acc), pos)) + scope_sig result_typ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = - let scope_ctx = - Ast.ScopeMap.map - (fun scope -> Dcalc.Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) - prgm - in let scope_dependencies = Dependency.build_program_dep_graph prgm in Dependency.check_for_cycle scope_dependencies; let scope_ordering = Dependency.get_scope_ordering scope_dependencies in - let top_level_scope = Ast.ScopeMap.find top_level_scope_name prgm in - let acc = translate_scope_decl scope_ctx top_level_scope in + let sctx : scope_sigs_ctx = + Ast.ScopeMap.map + (fun scope -> + let scope_dvar = Dcalc.Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name) in + ( List.map + (fun (scope_var, tau) -> (scope_var, Pos.unmark tau)) + (Ast.ScopeVarMap.bindings scope.scope_sig), + scope_dvar )) + prgm + in + (* the final expression on which we build on is the variable of the top-level scope that we are + returning *) + let acc = Bindlib.box_var (snd (Ast.ScopeMap.find top_level_scope_name sctx)) in (* the resulting expression is the list of definitions of all the scopes, ending with the top-level scope. *) Bindlib.unbox - (List.fold_right - (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> - if scope_name = top_level_scope_name then acc - else + (let acc = + List.fold_right + (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> let scope = Ast.ScopeMap.find scope_name prgm in - let scope_expr = translate_scope_decl scope_ctx scope in - (* here we perform type-checking, incidentally *) - let scope_typ = Dcalc.Typing.infer_type (Bindlib.unbox scope_expr) in - Dcalc.Ast.make_let_in - (Ast.ScopeMap.find scope_name scope_ctx, Pos.get_position scope_typ) - scope_typ scope_expr acc Pos.no_pos) - scope_ordering acc) + let pos_scope = Pos.get_position (Ast.ScopeName.get_info scope.scope_decl_name) in + let scope_expr = translate_scope_decl sctx scope in + let scope_sig, dvar = Ast.ScopeMap.find scope_name sctx in + let scope_typ = build_scope_typ_from_sig scope_sig pos_scope in + Dcalc.Ast.make_let_in (dvar, pos_scope) scope_typ scope_expr acc pos_scope) + scope_ordering acc + in + acc) diff --git a/tests/test_scope/sub_sub_scope.catala b/tests/test_scope/sub_sub_scope.catala index 42cb82a8..06ff9cfd 100644 --- a/tests/test_scope/sub_sub_scope.catala +++ b/tests/test_scope/sub_sub_scope.catala @@ -6,7 +6,8 @@ new scope A: param u type bool new scope B: - param a scope A + param a1 scope A + param a2 scope A param y type int new scope C: @@ -19,9 +20,9 @@ scope A: def u := true scope B: - def a.x [ a.u ] := 1 - def y [ a.x = 1 ] := 1 - def y [ a.x + 1 = 2 ] := 1 + def a2.x [ a1.u ] := 1 + def y [ a2.x = 1 ] := 1 + def y [ a2.x + 1 = 2 ] := 1 scope C: def a.x := 2 From 64cf1fd7cdb89a33a75001bf6b8d027f84008e7f Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 11:54:22 +0100 Subject: [PATCH 031/142] Test without func now pass! --- src/catala/default_calculus/interpreter.ml | 2 +- src/catala/default_calculus/print.ml | 2 +- src/catala/scope_language/scope_to_dcalc.ml | 27 ++++---------------- tests/test_scope/sub_scope.catala | 2 +- tests/test_scope/sub_scope.catala.A.out | 2 +- tests/test_scope/sub_scope.catala.B.out | 8 +----- tests/test_scope/sub_sub_scope.catala.A.out | 2 +- tests/test_scope/sub_sub_scope.catala.B.out | 28 ++++++++------------- tests/test_scope/sub_sub_scope.catala.C.out | 5 +--- 9 files changed, 23 insertions(+), 55 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 013457e4..a3e4f9e5 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -161,7 +161,7 @@ let empty_thunked_term : Ast.expr Pos.marked = Pos.no_pos [ (Ast.TUnit, Pos.no_pos) ] Pos.no_pos) let interpret_program (e : Ast.expr Pos.marked) : (Ast.Var.t * Ast.expr Pos.marked) list = - match Pos.unmark e with + match Pos.unmark (evaluate_expr e) with | Ast.EAbs (_, binder, taus) -> ( let application_term = List.map (fun _ -> empty_thunked_term) taus in let to_interpret = (Ast.EApp (e, application_term), Pos.no_pos) in diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 20bc2261..fadea637 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -115,6 +115,6 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = if List.length subs = 0 then Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons else - Format.fprintf fmt "@[⟨%a ⊢ %a | %a⟩@]" format_expr just format_expr cons + Format.fprintf fmt "@[⟨%a ⊢ %a |@ %a⟩@]" format_expr just format_expr cons (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) subs diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index f4739c6e..4d605e27 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -52,10 +52,7 @@ let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) Pos.no_pos )) caller callee in - let silent = Dcalc.Ast.Var.make ("_", Pos.no_pos) in - Dcalc.Ast.make_abs - (Array.of_list [ silent ]) - body Pos.no_pos [ (Dcalc.Ast.TUnit, Pos.no_pos) ] Pos.no_pos + body let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked Bindlib.box = @@ -121,12 +118,6 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in - let apply_thunked = - Bindlib.box_apply2 - (fun e u -> (Dcalc.Ast.EApp (e, u), var_def_pos)) - (Bindlib.box_var a_var) - (Bindlib.box_list [ Bindlib.box (Dcalc.Ast.ELit LUnit, var_def_pos) ]) - in let new_ctx = { ctx with @@ -134,21 +125,13 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos } in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in - let next_e = - Dcalc.Ast.make_let_in (a_var, var_def_pos) tau apply_thunked next_e (Pos.get_position a) - in - let intermediate_e = - Dcalc.Ast.make_abs - (Array.of_list [ a_var ]) - next_e (Pos.get_position a) - [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] - (Pos.get_position e) - in let new_e = translate_expr ctx e in let a_expr = Dcalc.Ast.make_var a_var in let merged_expr = merge_defaults a_expr new_e in - let out_e = Dcalc.Ast.make_app intermediate_e [ merged_expr ] (Pos.get_position e) in - (out_e, new_ctx) + let next_e = + Dcalc.Ast.make_let_in (a_var, var_def_pos) tau merged_expr next_e (Pos.get_position a) + in + (next_e, new_ctx) | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> let a_name = Pos.map_under_mark diff --git a/tests/test_scope/sub_scope.catala b/tests/test_scope/sub_scope.catala index 3bf6872a..90ff514d 100644 --- a/tests/test_scope/sub_scope.catala +++ b/tests/test_scope/sub_scope.catala @@ -20,5 +20,5 @@ scope A: scope B: def a := 42 def b := scopeA.b - def scopeA.a [ a > 0 ] := scopeA.a_base + def scopeA.a [ a > 0 ] := scopeAbis.a_base */ diff --git a/tests/test_scope/sub_scope.catala.A.out b/tests/test_scope/sub_scope.catala.A.out index 94c581f9..08227657 100644 --- a/tests/test_scope/sub_scope.catala.A.out +++ b/tests/test_scope/sub_scope.catala.A.out @@ -1,3 +1,3 @@ [RESULT] a -> -1 -[RESULT] b -> false [RESULT] a_base -> 1 +[RESULT] b -> false diff --git a/tests/test_scope/sub_scope.catala.B.out b/tests/test_scope/sub_scope.catala.B.out index bc8d148b..db60adbc 100644 --- a/tests/test_scope/sub_scope.catala.B.out +++ b/tests/test_scope/sub_scope.catala.B.out @@ -1,8 +1,2 @@ [RESULT] a -> 42 -[RESULT] b -> true -[RESULT] scopeA.a -> 1 -[RESULT] scopeA.b -> true -[RESULT] scopeA.a_base -> 1 -[RESULT] scopeAbis.a -> -1 -[RESULT] scopeAbis.b -> false -[RESULT] scopeAbis.a_base -> 1 \ No newline at end of file +[RESULT] b -> true \ No newline at end of file diff --git a/tests/test_scope/sub_sub_scope.catala.A.out b/tests/test_scope/sub_sub_scope.catala.A.out index a9618bb0..0f4b2ef8 100644 --- a/tests/test_scope/sub_sub_scope.catala.A.out +++ b/tests/test_scope/sub_sub_scope.catala.A.out @@ -1,2 +1,2 @@ -[RESULT] x -> 0 [RESULT] u -> true +[RESULT] x -> 0 diff --git a/tests/test_scope/sub_sub_scope.catala.B.out b/tests/test_scope/sub_sub_scope.catala.B.out index 733b0f30..17fc1eaa 100644 --- a/tests/test_scope/sub_sub_scope.catala.B.out +++ b/tests/test_scope/sub_sub_scope.catala.B.out @@ -1,19 +1,13 @@ -[ERROR] Default logic conflict, multiple justifications are true but are not related by a precedence -[ERROR] -[ERROR] The conflict concerns this variable y -[ERROR] --> test_scope/sub_sub_scope.catala -[ERROR] | -[ERROR] 10 | param y type int -[ERROR] | ^ -[ERROR] -[ERROR] This justification is true: +[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] +[ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/sub_sub_scope.catala -[ERROR] | -[ERROR] 23 | def y [ a.x = 1 ] := 1 -[ERROR] | ^^^^^^^ -[ERROR] -[ERROR] This justification is true: +[ERROR] | +[ERROR] 24 | def y [ a2.x = 1 ] := 1 +[ERROR] | ^ +[ERROR] +[ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/sub_sub_scope.catala -[ERROR] | -[ERROR] 24 | def y [ a.x + 1 = 2 ] := 1 -[ERROR] | ^^^^^^^^^^^ +[ERROR] | +[ERROR] 25 | def y [ a2.x + 1 = 2 ] := 1 +[ERROR] | ^ diff --git a/tests/test_scope/sub_sub_scope.catala.C.out b/tests/test_scope/sub_sub_scope.catala.C.out index 07582c1b..59553b02 100644 --- a/tests/test_scope/sub_sub_scope.catala.C.out +++ b/tests/test_scope/sub_sub_scope.catala.C.out @@ -1,4 +1 @@ -[RESULT] z -> 2 -[RESULT] a.x -> 2 -[RESULT] a.u -> true -[RESULT] b.y -> 3 \ No newline at end of file +[RESULT] z -> 2 \ No newline at end of file From 4709680557a9b4ef4eeb90431690a292e9dec1ec Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 12:15:54 +0100 Subject: [PATCH 032/142] Better cyclic dependencies error messages --- src/catala/desugared/dependency.ml | 29 +++++++++++++++++++------ src/catala/scope_language/dependency.ml | 21 +++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index 249ad953..de5ea02b 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -71,7 +71,7 @@ let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = if List.length sccs < ScopeDependencies.nb_vertex g then let scc = List.find (fun scc -> List.length scc > 1) sccs in Errors.raise_multispanned_error - (Format.asprintf "cyclic dependency detected between variables of scope %a !" + (Format.asprintf "Cyclic dependency detected between variables of scope %a !" Scopelang.Ast.ScopeName.format_t scope.scope_uid) (List.flatten (List.map @@ -93,8 +93,8 @@ let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = | Vertex.SubScope v -> Format.asprintf "%a" Scopelang.Ast.SubScopeName.format_t v in [ - (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); - ( Some ("used here in the definition of another cycle variable " ^ succ_str ^ ":"), + (Some ("Cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); + ( Some ("Used here in the definition of another cycle variable " ^ succ_str ^ ":"), edge_pos ); ]) scc)) @@ -130,10 +130,17 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = forbidden in Catala" Scopelang.Ast.ScopeVar.format_t defined) fv_def_pos - else ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.Var defined) + else + let edge = + ScopeDependencies.E.create (Vertex.Var used) fv_def_pos (Vertex.Var defined) + in + ScopeDependencies.add_edge_e g edge | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.Var used -> (* here we are defining the input of a subscope using a var of the scope *) - ScopeDependencies.add_edge g (Vertex.Var used) (Vertex.SubScope defined) + let edge = + ScopeDependencies.E.create (Vertex.Var used) fv_def_pos (Vertex.SubScope defined) + in + ScopeDependencies.add_edge_e g edge | Ast.ScopeDef.SubScopeVar (defined, _), Ast.ScopeDef.SubScopeVar (used, _) -> (* here we are defining the input of a scope with the output of another subscope *) if used = defined then @@ -144,10 +151,18 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = forbidden in Catala" Scopelang.Ast.SubScopeName.format_t defined) fv_def_pos - else ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.SubScope defined) + else + let edge = + ScopeDependencies.E.create (Vertex.SubScope used) fv_def_pos + (Vertex.SubScope defined) + in + ScopeDependencies.add_edge_e g edge | Ast.ScopeDef.Var defined, Ast.ScopeDef.SubScopeVar (used, _) -> (* finally we define a scope var with the output of a subscope *) - ScopeDependencies.add_edge g (Vertex.SubScope used) (Vertex.Var defined)) + let edge = + ScopeDependencies.E.create (Vertex.SubScope used) fv_def_pos (Vertex.Var defined) + in + ScopeDependencies.add_edge_e g edge) fv g) scope.scope_defs g in diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 90600188..ba598cb2 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -55,17 +55,22 @@ let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = (fun acc r -> match r with | Ast.Definition _ -> acc - | Ast.Call (subscope, _) -> + | Ast.Call (subscope, subindex) -> if subscope = scope_name then Errors.raise_spanned_error "The scope %a is calling into itself as a subscope, which is forbidden since \ Catala does not provide recursion" (Pos.get_position (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) - else Ast.ScopeNameSet.add subscope acc) - Ast.ScopeNameSet.empty scope.Ast.scope_decl_rules + else + Ast.ScopeMap.add subscope + (Pos.get_position (Ast.SubScopeName.get_info subindex)) + acc) + Ast.ScopeMap.empty scope.Ast.scope_decl_rules in - Ast.ScopeNameSet.fold - (fun subscope g -> Dependencies.add_edge g subscope scope_name) + Ast.ScopeMap.fold + (fun subscope pos g -> + let edge = Dependencies.E.create subscope pos scope_name in + Dependencies.add_edge_e g edge) subscopes g) prgm g @@ -74,7 +79,7 @@ let check_for_cycle (g : Dependencies.t) : unit = let sccs = SCC.scc_list g in if List.length sccs < Dependencies.nb_vertex g then let scc = List.find (fun scc -> List.length scc > 1) sccs in - Errors.raise_multispanned_error "cyclic dependency detected between scopes!" + Errors.raise_multispanned_error "Cyclic dependency detected between scopes!" (List.flatten (List.map (fun v -> @@ -85,8 +90,8 @@ let check_for_cycle (g : Dependencies.t) : unit = let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in let succ_str = Format.asprintf "%a" Ast.ScopeName.format_t succ in [ - (Some ("cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); - ( Some ("used here in the definition of another cycle variable " ^ succ_str ^ ":"), + (Some ("Cycle variable " ^ var_str ^ ", declared:"), Pos.get_position var_info); + ( Some ("Used here in the definition of another cycle variable " ^ succ_str ^ ":"), edge_pos ); ]) scc)) From 1030e4bc8df1efab3f6ced0fde8a1528da62777e Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 12:18:49 +0100 Subject: [PATCH 033/142] Better type printing --- src/catala/default_calculus/print.ml | 4 ++-- src/catala/default_calculus/typing.ml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index fadea637..3d581e8b 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -29,9 +29,9 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = | TInt -> Format.fprintf fmt "int" | TTuple ts -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ_with_parens t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a →@ %a" format_typ_with_parens t1 format_typ t2 let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index b33c507b..5fa36485 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -37,9 +37,9 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TAny -> Format.fprintf fmt "α" | TTuple ts -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") format_typ) + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a →@ %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) From 0443221e8bb91d946f22b1a15b1ce24564d96115 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 16:27:10 +0100 Subject: [PATCH 034/142] Fixed functions --- src/catala/catala_surface/desugaring.ml | 113 +++++++++++++------ src/catala/catala_surface/name_resolution.ml | 11 +- src/catala/default_calculus/print.ml | 3 +- src/catala/default_calculus/typing.ml | 4 +- src/catala/desugared/ast.ml | 13 ++- src/catala/desugared/desugared_to_scope.ml | 45 +++++--- src/catala/scope_language/print.ml | 81 +++++++++++++ src/catala/scope_language/scope_to_dcalc.ml | 1 + tests/test_func/func.catala | 4 +- 9 files changed, 206 insertions(+), 69 deletions(-) create mode 100644 src/catala/scope_language/print.ml diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 49a3bcc8..5f208b1d 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -14,6 +14,7 @@ module Pos = Utils.Pos module Errors = Utils.Errors +module Cli = Utils.Cli (** The optional argument subdef allows to choose between differents uids in case the expression is a redefinition of a subvariable *) @@ -37,22 +38,26 @@ let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Desugared.Ast.ScopeDef.t option) (ctxt : Name_resolution.context) - ((expr, pos) : Ast.expression Pos.marked) : Scopelang.Ast.expr Pos.marked = + ((expr, pos) : Ast.expression Pos.marked) : Scopelang.Ast.expr Pos.marked Bindlib.box = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in let rec_helper = translate_expr scope def_key ctxt in match expr with | IfThenElse (e_if, e_then, e_else) -> - (EIfThenElse (rec_helper e_if, rec_helper e_then, rec_helper e_else), pos) + Bindlib.box_apply3 + (fun e_if e_then e_else -> (Scopelang.Ast.EIfThenElse (e_if, e_then, e_else), pos)) + (rec_helper e_if) (rec_helper e_then) (rec_helper e_else) | Binop (op, e1, e2) -> let op_term = Pos.same_pos_as (Scopelang.Ast.EOp (Dcalc.Ast.Binop (translate_binop (Pos.unmark op)))) op in - (EApp (op_term, [ rec_helper e1; rec_helper e2 ]), pos) + Bindlib.box_apply2 + (fun e1 e2 -> (Scopelang.Ast.EApp (op_term, [ e1; e2 ]), pos)) + (rec_helper e1) (rec_helper e2) | Unop (op, e) -> let op_term = Pos.same_pos_as (Scopelang.Ast.EOp (Dcalc.Ast.Unop (translate_unop (Pos.unmark op)))) op in - (EApp (op_term, [ rec_helper e ]), pos) + Bindlib.box_apply (fun e -> (Scopelang.Ast.EApp (op_term, [ e ]), pos)) (rec_helper e) | Literal l -> let untyped_term = match l with @@ -61,7 +66,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) | _ -> Name_resolution.raise_unsupported_feature "literal" pos in - (untyped_term, pos) + Bindlib.box (untyped_term, pos) | Ident x -> ( (* first we check whether this is a local var, then we resort to scope-wide variables *) match def_key with @@ -70,14 +75,15 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) match Desugared.Ast.IdentMap.find_opt x def_ctxt.var_idmap with | None -> ( match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with - | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) + | Some uid -> Bindlib.box (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) | None -> Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" (x, pos) ) - | Some uid -> (Scopelang.Ast.EVar uid, pos) ) + | Some uid -> Bindlib.box_var uid + (* the whole box thing is to accomodate for this case *) ) | None -> ( match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with - | Some uid -> (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) + | Some uid -> Bindlib.box (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | Dotted (e, x) -> ( @@ -91,31 +97,41 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes in let subscope_var_uid = Name_resolution.get_var_uid subscope_real_uid ctxt x in - ( Scopelang.Ast.ELocation - (SubScopeVar (subscope_real_uid, (subscope_uid, pos), (subscope_var_uid, pos))), - pos ) + Bindlib.box + ( Scopelang.Ast.ELocation + (SubScopeVar (subscope_real_uid, (subscope_uid, pos), (subscope_var_uid, pos))), + pos ) | _ -> Name_resolution.raise_unsupported_feature "left hand side of a dotted expression should be an\n\n identifier" pos ) - | FunCall (f, arg) -> (EApp (rec_helper f, [ rec_helper arg ]), pos) + | FunCall (f, arg) -> + Bindlib.box_apply2 + (fun f arg -> (Scopelang.Ast.EApp (f, [ arg ]), pos)) + (rec_helper f) (rec_helper arg) | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos (* Translation from the parsed ast to the scope language *) -let merge_conditions (precond : Scopelang.Ast.expr Pos.marked option) - (cond : Scopelang.Ast.expr Pos.marked option) (default_pos : Pos.t) : - Scopelang.Ast.expr Pos.marked = +let merge_conditions (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) + (cond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (default_pos : Pos.t) : + Scopelang.Ast.expr Pos.marked Bindlib.box = match (precond, cond) with | Some precond, Some cond -> - let op_term = (Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.And), Pos.get_position precond) in - (Scopelang.Ast.EApp (op_term, [ precond; cond ]), Pos.get_position precond) + let op_term = + (Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.And), Pos.get_position (Bindlib.unbox precond)) + in + Bindlib.box_apply2 + (fun precond cond -> + (Scopelang.Ast.EApp (op_term, [ precond; cond ]), Pos.get_position precond)) + precond cond | Some cond, None | None, Some cond -> cond - | None, None -> (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) + | None, None -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t option) - (precond : Scopelang.Ast.expr Pos.marked option) (just : Ast.expression Pos.marked option) - (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = + (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) + (just : Ast.expression Pos.marked option) (cons : Ast.expression Pos.marked) : + Desugared.Ast.rule = let just = match just with | Some just -> Some (translate_expr scope (Some def_key) ctxt just) @@ -133,30 +149,55 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop | Dcalc.Ast.TArrow _, None -> Errors.raise_spanned_error "this definition has a function type but the parameter is missing" - (Pos.get_position cons) + (Pos.get_position (Bindlib.unbox cons)) | _, Some _ -> Errors.raise_spanned_error "this definition has a parameter but its type is not a function" - (Pos.get_position cons) + (Pos.get_position (Bindlib.unbox cons)) | _ -> None); parent_rule = None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); } +let add_var_to_def_idmap (ctxt : Name_resolution.context) (scope_uid : Scopelang.Ast.ScopeName.t) + (def_key : Desugared.Ast.ScopeDef.t) (name : string Pos.marked) (var : Scopelang.Ast.Var.t) : + Name_resolution.context = + { + ctxt with + scopes = + Scopelang.Ast.ScopeMap.update scope_uid + (fun scope_ctxt -> + match scope_ctxt with + | Some scope_ctxt -> + Some + { + scope_ctxt with + Name_resolution.definitions = + Desugared.Ast.ScopeDefMap.update def_key + (fun def_ctxt -> + match def_ctxt with + | None -> assert false (* should not happen *) + | Some (def_ctxt : Name_resolution.def_context) -> + Some + { + Name_resolution.var_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark name) var + def_ctxt.Name_resolution.var_idmap; + }) + scope_ctxt.Name_resolution.definitions; + } + | None -> assert false + (* should not happen *)) + ctxt.scopes; + } + (* Process a definition *) -let process_def (precond : Scopelang.Ast.expr Pos.marked option) +let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (def : Ast.definition) : Desugared.Ast.program = let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in - let param_uid (def_uid : Desugared.Ast.ScopeDef.t) : Scopelang.Ast.Var.t option = - match def.definition_parameter with - | None -> None - | Some param -> - let def_ctxt = Desugared.Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in - Some (Desugared.Ast.IdentMap.find (Pos.unmark param) def_ctxt.var_idmap) - in let def_key = match Pos.unmark def.definition_name with | [ x ] -> @@ -173,6 +214,14 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) Desugared.Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid) | _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos in + (* We add to the name resolution context the name of the parameter variable *) + let param_uid, new_ctxt = + match def.definition_parameter with + | None -> (None, ctxt) + | Some param -> + let param_var = Scopelang.Ast.Var.make param in + (Some param_var, add_var_to_def_idmap ctxt scope_uid def_key param param_var) + in let scope_updated = let x_def, x_type = match Desugared.Ast.ScopeDefMap.find_opt def_key scope.scope_defs with @@ -187,7 +236,7 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) in let x_def = Desugared.Ast.RuleMap.add rule_name - (process_default ctxt scope_uid def_key (param_uid def_key) precond def.definition_condition + (process_default new_ctxt scope_uid def_key param_uid precond def.definition_condition def.definition_expr) x_def in @@ -199,7 +248,7 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked option) Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm (** Process a rule from the surface language *) -let process_rule (precond : Scopelang.Ast.expr Pos.marked option) +let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (rule : Ast.rule) : Desugared.Ast.program = let consequence_expr = Ast.Literal (Ast.Bool (Pos.unmark rule.rule_consequence)) in diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 71dc0f86..5d22cebd 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -217,16 +217,7 @@ let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = | Ast.Definition def -> let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let def_uid = qident_to_scope_def ctxt scope_uid def.definition_name in - let def_ctxt = - { - var_idmap = - ( match def.definition_parameter with - | None -> Desugared.Ast.IdentMap.empty - | Some param -> - Desugared.Ast.IdentMap.singleton (Pos.unmark param) - (Scopelang.Ast.Var.make param) ); - } - in + let def_ctxt = { var_idmap = Desugared.Ast.IdentMap.empty } in let scope_ctxt = { scope_ctxt with diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 3d581e8b..4b925dd9 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -31,7 +31,8 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a →@ %a" format_typ_with_parens t1 format_typ t2 + | TArrow (t1, t2) -> + Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 5fa36485..7bac3753 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -37,9 +37,9 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TAny -> Format.fprintf fmt "α" | TTuple ts -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " * ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a →@ %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index ed361ccc..f091861d 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -53,16 +53,16 @@ module ScopeDefSet = Set.Make (ScopeDef) (* Scopes *) type rule = { - just : Scopelang.Ast.expr Pos.marked; - cons : Scopelang.Ast.expr Pos.marked; + just : Scopelang.Ast.expr Pos.marked Bindlib.box; + cons : Scopelang.Ast.expr Pos.marked Bindlib.box; parameter : (Scopelang.Ast.Var.t * Dcalc.Ast.typ Pos.marked) option; parent_rule : RuleName.t option; } let empty_rule (pos : Pos.t) (have_parameter : Dcalc.Ast.typ Pos.marked option) : rule = { - just = (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); - cons = (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); + just = Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); + cons = Bindlib.box (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); parameter = ( match have_parameter with | Some typ -> Some (Scopelang.Ast.Var.make ("dummy", pos), typ) @@ -117,6 +117,9 @@ let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t = in RuleMap.fold (fun _ rule acc -> - let locs = Scopelang.Ast.locations_used rule.just @ Scopelang.Ast.locations_used rule.cons in + let locs = + Scopelang.Ast.locations_used (Bindlib.unbox rule.just) + @ Scopelang.Ast.locations_used (Bindlib.unbox rule.cons) + in add_locs acc locs) def ScopeDefMap.empty diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 589a9e03..cb4c948d 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -14,6 +14,7 @@ module Pos = Utils.Pos module Errors = Utils.Errors +module Cli = Utils.Cli type rule_tree = Leaf of Ast.rule | Node of Ast.rule * rule_tree list @@ -46,31 +47,37 @@ let rec def_map_to_tree (def : Ast.rule Ast.RuleMap.t) : rule_tree = in Node (no_parent, tree_children) -let rec rule_tree_to_expr (is_func : Scopelang.Ast.Var.t option) (tree : rule_tree) : - Scopelang.Ast.expr Pos.marked = +let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t option) + (tree : rule_tree) : Scopelang.Ast.expr Pos.marked Bindlib.box = let rule, children = match tree with Leaf r -> (r, []) | Node (r, child) -> (r, child) in (* because each rule has its own variable parameter and we want to convert the whole rule tree into a function, we need to perform some alpha-renaming of all the expressions *) - let substitute_parameter (e : Scopelang.Ast.expr Pos.marked) : Scopelang.Ast.expr Pos.marked = + let substitute_parameter (e : Scopelang.Ast.expr Pos.marked Bindlib.box) : + Scopelang.Ast.expr Pos.marked Bindlib.box = match (is_func, rule.parameter) with | Some new_param, Some (old_param, _) -> - let binder = Bindlib.bind_var old_param (Bindlib.box e) in - Bindlib.subst (Bindlib.unbox binder) (Scopelang.Ast.EVar new_param, Pos.no_pos) + let binder = Bindlib.bind_var old_param e in + Bindlib.box_apply2 + (fun binder new_param -> Bindlib.subst binder new_param) + binder (Bindlib.box_var new_param) | None, None -> e | _ -> assert false (* should not happen *) in let just = substitute_parameter rule.Ast.just in let cons = substitute_parameter rule.Ast.cons in - let children = List.map (rule_tree_to_expr is_func) children in - let default = (Scopelang.Ast.EDefault (just, cons, children), Pos.no_pos) in + let children = Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false is_func) children) in + let default = + Bindlib.box_apply3 + (fun just cons children -> (Scopelang.Ast.EDefault (just, cons, children), Pos.no_pos)) + just cons children + in match (is_func, rule.parameter) with | None, None -> default | Some new_param, Some (_, typ) -> - Bindlib.unbox - (Scopelang.Ast.make_abs - (Array.of_list [ new_param ]) - (Bindlib.box default) Pos.no_pos [ typ ] Pos.no_pos) + if toplevel then + Scopelang.Ast.make_abs (Array.of_list [ new_param ]) default Pos.no_pos [ typ ] Pos.no_pos + else default | _ -> assert false (* should not happen *) @@ -97,7 +104,7 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked ( Some (Format.asprintf "The type of the parameter of this expression is %a" Dcalc.Print.format_typ typ), - Pos.get_position r.Ast.cons )) + Pos.get_position (Bindlib.unbox r.Ast.cons) )) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_typ n r)) def))) | None -> assert false (* should not happen *) else if all_rules_not_func then None @@ -105,10 +112,13 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked Errors.raise_multispanned_error "some definitions of the same variable are functions while others aren't" ( List.map - (fun (_, r) -> (Some "This definition is a function:", Pos.get_position r.Ast.cons)) + (fun (_, r) -> + (Some "This definition is a function:", Pos.get_position (Bindlib.unbox r.Ast.cons))) (Ast.RuleMap.bindings (Ast.RuleMap.filter is_func def)) @ List.map - (fun (_, r) -> (Some "This definition is not a function:", Pos.get_position r.Ast.cons)) + (fun (_, r) -> + ( Some "This definition is not a function:", + Pos.get_position (Bindlib.unbox r.Ast.cons) )) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_func n r)) def)) ) in let dummy_rule = Ast.empty_rule Pos.no_pos is_def_func in @@ -123,9 +133,10 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked def) in let def_tree = def_map_to_tree def in - rule_tree_to_expr - (Option.map (fun _ -> Scopelang.Ast.Var.make ("param", Pos.no_pos)) is_def_func) - def_tree + Bindlib.unbox + (rule_tree_to_expr ~toplevel:true + (Option.map (fun _ -> Scopelang.Ast.Var.make ("ρ", Pos.no_pos)) is_def_func) + def_tree) let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = let scope_dependencies = Dependency.build_scope_dependencies scope in diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml new file mode 100644 index 00000000..fdb6f221 --- /dev/null +++ b/src/catala/scope_language/print.ml @@ -0,0 +1,81 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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. *) + +module Pos = Utils.Pos +open Ast + +let needs_parens (e : expr Pos.marked) : bool = + match Pos.unmark e with EAbs _ -> true | _ -> false + +let format_var (fmt : Format.formatter) (v : Var.t) : unit = + Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v) + +let format_location (fmt : Format.formatter) (l : location) : unit = + match l with + | ScopeVar v -> Format.fprintf fmt "%a" ScopeVar.format_t (Pos.unmark v) + | SubScopeVar (_, subindex, subvar) -> + Format.fprintf fmt "%a.%a" SubScopeName.format_t (Pos.unmark subindex) ScopeVar.format_t + (Pos.unmark subvar) + +let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = + let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = + if needs_parens e then Format.fprintf fmt "(%a)" format_expr e + else Format.fprintf fmt "%a" format_expr e + in + match Pos.unmark e with + | ELocation l -> Format.fprintf fmt "%a" format_location l + | EVar v -> Format.fprintf fmt "%a" format_var v + | ELit l -> Format.fprintf fmt "%a" Dcalc.Print.format_lit (Pos.same_pos_as l e) + | EApp ((EAbs (_, binder, taus), _), args) -> + let xs, body = Bindlib.unmbind binder in + let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let xs_tau_arg = List.map2 (fun (x, tau) arg -> (x, tau, arg)) xs_tau args in + Format.fprintf fmt "@[%a%a@]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + (fun fmt (x, tau, arg) -> + Format.fprintf fmt "@[@[let@ %a@ :@ %a@ =@ %a@]@ in@\n@]" format_var x + Dcalc.Print.format_typ tau format_expr arg)) + xs_tau_arg format_expr body + | EAbs (_, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + Format.fprintf fmt "@[λ@ %a@ →@ %a@]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + (fun fmt (x, tau) -> + Format.fprintf fmt "@[(%a:@ %a)@]" format_var x Dcalc.Print.format_typ tau)) + xs_tau format_expr body + | EApp ((EOp (Binop op), _), [ arg1; arg2 ]) -> + Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 Dcalc.Print.format_binop + (op, Pos.no_pos) format_with_parens arg2 + | EApp ((EOp (Unop op), _), [ arg1 ]) -> + Format.fprintf fmt "@[%a@ %a@]" Dcalc.Print.format_unop (op, Pos.no_pos) format_with_parens + arg1 + | EApp (f, args) -> + Format.fprintf fmt "@[%a@ %a@]" format_expr f + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") format_with_parens) + args + | EIfThenElse (e1, e2, e3) -> + Format.fprintf fmt "if@ @[%a@]@ then@ @[%a@]@ else@ @[%a@]" format_expr + e1 format_expr e2 format_expr e3 + | EOp (Binop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_binop (op, Pos.no_pos) + | EOp (Unop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_unop (op, Pos.no_pos) + | EDefault (just, cons, subs) -> + if List.length subs = 0 then + Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons + else + Format.fprintf fmt "@[⟨%a ⊢ %a |@ %a⟩@]" format_expr just format_expr cons + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) + subs diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 4d605e27..87544987 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -56,6 +56,7 @@ let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked Bindlib.box = + (* Cli.debug_print (Format.asprintf "Translating: %a" Print.format_expr e); *) Bindlib.box_apply (fun (x : Dcalc.Ast.expr) -> Pos.same_pos_as x e) ( match Pos.unmark e with diff --git a/tests/test_func/func.catala b/tests/test_func/func.catala index c760f163..5903982b 100644 --- a/tests/test_func/func.catala +++ b/tests/test_func/func.catala @@ -7,8 +7,8 @@ new scope S: param b type bool scope S: - def f of x [ (x >= x) ] := x + x - def f of x [ not b ] := x * x + def f of x1 [ (x1 >= x1) ] := x1 + x1 + def f of x2 [ not b ] := x2 * x2 def b := false From ae1c2c6e02d9928f8af864c6cc83209f172b2e7d Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 17:21:37 +0100 Subject: [PATCH 035/142] Passing all tests! --- .github/workflows/build.yml | 4 ++++ tests/Makefile | 3 ++- tests/test_func/func.catala | 8 ++++++++ tests/test_func/func.catala.R.out | 1 + tests/test_func/func.catala.S.out | 13 +++++++++++++ 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 tests/test_func/func.catala.R.out create mode 100644 tests/test_func/func.catala.S.out diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 10e47e17..452e99ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -54,6 +54,10 @@ jobs: run: | eval $(opam env) make build + - name: Run tests + run: | + eval $(opam env) + make tests - name: Make examples run: | diff --git a/tests/Makefile b/tests/Makefile index bf22b58f..aba286bf 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -24,7 +24,8 @@ interpret_with_scope_and_compare =\ test_bool/test_bool.catala: $(call interpret_with_scope_and_compare,nv,TestBool) test_func/func.catala: - $(call interpret_with_scope,nv,S) + $(call interpret_with_scope_and_compare,nv,S) + $(call interpret_with_scope_and_compare,nv,R) test_scope/scope.catala: $(call interpret_with_scope_and_compare,nv,A) test_scope/sub_scope.catala: diff --git a/tests/test_func/func.catala b/tests/test_func/func.catala index 5903982b..0aab0c9e 100644 --- a/tests/test_func/func.catala +++ b/tests/test_func/func.catala @@ -6,6 +6,10 @@ new scope S: param x type int param b type bool +new scope R: + param s scope S + param r type int + scope S: def f of x1 [ (x1 >= x1) ] := x1 + x1 def f of x2 [ not b ] := x2 * x2 @@ -13,4 +17,8 @@ scope S: def b := false def x := f of 3 + +scope R: + def s.f of x := x + x * x + def r := s.f of 5 */ diff --git a/tests/test_func/func.catala.R.out b/tests/test_func/func.catala.R.out new file mode 100644 index 00000000..ad91a9a0 --- /dev/null +++ b/tests/test_func/func.catala.R.out @@ -0,0 +1 @@ +[RESULT] r -> 30 diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out new file mode 100644 index 00000000..7828d128 --- /dev/null +++ b/tests/test_func/func.catala.S.out @@ -0,0 +1,13 @@ +[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] +[ERROR] This value is available because the justification of its definition is true: +[ERROR] --> test_func/func.catala +[ERROR] | +[ERROR] 14 | def f of x1 [ (x1 >= x1) ] := x1 + x1 +[ERROR] | ^ +[ERROR] +[ERROR] This value is available because the justification of its definition is true: +[ERROR] --> test_func/func.catala +[ERROR] | +[ERROR] 15 | def f of x2 [ not b ] := x2 * x2 +[ERROR] | ^ From 180d56df13021a5161db27ad0aac4decd918d23b Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 18:36:38 +0100 Subject: [PATCH 036/142] Better error messages --- src/catala/catala_surface/desugaring.ml | 9 ++-- src/catala/default_calculus/ast.ml | 30 +++++++---- src/catala/default_calculus/interpreter.ml | 10 ++-- src/catala/default_calculus/print.ml | 2 +- src/catala/default_calculus/typing.ml | 4 +- src/catala/desugared/desugared_to_scope.ml | 3 +- src/catala/scope_language/ast.ml | 16 +++--- src/catala/scope_language/print.ml | 2 +- src/catala/scope_language/scope_to_dcalc.ml | 58 +++++++++++---------- tests/test_func/func.catala.S.out | 4 +- tests/test_scope/scope.catala.A.out | 4 +- tests/test_scope/sub_sub_scope.catala.B.out | 4 +- 12 files changed, 83 insertions(+), 63 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 5f208b1d..d17e7a9d 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -79,7 +79,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | None -> Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" (x, pos) ) - | Some uid -> Bindlib.box_var uid + | Some uid -> Scopelang.Ast.make_var (uid, pos) (* the whole box thing is to accomodate for this case *) ) | None -> ( match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with @@ -128,7 +128,7 @@ let merge_conditions (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option | None, None -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) - (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t option) + (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t Pos.marked option) (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (just : Ast.expression Pos.marked option) (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = @@ -145,7 +145,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop parameter = (let def_key_typ = Name_resolution.get_def_typ ctxt def_key in match (Pos.unmark def_key_typ, param_uid) with - | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (param_uid, t_in) + | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (Pos.unmark param_uid, t_in) | Dcalc.Ast.TArrow _, None -> Errors.raise_spanned_error "this definition has a function type but the parameter is missing" @@ -220,7 +220,8 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) | None -> (None, ctxt) | Some param -> let param_var = Scopelang.Ast.Var.make param in - (Some param_var, add_var_to_def_idmap ctxt scope_uid def_key param param_var) + ( Some (Pos.same_pos_as param_var param), + add_var_to_def_idmap ctxt scope_uid def_key param param_var ) in let scope_updated = let x_def, x_type = diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 7b11dfd9..78723864 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -30,30 +30,33 @@ type unop = Not | Minus type operator = Binop of binop | Unop of unop type expr = - | EVar of expr Pos.marked Bindlib.var + | EVar of expr Bindlib.var Pos.marked | ETuple of expr Pos.marked list | ETupleAccess of expr Pos.marked * int | ELit of lit - | EAbs of Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list + | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked module Var = struct - type t = expr Pos.marked Bindlib.var + type t = expr Bindlib.var - let make (s : string Pos.marked) = - Bindlib.new_var (fun x -> (EVar x, Pos.get_position s)) (Pos.unmark s) + let make (s : string Pos.marked) : t = + Bindlib.new_var + (fun (x : expr Bindlib.var) : expr -> EVar (x, Pos.get_position s)) + (Pos.unmark s) let compare x y = Bindlib.compare_vars x y end module VarMap = Map.Make (Var) -type vars = expr Pos.marked Bindlib.mvar +type vars = expr Bindlib.mvar -let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x +let make_var ((x, pos) : Var.t Pos.marked) : expr Pos.marked Bindlib.box = + Bindlib.box_apply (fun x -> (x, pos)) (Bindlib.box_var x) let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (taus : typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = @@ -63,11 +66,16 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box : expr Pos.marked Bindlib.box = Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) -let make_let_in (x : Var.t Pos.marked) (tau : typ Pos.marked) (e1 : expr Pos.marked Bindlib.box) - (e2 : expr Pos.marked Bindlib.box) (pos : Pos.t) : expr Pos.marked Bindlib.box = +let make_let_in (x : Var.t) (tau : typ Pos.marked) (e1 : expr Pos.marked Bindlib.box) + (e2 : expr Pos.marked Bindlib.box) : expr Pos.marked Bindlib.box = Bindlib.box_apply2 - (fun e u -> (EApp (e, u), pos)) - (make_abs (Array.of_list [ Pos.unmark x ]) e2 (Pos.get_position x) [ tau ] pos) + (fun e u -> (EApp (e, u), Pos.get_position (Bindlib.unbox e2))) + (make_abs + (Array.of_list [ x ]) + e2 + (Pos.get_position (Bindlib.unbox e2)) + [ tau ] + (Pos.get_position (Bindlib.unbox e2))) (Bindlib.box_list [ e1 ]) type binder = (expr, expr Pos.marked) Bindlib.binder diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index a3e4f9e5..2c559eb9 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -14,6 +14,7 @@ module Pos = Utils.Pos module Errors = Utils.Errors +module Cli = Utils.Cli module A = Ast let is_empty_error (e : A.expr Pos.marked) : bool = @@ -68,7 +69,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = match Pos.unmark e1 with | EAbs (_, binder, _) -> if Bindlib.mbinder_arity binder = List.length args then - evaluate_expr (Bindlib.msubst binder (Array.of_list args)) + evaluate_expr (Bindlib.msubst binder (Array.of_list (List.map Pos.unmark args))) else Errors.raise_spanned_error (Format.asprintf "wrong function call, expected %d arguments, got %d" @@ -116,6 +117,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = e) | e' -> e' ) | ELit (LBool false) -> ( + let subs_orig = subs in let subs = List.map evaluate_expr subs in let empty_count = List.length (List.filter is_empty_error subs) in match List.length subs - empty_count with @@ -131,12 +133,14 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = Pos.get_position e ); ] ) @ List.map - (fun sub -> + (fun (_, sub) -> ( Some "This value is available because the justification of its definition is \ true:", Pos.get_position sub )) - (List.filter (fun sub -> not (is_empty_error sub)) subs) ) ) + (List.filter + (fun (sub, _) -> not (is_empty_error sub)) + (List.map2 (fun x y -> (x, y)) subs subs_orig)) ) ) | _ -> Errors.raise_spanned_error "Default justification has not been reduced to a boolean at evaluation (should not \ diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 4b925dd9..ae24c768 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -72,7 +72,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = else Format.fprintf fmt "%a" format_expr e in match Pos.unmark e with - | EVar v -> Format.fprintf fmt "%a" format_var v + | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ETuple es -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") format_expr) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 7bac3753..359900a1 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -111,7 +111,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m let out = match Pos.unmark e with | EVar v -> ( - match A.VarMap.find_opt v env with + match A.VarMap.find_opt (Pos.unmark v) env with | Some t -> UnionFind.make t | None -> Errors.raise_spanned_error "Variable not found in the current context" @@ -189,7 +189,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (* Cli.debug_print (Format.asprintf "Down: %a | %a" Print.format_expr e format_typ tau); *) match Pos.unmark e with | EVar v -> ( - match A.VarMap.find_opt v env with + match A.VarMap.find_opt (Pos.unmark v) env with | Some tau' -> ignore (unify tau (UnionFind.make tau')) | None -> Errors.raise_spanned_error "Variable not found in the current context" diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index cb4c948d..0cb846da 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -69,7 +69,8 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti let children = Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false is_func) children) in let default = Bindlib.box_apply3 - (fun just cons children -> (Scopelang.Ast.EDefault (just, cons, children), Pos.no_pos)) + (fun just cons children -> + (Scopelang.Ast.EDefault (just, cons, children), Pos.get_position just)) just cons children in match (is_func, rule.parameter) with diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index acb2a72b..a6f000b9 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -36,10 +36,9 @@ type location = type expr = | ELocation of location - | EVar of expr Pos.marked Bindlib.var + | EVar of expr Bindlib.var Pos.marked | ELit of Dcalc.Ast.lit - | EAbs of - Pos.t * (expr Pos.marked, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ Pos.marked list + | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of Dcalc.Ast.operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list @@ -62,17 +61,20 @@ let rec locations_used (e : expr Pos.marked) : location Pos.marked list = subs module Var = struct - type t = expr Pos.marked Bindlib.var + type t = expr Bindlib.var let make (s : string Pos.marked) : t = - Bindlib.new_var (fun x -> (EVar x, Pos.get_position s)) (Pos.unmark s) + Bindlib.new_var + (fun (x : expr Bindlib.var) : expr -> EVar (x, Pos.get_position s)) + (Pos.unmark s) let compare x y = Bindlib.compare_vars x y end -type vars = expr Pos.marked Bindlib.mvar +type vars = expr Bindlib.mvar -let make_var (x : Var.t) : expr Pos.marked Bindlib.box = Bindlib.box_var x +let make_var ((x, pos) : Var.t Pos.marked) : expr Pos.marked Bindlib.box = + Bindlib.box_apply (fun v -> (v, pos)) (Bindlib.box_var x) let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) (taus : Dcalc.Ast.typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index fdb6f221..08d9d3d8 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -35,7 +35,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = in match Pos.unmark e with | ELocation l -> Format.fprintf fmt "%a" format_location l - | EVar v -> Format.fprintf fmt "%a" format_var v + | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ELit l -> Format.fprintf fmt "%a" Dcalc.Print.format_lit (Pos.same_pos_as l e) | EApp ((EAbs (_, binder, taus), _), args) -> let xs, body = Bindlib.unmbind binder in diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 87544987..d9276379 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -60,7 +60,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po Bindlib.box_apply (fun (x : Dcalc.Ast.expr) -> Pos.same_pos_as x e) ( match Pos.unmark e with - | EVar v -> Bindlib.box_apply Pos.unmark (Bindlib.box_var (Ast.VarMap.find v ctx.local_vars)) + | EVar v -> Bindlib.box_var (Ast.VarMap.find (Pos.unmark v) ctx.local_vars) | ELit l -> Bindlib.box (Dcalc.Ast.ELit l) | EApp (e1, args) -> Bindlib.box_apply2 @@ -69,7 +69,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (Bindlib.box_list (List.map (translate_expr ctx) args)) | EAbs (pos_binder, binder, typ) -> let xs, body = Bindlib.unmbind binder in - let new_xs = Array.map (fun x -> Dcalc.Ast.Var.make (Bindlib.name_of x, pos_binder)) xs in + let new_xs = Array.map (fun x -> Dcalc.Ast.Var.make (Bindlib.name_of x, Pos.no_pos)) xs in let both_xs = Array.map2 (fun x new_x -> (x, new_x)) xs new_xs in let body = translate_expr @@ -90,15 +90,13 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (translate_expr ctx just) (translate_expr ctx cons) (Bindlib.box_list (List.map (translate_expr ctx) subs)) | ELocation (ScopeVar a) -> - Bindlib.box_apply Pos.unmark - (Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars))) + Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars)) | ELocation (SubScopeVar (_, s, a)) -> ( try - Bindlib.box_apply Pos.unmark - (Bindlib.box_var - (fst - (Ast.ScopeVarMap.find (Pos.unmark a) - (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars)))) + Bindlib.box_var + (fst + (Ast.ScopeVarMap.find (Pos.unmark a) + (Ast.SubScopeMap.find (Pos.unmark s) ctx.subscope_vars))) with Not_found -> Errors.raise_spanned_error (Format.asprintf @@ -127,11 +125,9 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let new_e = translate_expr ctx e in - let a_expr = Dcalc.Ast.make_var a_var in + let a_expr = Dcalc.Ast.make_var (a_var, var_def_pos) in let merged_expr = merge_defaults a_expr new_e in - let next_e = - Dcalc.Ast.make_let_in (a_var, var_def_pos) tau merged_expr next_e (Pos.get_position a) - in + let next_e = Dcalc.Ast.make_let_in a_var tau merged_expr next_e in (next_e, new_ctx) | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> let a_name = @@ -139,7 +135,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos (fun str -> str ^ "." ^ Pos.unmark (Ast.ScopeVar.get_info (Pos.unmark subs_var))) (Ast.SubScopeName.get_info (Pos.unmark subs_index)) in - let a_var = Dcalc.Ast.Var.make a_name in + let a_var = (Dcalc.Ast.Var.make a_name, var_def_pos) in let new_ctx = { ctx with @@ -148,16 +144,21 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos (fun map -> match map with | Some map -> - Some (Ast.ScopeVarMap.add (Pos.unmark subs_var) (a_var, Pos.unmark tau) map) + Some + (Ast.ScopeVarMap.add (Pos.unmark subs_var) + (Pos.unmark a_var, Pos.unmark tau) + map) | None -> - Some (Ast.ScopeVarMap.singleton (Pos.unmark subs_var) (a_var, Pos.unmark tau))) + Some + (Ast.ScopeVarMap.singleton (Pos.unmark subs_var) + (Pos.unmark a_var, Pos.unmark tau))) ctx.subscope_vars; } in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let intermediate_e = Dcalc.Ast.make_abs - (Array.of_list [ a_var ]) + (Array.of_list [ Pos.unmark a_var ]) next_e var_def_pos [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] (Pos.get_position e) @@ -189,7 +190,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos Bindlib.box Dcalc.Interpreter.empty_thunked_term else let a_var, _ = Ast.ScopeVarMap.find subvar subscope_vars_defined in - Bindlib.box_var a_var) + Dcalc.Ast.make_var (a_var, Pos.get_position (Ast.SubScopeName.get_info subindex))) all_subscope_vars in let all_subscope_vars_dcalc = @@ -218,7 +219,9 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos let call_expr = Bindlib.box_apply2 (fun e u -> (Dcalc.Ast.EApp (e, u), Pos.no_pos)) - (Bindlib.box_var scope_dcalc_var) (Bindlib.box_list subscope_args) + (Dcalc.Ast.make_var + (scope_dcalc_var, Pos.get_position (Ast.SubScopeName.get_info subindex))) + (Bindlib.box_list subscope_args) in let result_tuple_var = Dcalc.Ast.Var.make ("result", Pos.no_pos) in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in @@ -228,17 +231,16 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos let result_access = Bindlib.box_apply (fun r -> (Dcalc.Ast.ETupleAccess (r, i), pos_sigma)) - (Bindlib.box_var result_tuple_var) + (Dcalc.Ast.make_var (result_tuple_var, pos_sigma)) in - ( Dcalc.Ast.make_let_in (dvar, pos_sigma) (tau, pos_sigma) result_access acc pos_sigma, - i - 1 )) + (Dcalc.Ast.make_let_in dvar (tau, pos_sigma) result_access acc, i - 1)) all_subscope_vars_dcalc (next_e, List.length all_subscope_vars_dcalc - 1) in - ( Dcalc.Ast.make_let_in (result_tuple_var, pos_sigma) + ( Dcalc.Ast.make_let_in result_tuple_var ( Dcalc.Ast.TTuple (List.map (fun (_, tau, _) -> (tau, pos_sigma)) all_subscope_vars_dcalc), pos_sigma ) - call_expr results_bindings pos_sigma, + call_expr results_bindings, new_ctx ) and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : @@ -250,7 +252,9 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : Bindlib.box_apply (fun args -> (Dcalc.Ast.ETuple args, pos_sigma)) (Bindlib.box_list - (List.map (fun (_, (dcalc_var, _)) -> Bindlib.box_var dcalc_var) scope_variables)) + (List.map + (fun (_, (dcalc_var, _)) -> Dcalc.Ast.make_var (dcalc_var, pos_sigma)) + scope_variables)) in (return_exp, ctx) | hd :: tl -> translate_rule ctx hd tl pos_sigma @@ -302,7 +306,7 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName in (* the final expression on which we build on is the variable of the top-level scope that we are returning *) - let acc = Bindlib.box_var (snd (Ast.ScopeMap.find top_level_scope_name sctx)) in + let acc = Dcalc.Ast.make_var (snd (Ast.ScopeMap.find top_level_scope_name sctx), Pos.no_pos) in (* the resulting expression is the list of definitions of all the scopes, ending with the top-level scope. *) Bindlib.unbox @@ -314,7 +318,7 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let scope_expr = translate_scope_decl sctx scope in let scope_sig, dvar = Ast.ScopeMap.find scope_name sctx in let scope_typ = build_scope_typ_from_sig scope_sig pos_scope in - Dcalc.Ast.make_let_in (dvar, pos_scope) scope_typ scope_expr acc pos_scope) + Dcalc.Ast.make_let_in dvar scope_typ scope_expr acc) scope_ordering acc in acc) diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out index 7828d128..ff08bb03 100644 --- a/tests/test_func/func.catala.S.out +++ b/tests/test_func/func.catala.S.out @@ -4,10 +4,10 @@ [ERROR] --> test_func/func.catala [ERROR] | [ERROR] 14 | def f of x1 [ (x1 >= x1) ] := x1 + x1 -[ERROR] | ^ +[ERROR] | ^^^^^^^^ [ERROR] [ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_func/func.catala [ERROR] | [ERROR] 15 | def f of x2 [ not b ] := x2 * x2 -[ERROR] | ^ +[ERROR] | ^^^^^ diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index b7a8f8e3..d9e3a10e 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -4,10 +4,10 @@ [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 13 | def b [ not c ] := 1337 -[ERROR] | ^^^^ +[ERROR] | ^^^^^ [ERROR] [ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 14 | def b [ not c ] := 0 -[ERROR] | ^ +[ERROR] | ^^^^^ diff --git a/tests/test_scope/sub_sub_scope.catala.B.out b/tests/test_scope/sub_sub_scope.catala.B.out index 17fc1eaa..3b556d9d 100644 --- a/tests/test_scope/sub_sub_scope.catala.B.out +++ b/tests/test_scope/sub_sub_scope.catala.B.out @@ -4,10 +4,10 @@ [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | [ERROR] 24 | def y [ a2.x = 1 ] := 1 -[ERROR] | ^ +[ERROR] | ^^^^^^^^ [ERROR] [ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | [ERROR] 25 | def y [ a2.x + 1 = 2 ] := 1 -[ERROR] | ^ +[ERROR] | ^^^^^^^^^^^^ From 80ef3211230072e4f90c2b23d9d7100557287473 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 18:40:19 +0100 Subject: [PATCH 037/142] Better func test --- src/catala/default_calculus/interpreter.ml | 4 +--- tests/test_func/func.catala | 12 +++++------- tests/test_func/func.catala.S.out | 8 ++++---- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 2c559eb9..fdec4bb7 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -134,9 +134,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = ] ) @ List.map (fun (_, sub) -> - ( Some - "This value is available because the justification of its definition is \ - true:", + ( Some "This value is available because this justification is true:", Pos.get_position sub )) (List.filter (fun (sub, _) -> not (is_empty_error sub)) diff --git a/tests/test_func/func.catala b/tests/test_func/func.catala index 0aab0c9e..979f2e83 100644 --- a/tests/test_func/func.catala +++ b/tests/test_func/func.catala @@ -3,22 +3,20 @@ /* new scope S: param f type int fun of int - param x type int param b type bool + param out type int new scope R: param s scope S param r type int scope S: - def f of x1 [ (x1 >= x1) ] := x1 + x1 - def f of x2 [ not b ] := x2 * x2 - + def f of x [ (x >= x) ] := x + x + def f of x [ not b ] := x * x def b := false - - def x := f of 3 + def out := f of 5 scope R: def s.f of x := x + x * x - def r := s.f of 5 + def r := s.out */ diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out index ff08bb03..f78d0c87 100644 --- a/tests/test_func/func.catala.S.out +++ b/tests/test_func/func.catala.S.out @@ -3,11 +3,11 @@ [ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_func/func.catala [ERROR] | -[ERROR] 14 | def f of x1 [ (x1 >= x1) ] := x1 + x1 -[ERROR] | ^^^^^^^^ +[ERROR] 14 | def f of x [ (x >= x) ] := x + x +[ERROR] | ^^^^^^ [ERROR] [ERROR] This value is available because the justification of its definition is true: [ERROR] --> test_func/func.catala [ERROR] | -[ERROR] 15 | def f of x2 [ not b ] := x2 * x2 -[ERROR] | ^^^^^ +[ERROR] 15 | def f of x [ not b ] := x * x +[ERROR] | ^^^^^ From 94f47b3ac49bcdceac4fee80e759a3d774b46722 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 19:04:22 +0100 Subject: [PATCH 038/142] Changed error message --- tests/test_scope/scope.catala.A.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index d9e3a10e..a31b9d2f 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -1,12 +1,12 @@ [ERROR] There is a conflict between multiple rules for assigning the same variable. [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This value is available because this justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 13 | def b [ not c ] := 1337 [ERROR] | ^^^^^ [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This value is available because this justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 14 | def b [ not c ] := 0 From 4599403d22105be89ce63c2b36a4b786f010f9e4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 19:04:57 +0100 Subject: [PATCH 039/142] Changed error message --- src/catala/default_calculus/interpreter.ml | 4 +--- tests/test_scope/scope.catala.A.out | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index fdec4bb7..8fe7cfd8 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -133,9 +133,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = Pos.get_position e ); ] ) @ List.map - (fun (_, sub) -> - ( Some "This value is available because this justification is true:", - Pos.get_position sub )) + (fun (_, sub) -> (Some "This justification is true:", Pos.get_position sub)) (List.filter (fun (sub, _) -> not (is_empty_error sub)) (List.map2 (fun x y -> (x, y)) subs subs_orig)) ) ) diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index a31b9d2f..d2c46188 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -1,12 +1,12 @@ [ERROR] There is a conflict between multiple rules for assigning the same variable. [ERROR] -[ERROR] This value is available because this justification is true: +[ERROR] This justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 13 | def b [ not c ] := 1337 [ERROR] | ^^^^^ [ERROR] -[ERROR] This value is available because this justification is true: +[ERROR] This justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | [ERROR] 14 | def b [ not c ] := 0 From 3d48effb170df23f3fd748865031769c32ed71c2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 27 Nov 2020 19:09:16 +0100 Subject: [PATCH 040/142] Fix all tests --- tests/test_func/func.catala.S.out | 4 ++-- tests/test_scope/sub_sub_scope.catala.B.out | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out index f78d0c87..e21ec185 100644 --- a/tests/test_func/func.catala.S.out +++ b/tests/test_func/func.catala.S.out @@ -1,12 +1,12 @@ [ERROR] There is a conflict between multiple rules for assigning the same variable. [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This justification is true: [ERROR] --> test_func/func.catala [ERROR] | [ERROR] 14 | def f of x [ (x >= x) ] := x + x [ERROR] | ^^^^^^ [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This justification is true: [ERROR] --> test_func/func.catala [ERROR] | [ERROR] 15 | def f of x [ not b ] := x * x diff --git a/tests/test_scope/sub_sub_scope.catala.B.out b/tests/test_scope/sub_sub_scope.catala.B.out index 3b556d9d..0002ddb0 100644 --- a/tests/test_scope/sub_sub_scope.catala.B.out +++ b/tests/test_scope/sub_sub_scope.catala.B.out @@ -1,12 +1,12 @@ [ERROR] There is a conflict between multiple rules for assigning the same variable. [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This justification is true: [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | [ERROR] 24 | def y [ a2.x = 1 ] := 1 [ERROR] | ^^^^^^^^ [ERROR] -[ERROR] This value is available because the justification of its definition is true: +[ERROR] This justification is true: [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | [ERROR] 25 | def y [ a2.x + 1 = 2 ] := 1 From 00505a9da763959183066afa3738bd845a3b4aeb Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 30 Nov 2020 10:55:27 +0100 Subject: [PATCH 041/142] Fixed newline problem! --- .../securite_sociale_D.catala_fr | 97 +++- .../securite_sociale_L.catala_fr | 113 ++++- .../securite_sociale_R.catala_fr | 65 ++- ...Section_I_Dispositions_generales.catala_fr | 15 +- examples/tutorial/tutorial_en.catala_en | 109 ++++- examples/us_tax_code/section_1015.catala_en | 86 +++- examples/us_tax_code/section_121.catala_en | 62 ++- examples/us_tax_code/section_132.catala_en | 34 +- src/catala/catala_surface/lexer.ml | 5 +- src/catala/catala_surface/lexer_en.ml | 5 +- src/catala/catala_surface/lexer_fr.ml | 5 +- src/catala/catala_surface/parser.messages | 440 +++++++++--------- src/catala/catala_surface/parser.mly | 20 +- src/catala/catala_surface/parser_errors.ml | 264 +++++------ src/catala/literate_programming/html.ml | 14 +- src/catala/utils/pos.ml | 8 +- 16 files changed, 840 insertions(+), 502 deletions(-) diff --git a/examples/allocations_familiales/securite_sociale_D.catala_fr b/examples/allocations_familiales/securite_sociale_D.catala_fr index 4cb3ffb9..fb260fe0 100644 --- a/examples/allocations_familiales/securite_sociale_D.catala_fr +++ b/examples/allocations_familiales/securite_sociale_D.catala_fr @@ -8,7 +8,9 @@ @@Chapitre 1er : Allocations familiales@@++++ @Article D521-1|LEGIARTI000030680318@ -I.-Pour l'application de l'article L. 521-1 , le montant des allocations familiales et de la majoration pour âge prévue à l'article L. 521-3 est défini selon le barème suivant : +I.-Pour l'application de l'article L. 521-1 , le montant des allocations +familiales et de la majoration pour âge prévue à l'article L. 521-3 +est défini selon le barème suivant : /* # Composantes des allocations familiales champ d'application CalculAllocationsFamiliales : @@ -18,7 +20,10 @@ champ d'application CalculAllocationsFamiliales : allocations_familiales.montant_deuxieme_enfant + allocations_familiales.montant_troisième_enfant_et_plus */ -1° Lorsque le ménage ou la personne a disposé d'un montant de ressources inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux servant au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : +1° Lorsque le ménage ou la personne a disposé d'un montant de ressources +inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux +servant au calcul des allocations familiales sont fixés, en pourcentage +de la base mensuelle prévue à l'article L. 551-1, à : a) 32 % pour le deuxième enfant à charge ; /* champ d'application CalculAllocationsFamiliales : @@ -42,7 +47,8 @@ champ d'application CalculAllocationsFamiliales : (nombre de ménage.enfants) - 2 ) sinon 0 € */ -La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des prestations familiales ; +La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des +prestations familiales ; /* champ d'application CalculAllocationsFamiliales : définition @@ -52,7 +58,11 @@ champ d'application CalculAllocationsFamiliales : conséquence égal à prestations_familiales.base_mensuelle * 16 % */ -2° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal à celui défini au II du même article, les taux servant au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : +2° Lorsque le ménage ou la personne a disposé d'un montant de ressources +supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal +à celui défini au II du même article, les taux servant au calcul des +allocations familiales sont fixés, en pourcentage de la base mensuelle +prévue à l'article L. 551-1, à : a) 16 % pour le deuxième enfant à charge ; /* champ d'application CalculAllocationsFamiliales : @@ -77,7 +87,8 @@ champ d'application CalculAllocationsFamiliales : (nombre de ménage.enfants) - 2 ) sinon 0 € */ -La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des prestations familiales ; +La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des +prestations familiales ; /* champ d'application CalculAllocationsFamiliales : définition @@ -89,7 +100,10 @@ champ d'application CalculAllocationsFamiliales : prestations_familiales.base_mensuelle * 8 % */ -3° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au II de l'article D. 521-3, les taux servant au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : +3° Lorsque le ménage ou la personne a disposé d'un montant de ressources +supérieur au plafond défini au II de l'article D. 521-3, les taux servant +au calcul des allocations familiales sont fixés, en pourcentage de la base +mensuelle prévue à l'article L. 551-1, à : a) 8 % pour le deuxième enfant à charge ; /* champ d'application CalculAllocationsFamiliales : @@ -112,7 +126,8 @@ champ d'application CalculAllocationsFamiliales : (nombre de ménage.enfants) - 2 ) sinon 0 € */ -La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des prestations familiales. +La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des +prestations familiales. /* champ d'application CalculAllocationsFamiliales : définition @@ -123,9 +138,17 @@ champ d'application CalculAllocationsFamiliales : prestations_familiales.base_mensuelle * 4 % */ -II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel des allocations familiales et, le cas échéant, de la majoration pour âge est majoré d'un complément dégressif, lorsque les ressources annuelles du ménage ou de la personne dépassent l'un des plafonds défini au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois le montant mensuel des allocations familiales augmenté, le cas échéant, de la ou des majorations pour âge. +II.-En application du sixième alinéa de l'article L. 521-1, le montant +mensuel des allocations familiales et, le cas échéant, de la majoration +pour âge est majoré d'un complément dégressif, lorsque les ressources +annuelles du ménage ou de la personne dépassent l'un des plafonds défini +au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois +le montant mensuel des allocations familiales augmenté, le cas échéant, +de la ou des majorations pour âge. -Ce complément dégressif est égal, pour chaque mois, au douzième de la différence entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. +Ce complément dégressif est égal, pour chaque mois, au douzième de la +différence entre, d'une part, ce plafond de ressources majoré de la somme +définie à l'alinéa précédent et, d'autre part, le montant des ressources. /* champ d'application CalculAllocationsFamiliales : définition complément_dégressif.dépassement de allocation @@ -166,9 +189,13 @@ champ d'application CalculAllocationsFamiliales : */ @Article D521-2|LEGIARTI000030680324@ -I.-Le montant mensuel de l'allocation forfaitaire prévue au deuxième alinéa de l'article L. 521-1 est défini selon le barème suivant : +I.-Le montant mensuel de l'allocation forfaitaire prévue au deuxième alinéa de +l'article L. 521-1 est défini selon le barème suivant : -1° Lorsque le ménage ou la personne a disposé d'un montant de ressources inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle de calcul des allocations familiales par enfant ; +1° Lorsque le ménage ou la personne a disposé d'un montant de ressources +inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant +mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle +de calcul des allocations familiales par enfant ; /* champ d'application CalculAllocationsFamiliales : définition allocation_forfaitaire.montant_versé sous condition @@ -179,7 +206,11 @@ champ d'application CalculAllocationsFamiliales : allocation_forfaitaire.droits_ouverts de enfant */ -2° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal à celui défini au II du même article, le montant mensuel de l'allocation forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations familiales par enfant ; +2° Lorsque le ménage ou la personne a disposé d'un montant de ressources +supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal +à celui défini au II du même article, le montant mensuel de l'allocation +forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations +familiales par enfant ; /* champ d'application CalculAllocationsFamiliales : définition allocation_forfaitaire.montant_versé sous condition @@ -191,7 +222,10 @@ champ d'application CalculAllocationsFamiliales : allocation_forfaitaire.droits_ouvert de enfant */ -3° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul des allocations familiales par enfant. +3° Lorsque le ménage ou la personne a disposé d'un montant de ressources +supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel +de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul +des allocations familiales par enfant. /* champ d'application CalculAllocationsFamiliales : définition allocation_forfaitaire.montant_versé sous condition @@ -202,8 +236,14 @@ champ d'application CalculAllocationsFamiliales : allocation_forfaitaire.droits_ouvert de enfant */ -II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel de l'allocation forfaitaire est majoré d'un complément dégressif lorsque les ressources annuelles du ménage ou de la personne dépassent l'un des plafonds défini au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois le montant mensuel de l'allocation forfaitaire auquel l'enfant ouvre droit. -Ce complément dégressif est égal, pour chaque mois, au douzième de la différence entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. +II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel +de l'allocation forfaitaire est majoré d'un complément dégressif lorsque les +ressources annuelles du ménage ou de la personne dépassent l'un des plafonds +défini au I ou au II de l'article D. 521-3 d'une somme inférieure à douze fois +le montant mensuel de l'allocation forfaitaire auquel l'enfant ouvre droit. +Ce complément dégressif est égal, pour chaque mois, au douzième de la différence +entre, d'une part, ce plafond de ressources majoré de la somme définie à +l'alinéa précédent et, d'autre part, le montant des ressources. /* champ d'application CalculAllocationsFamiliales : définition @@ -216,7 +256,8 @@ champ d'application CalculAllocationsFamiliales : de allocation_forfaitaire.montant_versé) / 12 */ -III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de l'article L. 521-1 est fixé à trois. +III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de +l'article L. 521-1 est fixé à trois. /* champ d'application CalculAllocationsFamiliales : définition l521_1.nombre_minimum_enfants égal à 3 @@ -224,21 +265,27 @@ champ d'application CalculAllocationsFamiliales : @Article D521-3|LEGIARTI000030678079@ -I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à 55 950 euros. Il est majoré de 5 595 euros par enfant à charge. +I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à +55 950 euros. Il est majoré de 5 595 euros par enfant à charge. /* champ d'application CalculAllocationsFamiliales : définition d521_3.plafond_I égal à 55 950 € + 5 595 € * nombre de ménage.enfants */ -II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à 78 300 euros. Il est majoré de 5 595 euros par enfant à charge. +II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à +78 300 euros. Il est majoré de 5 595 euros par enfant à charge. /* champ d'application CalculAllocationsFamiliales : définition d521_3.plafond_II égal à 78 300 € + 5 595 € * nombre de ménage.enfants */ -III.-Les montants des plafonds et de leur majoration respective fixés au présent article sont revalorisés au 1er janvier de chaque année, conformément à l'évolution en moyenne annuelle des prix à la consommation hors tabac de l'année civile de référence, par arrêté des ministres chargés de la sécurité sociale, du budget et de l'agriculture. +III.-Les montants des plafonds et de leur majoration respective fixés au présent +article sont revalorisés au 1er janvier de chaque année, conformément à +l'évolution en moyenne annuelle des prix à la consommation hors tabac de +l'année civile de référence, par arrêté des ministres chargés de la sécurité +sociale, du budget et de l'agriculture. @@Livre 7 : Régimes divers - Dispositions diverses@@++ @@ -247,13 +294,17 @@ III.-Les montants des plafonds et de leur majoration respective fixés au prése @@Chapitre 5 : Prestations familiales et prestations assimilées@@++++ @Article D755-5|LEGIARTI000006738575@ -I. - Les taux servant au calcul des allocations familiales et de la majoration prévue à l'article L. 755-11 sont identiques à ceux mentionnés à l'article D. 521-1. +I. - Les taux servant au calcul des allocations familiales et de la majoration +prévue à l'article L. 755-11 sont identiques à ceux mentionnés à l'article +D. 521-1. /* # Pas de changement à déclarer */ -II. - En application de l'article L. 755-11, 2e alinéa, le taux servant au calcul des allocations familiales servies pour un seul enfant à charge est fixé à 5,88 p. 100 de la base mensuelle prévue à l'article L. 755-3. +II. - En application de l'article L. 755-11, 2e alinéa, le taux servant au +calcul des allocations familiales servies pour un seul enfant à charge est +fixé à 5,88 p. 100 de la base mensuelle prévue à l'article L. 755-3. /* # Composantes des allocations familiales @@ -276,7 +327,9 @@ champ d'application CalculAllocationsFamiliales : # est basé sur les plafonds du taux de base qui ne s'appliquent pas ici, # donc il serait logique que le plafond ne s'applique pas. */ -La majoration des allocations familiales pour un seul enfant à charge est fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à partir de onze ans et à 5,67 p. 100 à partir de seize ans. +La majoration des allocations familiales pour un seul enfant à charge est +fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à +partir de onze ans et à 5,67 p. 100 à partir de seize ans. /* champ d'application CalculAllocationsFamiliales : définition l521_3.âge_limite_alinéa_1 de enfant diff --git a/examples/allocations_familiales/securite_sociale_L.catala_fr b/examples/allocations_familiales/securite_sociale_L.catala_fr index b9bf985f..eb3194c4 100644 --- a/examples/allocations_familiales/securite_sociale_L.catala_fr +++ b/examples/allocations_familiales/securite_sociale_L.catala_fr @@ -11,14 +11,23 @@ @Article L511-1|LEGIARTI000038834530@ Les prestations familiales comprennent : + 1°) la prestation d'accueil du jeune enfant ; + 2°) les allocations familiales ; + 3°) le complément familial ; + 4°) L'allocation de logement régie par les dispositions du livre VIII du code de la construction et de l'habitation ; + 5°) l'allocation d'éducation de l'enfant handicapé ; + 6°) l'allocation de soutien familial ; + 7°) l'allocation de rentrée scolaire ; + 8°) (Abrogé) ; + 9°) l'allocation journalière de présence parentale. /* # Voir métadonnnée L511_1.prestation_courante @@ -27,7 +36,8 @@ Les prestations familiales comprennent : @@Chapitre 2 : Champ d'application@@++++ @Article L512-3|LEGIARTI000038834523@ -Sous réserve des règles particulières à chaque prestation, ouvre droit aux prestations familiales : +Sous réserve des règles particulières à chaque prestation, +ouvre droit aux prestations familiales : /* champ d'application CalculPrestationsFamiliales : # On suppose dans le programme que tous les enfants déclarés dans @@ -45,7 +55,8 @@ champ d'application CalculPrestationsFamiliales : conséquence rempli */ -2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite, tout enfant dont la rémunération éventuelle n'excède pas un plafond. +2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite, +tout enfant dont la rémunération éventuelle n'excède pas un plafond. /* champ d'application CalculPrestationsFamiliales : # On définit les conditions hors âge d'abord car elles @@ -66,7 +77,9 @@ champ d'application CalculPrestationsFamiliales : conséquence rempli */ -Toutefois, pour l'attribution du complément familial et de l'allocation de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite peut être différent de celui mentionné au 2° du présent article. +Toutefois, pour l'attribution du complément familial et de l'allocation +de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite +peut être différent de celui mentionné au 2° du présent article. /* champ d'application CalculPrestationsFamiliales : définition l512_3.âge_limite_alinéa_2 sous condition @@ -99,7 +112,13 @@ champ d'application CalculAllocationsFamiliales : définition l511_1.prestation_courante égal à AllocationFamiliale */ -Une allocation forfaitaire par enfant d'un montant fixé par décret est versée pendant un an à la personne ou au ménage qui assume la charge d'un nombre minimum d'enfants également fixé par décret lorsque l'un ou plusieurs des enfants qui ouvraient droit aux allocations familiales atteignent l'âge limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée à la condition que le ou les enfants répondent aux conditions autres que celles de l'âge pour l'ouverture du droit aux allocations familiales. +Une allocation forfaitaire par enfant d'un montant fixé par décret est versée +pendant un an à la personne ou au ménage qui assume la charge d'un nombre +minimum d'enfants également fixé par décret lorsque l'un ou plusieurs des +enfants qui ouvraient droit aux allocations familiales atteignent l'âge +limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée +à la condition que le ou les enfants répondent aux conditions autres que +celles de l'âge pour l'ouverture du droit aux allocations familiales. /* champ d'application CalculAllocationsFamiliales : assertion fixé allocation_forfaitaire.montant_versé par décret @@ -121,7 +140,10 @@ champ d'application CalculAllocationsFamiliales : conséquence rempli */ -Le montant des allocations mentionnées aux deux premiers alinéas du présent article, ainsi que celui des majorations mentionnées à l'article L. 521-3 varient en fonction des ressources du ménage ou de la personne qui a la charge des enfants, selon un barème défini par décret. +Le montant des allocations mentionnées aux deux premiers alinéas du présent +article, ainsi que celui des majorations mentionnées à l'article L. 521-3 +varient en fonction des ressources du ménage ou de la personne qui a la charge +des enfants, selon un barème défini par décret. /* champ d'application CalculAllocationsFamiliales : assertion fixé allocations_familiales.montant_versé par décret @@ -132,14 +154,17 @@ champ d'application CalculAllocationsFamiliales : l521_1.ressources_ménage */ -Le montant des allocations familiales varie en fonction du nombre d'enfants à charge. +Le montant des allocations familiales varie en fonction du nombre d'enfants +à charge. /* champ d'application CalculAllocationsFamiliales : assertion varie allocations_familiales.montant_versé avec nombre de ménage.enfants */ -Les niveaux des plafonds de ressources, qui varient en fonction du nombre d'enfants à charge, sont révisés conformément à l'évolution annuelle de l'indice des prix à la consommation, hors tabac. +Les niveaux des plafonds de ressources, qui varient en fonction du nombre +d'enfants à charge, sont révisés conformément à l'évolution annuelle de +l'indice des prix à la consommation, hors tabac. /* # Pour formaliser l'évolution des prix, il faudrait recopier ici # tous les décrets d'application qui fixent la valeur des plafonds @@ -147,7 +172,10 @@ Les niveaux des plafonds de ressources, qui varient en fonction du nombre d'enfa # nous avons choisi de ne pas inclure tout ce code dans ce document. */ -Un complément dégressif est versé lorsque les ressources du bénéficiaire dépassent l'un des plafonds, dans la limite de montants définis par décret. Les modalités de calcul de ces montants et celles du complément dégressif sont définies par décret. +Un complément dégressif est versé lorsque les ressources du bénéficiaire +dépassent l'un des plafonds, dans la limite de montants définis par décret. +Les modalités de calcul de ces montants et celles du complément dégressif +sont définies par décret. /* # Ditto, le volume du code à inclure pour formaliser cette assertion # est assez important et nous avons choisi de ne pas l'inclure dans ce @@ -158,7 +186,8 @@ champ d'application CalculAllocationsFamiliales : */ @Article L521-2|LEGIARTI000006743210@ -Les allocations sont versées à la personne qui assume, dans quelques conditions que ce soit, la charge effective et permanente de l'enfant. +Les allocations sont versées à la personne qui assume, dans quelques conditions +que ce soit, la charge effective et permanente de l'enfant. /* champ d'application CalculAllocationsFamiliales : définition allocations_familiales.charge_par_enfant de enfant @@ -172,7 +201,13 @@ champ d'application CalculAllocationsFamiliales : conséquence égal à ménage.parent_en_charge */ -En cas de résidence alternée de l'enfant au domicile de chacun des parents telle que prévue à l'article 373-2-9 du code civil, mise en oeuvre de manière effective, les parents désignent l'allocataire. Cependant, la charge de l'enfant pour le calcul des allocations familiales est partagée par moitié entre les deux parents soit sur demande conjointe des parents, soit si les parents sont en désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fixe les conditions d'application du présent alinéa. +En cas de résidence alternée de l'enfant au domicile de chacun des parents telle +que prévue à l'article 373-2-9 du code civil, mise en oeuvre de manière +effective, les parents désignent l'allocataire. Cependant, la charge de l'enfant +pour le calcul des allocations familiales est partagée par moitié entre les deux +parents soit sur demande conjointe des parents, soit si les parents sont en +désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fixe +les conditions d'application du présent alinéa. /* champ d'application CalculAllocationsFamiliales : @@ -218,7 +253,10 @@ champ d'application CalculAllocationsFamiliales : # Quelles variables fixées par R521_2 ? */ -Lorsque la personne qui assume la charge effective et permanente de l'enfant ne remplit pas les conditions prévues au titre I du présent livre pour l'ouverture du droit aux allocations familiales, ce droit s'ouvre du chef du père ou, à défaut, du chef de la mère. +Lorsque la personne qui assume la charge effective et permanente de l'enfant ne +remplit pas les conditions prévues au titre I du présent livre pour l'ouverture +du droit aux allocations familiales, ce droit s'ouvre du chef du père ou, +à défaut, du chef de la mère. /* champ d'application CalculAllocationsFamiliales : définition allocations_familiales.récipiendaire_par_enfant de enfant @@ -231,7 +269,18 @@ champ d'application CalculAllocationsFamiliales : # (ménage.parent2 est optionnel) */ -Lorsqu'un enfant est confié au service d'aide sociale à l'enfance, les allocations familiales continuent d'être évaluées en tenant compte à la fois des enfants présents au foyer et du ou des enfants confiés au service de l'aide sociale à l'enfance. La part des allocations familiales dues à la famille pour cet enfant est versée à ce service. Toutefois, le juge peut décider, d'office ou sur saisine du président du conseil général, à la suite d'une mesure prise en application des articles 375-3 et 375-5 du code civil ou des articles 15,16,16 bis et 28 de l' ordonnance n° 45-174 du 2 février 1945 relative à l'enfance délinquante, de maintenir le versement des allocations à la famille, lorsque celle-ci participe à la prise en charge morale ou matérielle de l'enfant ou en vue de faciliter le retour de l'enfant dans son foyer. +Lorsqu'un enfant est confié au service d'aide sociale à l'enfance, les +allocations familiales continuent d'être évaluées en tenant compte à la fois +des enfants présents au foyer et du ou des enfants confiés au service de +l'aide sociale à l'enfance. La part des allocations familiales dues à la +famille pour cet enfant est versée à ce service. Toutefois, le juge peut +décider, d'office ou sur saisine du président du conseil général, à la +suite d'une mesure prise en application des articles 375-3 et 375-5 du code +civil ou des articles 15,16,16 bis et 28 de l' ordonnance n° 45-174 du 2 +février 1945 relative à l'enfance délinquante, de maintenir le versement +des allocations à la famille, lorsque celle-ci participe à la prise en +charge morale ou matérielle de l'enfant ou en vue de faciliter le retour +de l'enfant dans son foyer. /* champ d'application CalculAllocationsFamiliales : @@ -248,7 +297,8 @@ champ d'application CalculAllocationsFamiliales : conséquence égal à service_social */ -Un décret en Conseil d'Etat fixe les conditions d'application du présent article, notamment dans les cas énumérés ci-dessous : +Un décret en Conseil d'Etat fixe les conditions d'application du présent +article, notamment dans les cas énumérés ci-dessous : a) retrait total de l'autorité parentale des parents ou de l'un d'eux ; @@ -263,7 +313,9 @@ d) enfants confiés à un service public, à une institution privée, à un part # est confié à un service social. */ -@Article L521-3|LEGIARTI000006743289@ Chacun des enfants à charge, à l'exception du plus âgé, ouvre droit à partir d'un âge minimum à une majoration des allocations familiales. +@Article L521-3|LEGIARTI000006743289@ Chacun des enfants à charge, à +l'exception du plus âgé, ouvre droit à partir d'un âge minimum à une +majoration des allocations familiales. /* champ d'application CalculAllocationsFamiliales : règle majorations_allocations_familiales.droits_ouverts de enfant @@ -274,7 +326,9 @@ champ d'application CalculAllocationsFamiliales : conséquence rempli */ -Toutefois, les personnes ayant un nombre déterminé d'enfants à charge bénéficient de ladite majoration pour chaque enfant à charge à partir de l'âge mentionné au premier alinéa. +Toutefois, les personnes ayant un nombre déterminé d'enfants à charge +bénéficient de ladite majoration pour chaque enfant à charge à partir +de l'âge mentionné au premier alinéa. /* champ d'application CalculAllocationsFamiliales : règle majorations_allocations_familiales.droits_ouverts de enfant @@ -290,7 +344,9 @@ champ d'application CalculAllocationsFamiliales : @@Chapitre 1er : Etablissement du salaire de base@@++++ @Article L551-1|LEGIARTI000031688371@ -Le montant des prestations familiales est déterminé d'après des bases mensuelles de calcul revalorisées au 1er avril de chaque année par application du coefficient mentionné à l'article L. 161-25 . +Le montant des prestations familiales est déterminé d'après des bases +mensuelles de calcul revalorisées au 1er avril de chaque année par application +du coefficient mentionné à l'article L. 161-25 . /* # Idem que L521-1, on ne formalise pas ici l'évolution de la BMPA champ d'application PrestationsFamiliales : @@ -305,7 +361,10 @@ Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin@@+++ @@Chapitre 1er : Généralités@@++++ @Article L751-1|LEGIARTI000031323778@ -Les dispositions du présent titre s'appliquent en Guadeloupe, en Guyane, en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à l'ensemble des bénéficiaires de la législation générale de sécurité sociale, y compris les membres des professions agricoles. +Les dispositions du présent titre s'appliquent en Guadeloupe, en Guyane, +en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à +l'ensemble des bénéficiaires de la législation générale de sécurité +sociale, y compris les membres des professions agricoles. /* champ d'application CalculPrestationsFamiliales : règle l751_1.régime_outre_mer sous condition @@ -321,9 +380,12 @@ champ d'application CalculPrestationsFamiliales : @@Chapitre 5 : Prestations familiales et prestations assimilées@@++++ @Article L755-3|LEGIARTI000033728786@ -Les dispositions des articles L. 512-1 à L. 512-4 , L. 513-1 , L. 521-2 , L. 552-1 , L. 553-1 , L. 553-2 , L. 553-4 , L. 582-1 , L. 582-2 , L. 583-3 et L. 583-5 sont applicables aux collectivités mentionnées à l'article L. 751-1 . +Les dispositions des articles L. 512-1 à L. 512-4 , L. 513-1 , L. 521-2 , +L. 552-1 , L. 553-1 , L. 553-2 , L. 553-4 , L. 582-1 , L. 582-2 , L. 583-3 +et L. 583-5 sont applicables aux collectivités mentionnées à l'article L. 751-1 . -La base de calcul des prestations familiales est la même que celle qui est fixée en application de l'article L. 551-1 . +La base de calcul des prestations familiales est la même que celle qui est +fixée en application de l'article L. 551-1 . /* champ d'application CalculPrestationsFamiliales : @@ -332,15 +394,19 @@ champ d'application CalculPrestationsFamiliales : */ @Article L755-11|LEGIARTI000031323803@ -Les conditions d'attribution des allocations familiales et de leurs majorations fixées par les articles L. 521-1 et L. 521-3 sont applicables dans les collectivités mentionnées à l'article L. 751-1 . +Les conditions d'attribution des allocations familiales et de leurs majorations +fixées par les articles L. 521-1 et L. 521-3 sont applicables dans les +collectivités mentionnées à l'article L. 751-1 . /* # Aucun changement dans le code, puisque les articles restent applicables */ -Toutefois, les dispositions de l'article L. 755-12 restent en vigueur aussi longtemps que le présent chapitre V est applicable. +Toutefois, les dispositions de l'article L. 755-12 restent en vigueur aussi +longtemps que le présent chapitre V est applicable. @Article L755-12|LEGIARTI000029962999@ -Les allocations familiales sont dues, pour tout enfant, à la personne qui a effectivement la charge de celui-ci. +Les allocations familiales sont dues, pour tout enfant, à la personne qui a +effectivement la charge de celui-ci. /* champ d'application CalculAllocationsFamiliales : règle allocations_familiales.droits_ouverts sous condition @@ -348,7 +414,8 @@ champ d'application CalculAllocationsFamiliales : (nombre de ménage.enfants >= 1) conséquence rempli */ -Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas applicables lorsque le ménage ou la personne a un seul enfant à charge. +Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas +applicables lorsque le ménage ou la personne a un seul enfant à charge. /* # Ceci concerne l'ouverture du droit à l'allocation forfaitaire # et au complément dégressif. diff --git a/examples/allocations_familiales/securite_sociale_R.catala_fr b/examples/allocations_familiales/securite_sociale_R.catala_fr index 4915fb8e..44c4c983 100644 --- a/examples/allocations_familiales/securite_sociale_R.catala_fr +++ b/examples/allocations_familiales/securite_sociale_R.catala_fr @@ -7,13 +7,17 @@ @@Chapitre 2 : Champ d'application.@@++++ @Article R512-2|LEGIARTI000006750602@ -Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième alinéa du présent article. +Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt +ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième +alinéa du présent article. /* champ d'application CalculAllocationsFamiliales : définition l512_3.âge_limite_alinéa_2 égal à 20 an */ -Le plafond de rémunération mentionné au 2° de l'article L. 512-3 est égal, pour un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169. +Le plafond de rémunération mentionné au 2° de l'article L. 512-3 est égal, pour +un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux +articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169. /* champ d'application CalculAllocationsFamiliales : @@ -21,7 +25,9 @@ champ d'application CalculAllocationsFamiliales : 55 % * smic.brut_horaire de ménage.résidence * 169 */ -Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de ces avantages devra être faite suivant les barèmes fixés pour l'application de la législation sur les assurances sociales. +Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de ces +avantages devra être faite suivant les barèmes fixés pour l'application de la +législation sur les assurances sociales. /* # Le programme ne tient pas en compte des avantages en nature @@ -32,19 +38,24 @@ Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de @@Chapitre 1er : Allocations familiales@@++++ @Article R521-1|LEGIARTI000018735853@ -L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les enfants ouvrent droit à la majoration des allocations familiales est fixé à 14 ans. +L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les +enfants ouvrent droit à la majoration des allocations familiales est fixé à +14 ans. /* champ d'application CalculAllocationsFamiliales : définition l521_3.âge_limite_alinéa_1 de enfant égal à 14 an */ -Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article L. 521-3 ouvrant droit à ladite majoration pour chaque enfant est fixé à trois. +Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article +L. 521-3 ouvrant droit à ladite majoration pour chaque enfant est fixé à trois. /* champ d'application CalculAllocationsFamiliales : définition l521_3.minimum_alinéa_2 égal à 3 */ -NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les modifications induites par le décret n° 2008-409 s'appliquent aux enfants dont le onzième anniversaire est postérieur au 30 avril 2008. +NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les +modifications induites par le décret n° 2008-409 s'appliquent aux enfants dont +le onzième anniversaire est postérieur au 30 avril 2008. /* # Notons ici un champ d'application différent, correspondant à une ancienne # version du corpus législatif dont un morceau s'applique encore. Nous avons @@ -61,9 +72,15 @@ champ d'application CalculAllocationsFamiliales : calcul_avril_2008.l521_3.minimum_alinéa_2 de enfant */ @Article R521-2|LEGIARTI000006750608@ -Dans les situations visées au deuxième alinéa de l'article L. 521-2 , l'allocataire est celui des deux parents qu'ils désignent d'un commun accord. A défaut d'accord sur la désignation d'un allocataire unique, chacun des deux parents peut se voir reconnaître la qualité d'allocataire : +Dans les situations visées au deuxième alinéa de l'article L. 521-2 , +l'allocataire est celui des deux parents qu'ils désignent d'un commun accord. +A défaut d'accord sur la désignation d'un allocataire unique, chacun des deux +parents peut se voir reconnaître la qualité d'allocataire : + 1° Lorsque les deux parents en ont fait la demande conjointe ; -2° Lorsque les deux parents n'ont ni désigné un allocataire unique, ni fait une demande conjointe de partage. + +2° Lorsque les deux parents n'ont ni désigné un allocataire unique, ni fait +une demande conjointe de partage. /* # Le fait que l'allocataire dans le cas d'un commun accord soit celui des # deux parents désigné par l'accord est déjà modélisé dans L512-2. @@ -82,14 +99,21 @@ champ d'application CalculAllocationsFamiliales : conséquence égal à Partagée */ -Lorsque les parents ont désigné un allocataire unique ou fait une demande conjointe de partage, ils ne peuvent remettre en cause les modalités ainsi choisies qu'au bout d'un an, sauf modification des modalités de résidence du ou des enfants. +Lorsque les parents ont désigné un allocataire unique ou fait une demande +conjointe de partage, ils ne peuvent remettre en cause les modalités ainsi +choisies qu'au bout d'un an, sauf modification des modalités de résidence du +ou des enfants. /* # On ne modélise pas le délai minimal entre changement de situation dans # ce programme. */ @Article R521-3|LEGIARTI000006750610@ -Sous réserve de l'article R. 521-4, dans les situations visées aux 1° et 2° de l'article R. 521-2 , la prestation due à chacun des parents est égale au montant des allocations familiales dues pour le total des enfants à charge, multiplié par un coefficient résultant du rapport entre le nombre moyen d'enfants et le nombre total d'enfants. +Sous réserve de l'article R. 521-4, dans les situations visées aux 1° et 2° de +l'article R. 521-2 , la prestation due à chacun des parents est égale au +montant des allocations familiales dues pour le total des enfants à charge, +multiplié par un coefficient résultant du rapport entre le nombre moyen +d'enfants et le nombre total d'enfants. /* champ d'application CalculAllocationsFamiliales : @@ -102,8 +126,11 @@ champ d'application CalculAllocationsFamiliales : allocations_familiales.nombre_total_enfants */ -Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme du nombre d'enfants à charge dans les conditions suivantes : +Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme +du nombre d'enfants à charge dans les conditions suivantes : + 1° Chaque enfant en résidence alternée compte pour 0,5 ; + 2° Les autres enfants à charge comptent pour 1. /* champ d'application CalculAllocationsFamiliales : @@ -114,7 +141,9 @@ champ d'application CalculAllocationsFamiliales : -- GardeAlternée de parents : 0,5 ) */ -Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du ou des enfants en résidence alternée et, le cas échéant, du ou des autres enfants à charge. +Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du +ou des enfants en résidence alternée et, le cas échéant, du ou des autres +enfants à charge. /* champ d'application CalculAllocationsFamiliales : définition allocations_familiales.nombre_total_enfants égal à @@ -122,14 +151,17 @@ champ d'application CalculAllocationsFamiliales : */ @Article R521-4|LEGIARTI000006750613@ -Pour l'ouverture du droit à la majoration prévue à l'article L. 521-3 , le nombre d'enfants à charge est évalué dans les conditions prévues au premier alinéa de l'article R. 521-3. +Pour l'ouverture du droit à la majoration prévue à l'article L. 521-3 , le +nombre d'enfants à charge est évalué dans les conditions prévues au premier +alinéa de l'article R. 521-3. /* # ménage.enfants ne contient que des enfants à charge donc rien à formaliser # ici */ -Lorsque le ou les enfants ouvrant droit à ladite majoration sont en résidence alternée, le montant servi au titre de cette majoration est réduit de moitié. +Lorsque le ou les enfants ouvrant droit à ladite majoration sont en résidence +alternée, le montant servi au titre de cette majoration est réduit de moitié. /* champ d'application CalculAllocationsFamiliales : @@ -151,7 +183,10 @@ champ d'application CalculAllocationsFamiliales : @@Chapitre 5 : Prestations familiales et prestations assimilées@@++++ @Article R755-0-2|LEGIARTI000006752633@ -Le plafond de rémunération des enfants à charge mentionnés à l'article L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en vigueur dans chacun des départements mentionnés à l'article L. 751-1 , multiplié par 169. +Le plafond de rémunération des enfants à charge mentionnés à l'article +L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en +vigueur dans chacun des départements mentionnés à l'article L. 751-1 , +multiplié par 169. /* champ d'application CalculAllocationsFamiliales : définition l512_3.plafond_rémunération_mensuelle_alinéa_2 diff --git a/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr b/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr index 621fc779..7e70a0d8 100644 --- a/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr +++ b/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr @@ -7,15 +7,20 @@ @@0I : Définition du revenu net global@@++++++ @Article 1 A@ -Il est établi un impôt annuel unique sur le revenu des personnes physiques désigné sous le nom d'impôt sur le revenu. Cet impôt frappe le revenu net global du contribuable déterminé conformément aux dispositions des articles 156 à 168. +Il est établi un impôt annuel unique sur le revenu des personnes physiques +désigné sous le nom d'impôt sur le revenu. Cet impôt frappe le revenu net +global du contribuable déterminé conformément aux dispositions des +articles 156 à 168. -Ce revenu net global est constitué par le total des revenus nets des catégories suivantes : +Ce revenu net global est constitué par le total des revenus nets des +catégories suivantes : – Revenus fonciers ; – Bénéfices industriels et commerciaux ; -– Rémunérations, d'une part, des gérants majoritaires des sociétés à responsabilité limitée n'ayant pas opté pour le régime fiscal des sociétés de personnes dans les conditions prévues au IV de l'article 3 du décret n° 55-594 du 20 mai 1955 modifié et des gérants des sociétés en commandite par actions et, d'autre part, des associés en nom des sociétés de personnes et des membres des sociétés en participation lorsque ces sociétés ont opté pour le régime fiscal des sociétés de capitaux ; +– Rémunérations, d'une part, des gérants majoritaires des sociétés à +responsabilité limitée n'ayant pas opté pour le régime fiscal des sociétés de personnes dans les conditions prévues au IV de l'article 3 du décret n° 55-594 du 20 mai 1955 modifié et des gérants des sociétés en commandite par actions et, d'autre part, des associés en nom des sociétés de personnes et des membres des sociétés en participation lorsque ces sociétés ont opté pour le régime fiscal des sociétés de capitaux ; – Bénéfices de l'exploitation agricole ; @@ -25,7 +30,9 @@ Ce revenu net global est constitué par le total des revenus nets des catégorie – Revenus de capitaux mobiliers ; -– Plus-values de cession à titre onéreux de biens ou de droits de toute nature, déterminés conformément aux dispositions des articles 14 à 155, total dont sont retranchées les charges énumérées à l'article 156. +– Plus-values de cession à titre onéreux de biens ou de droits de toute +nature, déterminés conformément aux dispositions des articles 14 à 155, +total dont sont retranchées les charges énumérées à l'article 156. /* déclaration structure RevenuNetGlobal: diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index cec6c36d..94fd31f1 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -1,26 +1,48 @@ @@The Catala language tutorial@@ -Welcome to this tutorial, whose objective is to guide you through the features of the Catala language and trach you how to annotate a legislative text using the language. This document is addressed primarily to developers or people that have a programming background. It will use terms and jargon that might be unintelligible for lawyers in general. +Welcome to this tutorial, whose objective is to guide you through the features +of the Catala language and trach you how to annotate a legislative text using +the language. This document is addressed primarily to developers or people that +have a programming background. It will use terms and jargon that might be +unintelligible for lawyers in general. @@Literate programming@@+ -To begin writing a Catala program, you must start from the text of the legislative source that will justify the code that you will write. Concretely, that means copy-pasting the text of the law into a Catala source file and formatting it according so that Catala can understand it. +To begin writing a Catala program, you must start from the text of the +legislative source that will justify the code that you will write. Concretely, +that means copy-pasting the text of the law into a Catala source file and +formatting it according so that Catala can understand it. -You can write any kind of plain text in Catala, and it will be printed as is in PDF or HTML output. Keep in mind however that one line in the source file corresponds to a paragraph in the output. Catala allows you to declare section or subsection headers as it is done here, but the fundamental division unit is the article. Let's analyse a fictional example that defines an income tax. +You can write any kind of plain text in Catala, and it will be printed as is +in PDF or HTML output. Keep in mind however that one line in the source file +corresponds to a paragraph in the output. Catala allows you to declare section +or subsection headers as it is done here, but the fundamental division unit is +the article. Let's analyse a fictional example that defines an income tax. @Article 1@ -The income tax for an individual is defined as a fixed percentage of the individual's income over a year. +The income tax for an individual is defined as a fixed percentage of the +individual's income over a year. /* # This is a placeholder comment, the code for that article should go here */ -We will now proceed to encode the algorithmic content of this article using the Catala language. To do that, we will intertwine short snippets of code between the sentences of the legislative text. Each snippet of code should be as short as possible and as close as possible to the actual sentence that justifies the code. +We will now proceed to encode the algorithmic content of this article using +the Catala language. To do that, we will intertwine short snippets of code +between the sentences of the legislative text. Each snippet of code should +be as short as possible and as close as possible to the actual sentence that +justifies the code. @@Defining a fictional income tax@@+ -The content of article 1 uses a lot of implicit context : there exists an individual with an income, as well as an income tax that the individual has to pay each year. Even if this implicit context is not verbatim in the law, we have to explicit it for programming purposes. Concretely, we need a "metadata" section that defines the shape and types of the data used inside the law. +The content of article 1 uses a lot of implicit context : there exists an +individual with an income, as well as an income tax that the individual has +to pay each year. Even if this implicit context is not verbatim in the law, +we have to explicit it for programming purposes. Concretely, we need a +"metadata" section that defines the shape and types of the data used +inside the law. -Let's start our metadata section by declaring the type information for the individual and the income tax computation: +Let's start our metadata section by declaring the type information for the +individual and the income tax computation: @@Begin metadata@@ /* declaration structure Individual: @@ -32,9 +54,15 @@ declaration structure Article1: */ @@End metadata@@ -Each of this declaration is a structure, containing one or more data fields. Structures are useful to group together data that goes together. Usually, you get one structure per concrete object on which the law applies (like the individual), but also one structure for each article that defines quantities (like the article 1). It is up to you to decide how to group the data together, but you should aim to optimize code readability. +Each of this declaration is a structure, containing one or more data fields. +Structures are useful to group together data that goes together. Usually, you +get one structure per concrete object on which the law applies (like the +individual), but also one structure for each article that defines quantities +(like the article 1). It is up to you to decide how to group the data together, +but you should aim to optimize code readability. -Sometimes, the law gives an enumeration of different situations. These enumerations are modeled in Catala using an enumeration type, like: +Sometimes, the law gives an enumeration of different situations. These +enumerations are modeled in Catala using an enumeration type, like: @@Begin metadata@@ /* declaration enumeration TaxCredit: @@ -44,7 +72,10 @@ declaration enumeration TaxCredit: */ @@End metadata@@ -We've defined and typed the data that the program will manipulate. Now we have to define the logical context in which these data will evolve. This is done in Catala using "scopes". Scopes also have to be declared in metadata, so here we go: +We've defined and typed the data that the program will manipulate. Now we have +to define the logical context in which these data will evolve. This is done in +Catala using "scopes". Scopes also have to be declared in metadata, so here we +go: @@Begin metadata@@ /* @@ -54,19 +85,29 @@ declaration scope IncomeTaxComputation: */ @@End metadata@@ -This scope declaration says that whenever we're in the scope "IncomeTaxComputation", then we have access to two elements in context, namely the individual's data and the data defined by article 1. We will be able to refer to the lowercase variables in our code, either to use them or to define them or one of their part. +This scope declaration says that whenever we're in the scope +"IncomeTaxComputation", then we have access to two elements in context, +namely the individual's data and the data defined by article 1. We will be +able to refer to the lowercase variables in our code, either to use them or to +define them or one of their part. -We now have everything to annotate the contents of article 1, which is copied over below. +We now have everything to annotate the contents of article 1, which is copied +over below. @Article 1@ -The income tax for an individual is defined as a fixed percentage of the individual's income over a year. +The income tax for an individual is defined as a fixed percentage of the +individual's income over a year. /* scope IncomeTaxComputation: definition article1.income_tax equals invidual.income * article1.fixed_percentage */ -In the code, we are defining inside our scope the amount of the income tax according to the formula described in the article. When defining formulaes, you have access to all the usual arithmetic operators. But what is the value of that fixed percentage? Often, precise values are defined elsewhere in the legislative source. Here, let's suppose we have: +In the code, we are defining inside our scope the amount of the income tax +according to the formula described in the article. When defining formulaes, +you have access to all the usual arithmetic operators. But what is the value +of that fixed percentage? Often, precise values are defined elsewhere in the +legislative source. Here, let's suppose we have: @Article 2@ The fixed percentage mentionned at article 1 is equal to 20 %. @@ -75,19 +116,25 @@ scope IncomeTaxComputation: definition article1.fixed_percentage equals 20 % */ -You can see here that Catala allows definitions to be scattered throughout the annotation of the legislative text, so that each +You can see here that Catala allows definitions to be scattered throughout +the annotation of the legislative text, so that each definition is as close as possible to its location in the text. @@Conditional definitions@@ -So far so good, but now the legislative text introduces some trickyness. Let us suppose the third article says: +So far so good, but now the legislative text introduces some trickyness. Let us +suppose the third article says: -@Article 3@ If the individual is in charge of 2 or more children, then the fixed percentage mentionned at article 1 is equal to 15 %. +@Article 3@ If the individual is in charge of 2 or more children, then the fixed +percentage mentionned at article 1 is equal to 15 %. /* # How to redefine article1.fixed_percentage? */ -This article actually gives another definition for the fixed percentage, which was already defined in article 2. However, article 3 defines the percentage conditionnally to the individual having more than 2 children. Catala allows you precisely to redefine a variable under a condition: +This article actually gives another definition for the fixed percentage, which + was already defined in article 2. However, article 3 defines the percentage + conditionnally to the individual having more than 2 children. Catala allows + you precisely to redefine a variable under a condition: /* scope IncomeTaxComputation: @@ -96,12 +143,18 @@ scope IncomeTaxComputation: consequence equals 15 % */ -When the Catala program will execute, the right definition will be dynamically chosen by looking at which condition is true. A correctly drafted legislative source should always ensure that at most one condition is true at all times. However, if it is not the case, Catala will let you define a precedence on the conditions, which has to be justified by the law. +When the Catala program will execute, the right definition will be dynamically +chosen by looking at which condition is true. A correctly drafted legislative +source should always ensure that at most one condition is true at all times. +However, if it is not the case, Catala will let you define a precedence on the +conditions, which has to be justified by the law. @@Functions@@ -Catala lets you define functions anywhere in your data. Here's what it looks like in the metadata definition when we want to define a two-brackets tax computation: +Catala lets you define functions anywhere in your data. Here's what it looks +like in the metadata definition when we want to define a two-brackets tax +computation: @@Begin metadata@@ /* declaration structure TwoBrackets: @@ -117,7 +170,8 @@ declaration scope TwoBracketsTaxComputation : And in the code: -@Article4@ The tax amount for a two-brackets computation is equal to the amount of income in each bracket multiplied by the rate of each bracket. +@Article4@ The tax amount for a two-brackets computation is equal to the amount +of income in each bracket multiplied by the rate of each bracket. /* scope TwoBracketsTaxComputation : @@ -131,9 +185,11 @@ scope TwoBracketsTaxComputation : @@Scope inclusion@@ -Now that we've defined our helper scope for computing a two-brackets tax, we want to use it in our main tax computation scope. +Now that we've defined our helper scope for computing a two-brackets tax, we +want to use it in our main tax computation scope. -@Article 5@ For individuals whose income is greater than $100,000, the income tax of article 1 is computed with a two-brackets system. +@Article 5@ For individuals whose income is greater than $100,000, the income +tax of article 1 is computed with a two-brackets system. /* declaration scope IncomeTaxComputation: # The scope inclusion has to be added in the scope declaration @@ -158,7 +214,8 @@ declaration scope ExemptedOfTax: @@End metadata@@ @Article 6@ -Individuals earning less than $10,000 are exempted of the income tax mentionned at article 1. +Individuals earning less than $10,000 are exempted of the income tax mentionned +at article 1. /* scope ExemptedOfTax : definition article1.income_tax equals $0 @@ -174,4 +231,6 @@ scope IncomeTaxComputation: tax_exempt.article1.income_tax */ -This snippet of code actually brings the definition of article1.income_tax of ExemptedOfTax into the IncomeTaxComputation scope, prefixing it with the "income under $10,000" condition. +This snippet of code actually brings the definition of article1.income_tax of +ExemptedOfTax into the IncomeTaxComputation scope, prefixing it with the +"income under $10,000" condition. diff --git a/examples/us_tax_code/section_1015.catala_en b/examples/us_tax_code/section_1015.catala_en index a49bf3b6..16770ee3 100644 --- a/examples/us_tax_code/section_1015.catala_en +++ b/examples/us_tax_code/section_1015.catala_en @@ -34,7 +34,12 @@ declaration scope BasisOfGift: @@End metadata@@ @(a) Gifts after December 31, 1920@ -If the property was acquired by gift after December 31, 1920, the basis shall be the same as it would be in the hands of the donor or the last preceding owner by whom it was not acquired by gift, except that if such basis (adjusted for the period before the date of the gift as provided in section 1016) is greater than the fair market value of the property at the time of the gift, then for the purpose of determining loss the basis shall be such fair market value. +If the property was acquired by gift after December 31, 1920, the basis shall be +the same as it would be in the hands of the donor or the last preceding owner by +whom it was not acquired by gift, except that if such basis (adjusted for the +period before the date of the gift as provided in section 1016) is greater than +the fair market value of the property at the time of the gift, then for the +purpose of determining loss the basis shall be such fair market value. /* scope BasisOfGift: definition basis_subsection_a equals @@ -49,7 +54,15 @@ scope BasisOfGift: consequence equals basis_subsection_a */ - If the facts necessary to determine the basis in the hands of the donor or the last preceding owner are unknown to the donee, the Secretary shall, if possible, obtain such facts from such donor or last preceding owner, or any other person cognizant thereof. If the Secretary finds it impossible to obtain such facts, the basis in the hands of such donor or last preceding owner shall be the fair market value of such property as found by the Secretary as of the date or approximate date at which, according to the best information that the Secretary is able to obtain, such property was acquired by such donor or last preceding owner. + If the facts necessary to determine the basis in the hands of the donor or the + last preceding owner are unknown to the donee, the Secretary shall, if + possible, obtain such facts from such donor or last preceding owner, or any + other person cognizant thereof. If the Secretary finds it impossible to obtain + such facts, the basis in the hands of such donor or last preceding owner shall + be the fair market value of such property as found by the Secretary as of the + date or approximate date at which, according to the best information that the + Secretary is able to obtain, such property was acquired by such donor or last + preceding owner. /* scope BasisOfGift under condition acquisition.moment > |01/31/1920| and @@ -63,7 +76,12 @@ scope BasisOfGift under condition @(b) Transfer in trust after December 31, 1920@ -If the property was acquired after December 31, 1920, by a transfer in trust (other than by a transfer in trust by a gift, bequest, or devise), the basis shall be the same as it would be in the hands of the grantor increased in the amount of gain or decreased in the amount of loss recognized to the grantor on such transfer under the law applicable to the year in which the transfer was made. +If the property was acquired after December 31, 1920, by a transfer in trust +(other than by a transfer in trust by a gift, bequest, or devise), the basis +shall be the same as it would be in the hands of the grantor increased in the +amount of gain or decreased in the amount of loss recognized to the grantor on +such transfer under the law applicable to the year in which the transfer was +made. /* scope BasisOfGift under condition acquisition.moment > |01/31/1920| and @@ -74,7 +92,9 @@ scope BasisOfGift under condition */ @(c) Gift or transfer in trust before January 1, 1921@ -If the property was acquired by gift or transfer in trust on or before December 31, 1920, the basis shall be the fair market value of such property at the time of such acquisition. +If the property was acquired by gift or transfer in trust on or before December +31, 1920, the basis shall be the fair market value of such property at the time +of such acquisition. /* scope BasisOfGift under condition acquisition.moment <= |01/31/1920|: definition basis equals @@ -84,7 +104,10 @@ scope BasisOfGift under condition acquisition.moment <= |01/31/1920|: @@(d) Increased basis for gift tax paid@@+ @(1) In general@ If— -(A) the property is acquired by gift on or after September 2, 1958, the basis shall be the basis determined under subsection (a), increased (but not above the fair market value of the property at the time of the gift) by the amount of gift tax paid with respect to such gift, or +(A) the property is acquired by gift on or after September 2, 1958, the basis +shall be the basis determined under subsection (a), increased (but not above +the fair market value of the property at the time of the gift) by the amount +of gift tax paid with respect to such gift, or /* scope BasisOfGift under condition acquisition.moment >= |09/02/1958| and @@ -98,7 +121,13 @@ scope BasisOfGift under condition gift_tax_paid ) */ -(B) the property was acquired by gift before September 2, 1958, and has not been sold, exchanged, or otherwise disposed of before such date, the basis of the property shall be increased on such date by the amount of gift tax paid with respect to such gift, but such increase shall not exceed an amount equal to the amount by which the fair market value of the property at the time of the gift exceeded the basis of the property in the hands of the donor at the time of the gift. +(B) the property was acquired by gift before September 2, 1958, and has not been +sold, exchanged, or otherwise disposed of before such date, the basis of the +property shall be increased on such date by the amount of gift tax paid with +respect to such gift, but such increase shall not exceed an amount equal to the +amount by which the fair market value of the property at the time of the gift +exceeded the basis of the property in the hands of the donor at the time of the +gift. /* scope BasisOfGift under condition acquisition.moment < |09/02/1958| and @@ -118,26 +147,46 @@ scope BasisOfGift under condition */ @(2) Amount of tax paid with respect to gift@ -For purposes of paragraph (1), the amount of gift tax paid with respect to any gift is an amount which bears the same ratio to the amount of gift tax paid under chapter 12 with respect to all gifts made by the donor for the calendar year (or preceding calendar period) in which such gift is made as the amount of such gift bears to the taxable gifts (as defined in section 2503(a) but computed without the deduction allowed by section 2521) made by the donor during such calendar year or period. For purposes of the preceding sentence, the amount of any gift shall be the amount included with respect to such gift in determining (for the purposes of section 2503(a)) the total amount of gifts made during the calendar year or period, reduced by the amount of any deduction allowed with respect to such gift under section 2522 (relating to charitable deduction) or under section 2523 (relating to marital deduction). +For purposes of paragraph (1), the amount of gift tax paid with respect to any +gift is an amount which bears the same ratio to the amount of gift tax paid under +chapter 12 with respect to all gifts made by the donor for the calendar year +(or preceding calendar period) in which such gift is made as the amount of such +gift bears to the taxable gifts (as defined in section 2503(a) but computed +without the deduction allowed by section 2521) made by the donor during such +calendar year or period. For purposes of the preceding sentence, the amount of +any gift shall be the amount included with respect to such gift in determining +(for the purposes of section 2503(a)) the total amount of gifts made during the +calendar year or period, reduced by the amount of any deduction allowed with +respect to such gift under section 2522 (relating to charitable deduction) or +under section 2523 (relating to marital deduction). /* -# We don't formalize the amount of gift tax since it would require formalizing other sections of the code +# We don't formalize the amount of gift tax since it would require +#formalizing other sections of the code */ @(3) Gifts treated as made one-half by each spouse@ -For purposes of paragraph (1), where the donor and his spouse elected, under section 2513 to have the gift considered as made one-half by each, the amount of gift tax paid with respect to such gift under chapter 12 shall be the sum of the amounts of tax paid with respect to each half of such gift (computed in the manner provided in paragraph (2)). +For purposes of paragraph (1), where the donor and his spouse elected, under +section 2513 to have the gift considered as made one-half by each, the amount +of gift tax paid with respect to such gift under chapter 12 shall be the sum +of the amounts of tax paid with respect to each half of such gift (computed in +the manner provided in paragraph (2)). /* # Same here */ @(4) Treatment as adjustment to basis@ -For purposes of section 1016(b), an increase in basis under paragraph (1) shall be treated as an adjustment under section 1016(a). +For purposes of section 1016(b), an increase in basis under paragraph (1) shall +be treated as an adjustment under section 1016(a). /* # Same here */ @(5) Application to gifts before 1955@ -With respect to any property acquired by gift before 1955, references in this subsection to any provision of this title shall be deemed to refer to the corresponding provision of the Internal Revenue Code of 1939 or prior revenue laws which was effective for the year in which such gift was made. +With respect to any property acquired by gift before 1955, references in this +subsection to any provision of this title shall be deemed to refer to the +corresponding provision of the Internal Revenue Code of 1939 or prior revenue +laws which was effective for the year in which such gift was made. /* # Same here */ @@ -145,8 +194,13 @@ With respect to any property acquired by gift before 1955, references in this su @@(6) Special rule for gifts made after December 31, 1976@@++ @(A) In general@ -In the case of any gift made after December 31, 1976, the increase in basis provided by this subsection with respect to any gift for the gift tax paid under chapter 12 shall be an amount (not in excess of the amount of tax so paid) which bears the same ratio to the amount of tax so paid as— +In the case of any gift made after December 31, 1976, the increase in basis +provided by this subsection with respect to any gift for the gift tax paid under +chapter 12 shall be an amount (not in excess of the amount of tax so paid) which +bears the same ratio to the amount of tax so paid as— + (i) the net appreciation in value of the gift, bears to + (ii) the amount of the gift. /* scope BasisOfGift under condition @@ -161,7 +215,9 @@ scope BasisOfGift under condition */ @(B) Net appreciation@ -For purposes of paragraph (1), the net appreciation in value of any gift is the amount by which the fair market value of the gift exceeds the donor’s adjusted basis immediately before the gift. +For purposes of paragraph (1), the net appreciation in value of any gift is the +amount by which the fair market value of the gift exceeds the donor’s adjusted +basis immediately before the gift. /* scope BasisOfGift: definition value.net_appreciation equals @@ -169,7 +225,9 @@ scope BasisOfGift: */ @(e) Gifts between spouses@ -In the case of any property acquired by gift in a transfer described in section 1041(a), the basis of such property in the hands of the transferee shall be determined under section 1041(b)(2) and not this section. +In the case of any property acquired by gift in a transfer described in section +1041(a), the basis of such property in the hands of the transferee shall be +determined under section 1041(b)(2) and not this section. /* # Same here */ diff --git a/examples/us_tax_code/section_121.catala_en b/examples/us_tax_code/section_121.catala_en index decf0487..878a694b 100644 --- a/examples/us_tax_code/section_121.catala_en +++ b/examples/us_tax_code/section_121.catala_en @@ -34,7 +34,10 @@ declaration scope Section121: @(a) Exclusion@ -Gross income shall not include gain from the sale or exchange of property if, during the 5-year period ending on the date of the sale or exchange, such property has been owned and used by the taxpayer as the taxpayer’s principal residence for periods aggregating 2 years or more. +Gross income shall not include gain from the sale or exchange of property if, +during the 5-year period ending on the date of the sale or exchange, such +property has been owned and used by the taxpayer as the taxpayer’s principal +residence for periods aggregating 2 years or more. /* # It's actually agragated. Input: how many days have you lived in the property # for the last five years. @@ -56,7 +59,8 @@ scope Section121: @(1) In general@ -The amount of gain excluded from gross income under subsection (a) with respect to any sale or exchange shall not exceed $250,000. +The amount of gain excluded from gross income under subsection (a) with +respect to any sale or exchange shall not exceed $250,000. /* scope Section121: definition maximum_gain_excluded equals $250,000 @@ -70,7 +74,8 @@ scope Section121: @(2) Special rules for joint returns@ -In the case of a husband and wife who make a joint return for the taxable year of the sale or exchange of the property— +In the case of a husband and wife who make a joint return for the taxable year +of the sale or exchange of the property— /* scope Section121: @@ -96,26 +101,41 @@ such property; and respect to such property by reason of paragraph (3). @(B) Other joint returns@ -If such spouses do not meet the requirements of subparagraph (A), the limitation under paragraph (1) shall be the sum of the limitations under paragraph (1) to which each spouse would be entitled if such spouses had not been married. For purposes of the preceding sentence, each spouse shall be treated as owning the property during the period that either spouse owned the property. +If such spouses do not meet the requirements of subparagraph (A), the limitation +under paragraph (1) shall be the sum of the limitations under paragraph (1) to +which each spouse would be entitled if such spouses had not been married. For +purposes of the preceding sentence, each spouse shall be treated as owning the +property during the period that either spouse owned the property. @@(3) Application to only 1 sale or exchange every 2 years@@++ -Subsection (a) shall not apply to any sale or exchange by the taxpayer if, during the 2-year period ending on the date of such sale or exchange, there was any other sale or exchange by the taxpayer to which subsection (a) applied. +Subsection (a) shall not apply to any sale or exchange by the taxpayer if, +during the 2-year period ending on the date of such sale or exchange, there +was any other sale or exchange by the taxpayer to which subsection (a) applied. @@(4) Special rule for certain sales by surviving spouses@@++ -In the case of a sale or exchange of property by an unmarried individual whose spouse is deceased on the date of such sale, paragraph (1) shall be applied by substituting “$500,000” for “$250,000” if such sale occurs not later than 2 years after the date of death of such spouse and the requirements of paragraph (2)(A) were met immediately before such date of death. +In the case of a sale or exchange of property by an unmarried individual whose +spouse is deceased on the date of such sale, paragraph (1) shall be applied by +substituting “$500,000” for “$250,000” if such sale occurs not later than 2 +years after the date of death of such spouse and the requirements of paragraph +(2)(A) were met immediately before such date of death. @@(5) Exclusion of gain allocated to nonqualified use@@++ @(A) In general@ -Subsection (a) shall not apply to so much of the gain from the sale or exchange of property as is allocated to periods of nonqualified use. +Subsection (a) shall not apply to so much of the gain from the sale or exchange +of property as is allocated to periods of nonqualified use. @(B) Gain allocated to periods of nonqualified use@ -For purposes of subparagraph (A), gain shall be allocated to periods of nonqualified use based on the ratio which— -(i) the aggregate periods of nonqualified use during the period such property was owned by the taxpayer, bears to +For purposes of subparagraph (A), gain shall be allocated to periods of +nonqualified use based on the ratio which— + +(i) the aggregate periods of nonqualified use during the period such property +was owned by the taxpayer, bears to + (ii) the period such property was owned by the taxpayer. @@(C) Period of nonqualified use@@+++ @@ -124,21 +144,33 @@ For purposes of this paragraph— @(i) In general@ -The term “period of nonqualified use” means any period (other than the portion of any period preceding January 1, 2009) during which the property is not used as the principal residence of the taxpayer or the taxpayer’s spouse or former spouse. +The term “period of nonqualified use” means any period (other than the portion +of any period preceding January 1, 2009) during which the property is not used +as the principal residence of the taxpayer or the taxpayer’s spouse or former +spouse. @(ii) Exceptions@ The term “period of nonqualified use” does not include— -(I) any portion of the 5-year period described in subsection (a) which is after the last date that such property is used as the principal residence of the taxpayer or the taxpayer’s spouse, +(I) any portion of the 5-year period described in subsection (a) which is after +the last date that such property is used as the principal residence of the +taxpayer or the taxpayer’s spouse, -(II) any period (not to exceed an aggregate period of 10 years) during which the taxpayer or the taxpayer’s spouse is serving on qualified official extended duty (as defined in subsection (d)(9)(C)) described in clause (i), (ii), or (iii) of subsection (d)(9)(A), and +(II) any period (not to exceed an aggregate period of 10 years) during which the +taxpayer or the taxpayer’s spouse is serving on qualified official extended duty +(as defined in subsection (d)(9)(C)) described in clause (i), (ii), or (iii) of +subsection (d)(9)(A), and -(III) any other period of temporary absence (not to exceed an aggregate period of 2 years) due to change of employment, health conditions, or such other unforeseen circumstances as may be specified by the Secretary. +(III) any other period of temporary absence (not to exceed an aggregate period +of 2 years) due to change of employment, health conditions, or such other +unforeseen circumstances as may be specified by the Secretary. @(D) Coordination with recognition of gain attributable to depreciation@ For purposes of this paragraph— -(i) subparagraph (A) shall be applied after the application of subsection (d)(6), and +(i) subparagraph (A) shall be applied after the application of subsection +(d)(6), and -(ii) subparagraph (B) shall be applied without regard to any gain to which subsection (d)(6) applies. +(ii) subparagraph (B) shall be applied without regard to any gain to which +subsection (d)(6) applies. diff --git a/examples/us_tax_code/section_132.catala_en b/examples/us_tax_code/section_132.catala_en index 03354484..41a8058b 100644 --- a/examples/us_tax_code/section_132.catala_en +++ b/examples/us_tax_code/section_132.catala_en @@ -23,8 +23,10 @@ declaration scope QualifiedEmployeeDiscount: For purposes of this section— @(1) Qualified employee discount@ -The term “qualified employee discount” means any employee discount with respect to qualified property or services to the extent such discount does not exceed— -(A) in the case of property, the gross profit percentage of the price at which the property is being offered by the employer to customers, or +The term “qualified employee discount” means any employee discount with respect +to qualified property or services to the extent such discount does not exceed— +(A) in the case of property, the gross profit percentage of the price at which +the property is being offered by the employer to customers, or /* scope QualifiedEmployeeDiscount : definition qualified_employee_discount @@ -35,7 +37,8 @@ scope QualifiedEmployeeDiscount : then customer_price * gross_profit_percentage else employee_discount */ -(B) in the case of services, 20 percent of the price at which the services are being offered by the employer to customers. +(B) in the case of services, 20 percent of the price at which the services are +being offered by the employer to customers. /* scope QualifiedEmployeeDiscount : definition qualified_employee_discount @@ -50,7 +53,10 @@ equals @(A) In general@ The term “gross profit percentage” means the percent which— -(i) the excess of the aggregate sales price of property sold by the employer to customers over the aggregate cost of such property to the employer, is of + +(i) the excess of the aggregate sales price of property sold by the employer +to customers over the aggregate cost of such property to the employer, is of + (ii) the aggregate sale price of such property. /* scope QualifiedEmployeeDiscount @@ -62,7 +68,11 @@ scope QualifiedEmployeeDiscount */ @(B) Determination of gross profit percentage@ Gross profit percentage shall be determined on the basis of— -(i) all property offered to customers in the ordinary course of the line of business of the employer in which the employee is performing services (or a reasonable classification of property selected by the employer), and + +(i) all property offered to customers in the ordinary course of the line of +business of the employer in which the employee is performing services (or a +reasonable classification of property selected by the employer), and + (ii) the employer’s experience during a representative period. /* # (i) and (ii) are subjective criteria for determining the gross profit @@ -70,8 +80,12 @@ Gross profit percentage shall be determined on the basis of— */ @(3) Employee discount defined@ The term “employee discount” means the amount by which— -(A) the price at which the property or services are provided by the employer to an employee for use by such employee, is less than -(B) the price at which such property or services are being offered by the employer to customers. + +(A) the price at which the property or services are provided by the employer to +an employee for use by such employee, is less than + +(B) the price at which such property or services are being offered by the +employer to customers. /* scope QualifiedEmployeeDiscount: assertion customer_price >= employee_price @@ -80,7 +94,11 @@ scope QualifiedEmployeeDiscount: employee_price - customer_price */ @(4) Qualified property or services@ -The term “qualified property or services” means any property (other than real property and other than personal property of a kind held for investment) or services which are offered for sale to customers in the ordinary course of the line of business of the employer in which the employee is performing services. +The term “qualified property or services” means any property (other than real +property and other than personal property of a kind held for investment) or +services which are offered for sale to customers in the ordinary course of +the line of business of the employer in which the employee is performing +services. /* # Again, this is for subjectively determining what item qualifies for a # discount, not formalizing diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 004e973e..d7367d9e 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -360,9 +360,8 @@ let rec lex_code (lexbuf : lexbuf) : token = INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" -let rec lex_law (lexbuf : lexbuf) : token = +let lex_law (lexbuf : lexbuf) : token = match%sedlex lexbuf with - | '\n' -> lex_law lexbuf | "/*" -> is_code := true; code_string_acc := ""; @@ -415,7 +414,7 @@ let rec lex_law (lexbuf : lexbuf) : token = done; LAW_ARTICLE (title, None, None) - | Plus (Compl ('@' | '/' | '\n')) -> LAW_TEXT (Utf8.lexeme lexbuf) + | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) | _ -> raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let lexer lexbuf = if !is_code then lex_code lexbuf else lex_law lexbuf diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 3c785854..32294fdf 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -332,9 +332,8 @@ let rec lex_code_en (lexbuf : lexbuf) : token = INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" -let rec lex_law_en (lexbuf : lexbuf) : token = +let lex_law_en (lexbuf : lexbuf) : token = match%sedlex lexbuf with - | '\n' -> lex_law_en lexbuf | "/*" -> L.is_code := true; L.code_string_acc := ""; @@ -387,7 +386,7 @@ let rec lex_law_en (lexbuf : lexbuf) : token = done; LAW_ARTICLE (title, None, None) - | Plus (Compl ('@' | '/' | '\n')) -> LAW_TEXT (Utf8.lexeme lexbuf) + | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let lexer_en lexbuf = if !L.is_code then lex_code_en lexbuf else lex_law_en lexbuf diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 63d3832b..04265166 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -341,9 +341,8 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" -let rec lex_law_fr (lexbuf : lexbuf) : token = +let lex_law_fr (lexbuf : lexbuf) : token = match%sedlex lexbuf with - | '\n' -> lex_law_fr lexbuf | "/*" -> L.is_code := true; L.code_string_acc := ""; @@ -411,7 +410,7 @@ let rec lex_law_fr (lexbuf : lexbuf) : token = done; LAW_ARTICLE (title, article_id, article_expiration_date) - | Plus (Compl ('@' | '/' | '\n')) -> LAW_TEXT (Utf8.lexeme lexbuf) + | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" let lexer_fr (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index cf35b0ba..71864ef0 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,20 +1,20 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 274. +## Ends in an error in state: 279. ## -## metadata_block -> BEGIN_CODE code END_CODE . END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: -## BEGIN_CODE code END_CODE +## BEGIN_CODE option(law_text) code END_CODE ## should not happen, please file an issue at https://github.com/CatalaLang/catala/issues source_file_or_master: BEGIN_METADATA BEGIN_CODE YEAR ## -## Ends in an error in state: 15. +## Ends in an error in state: 19. ## -## metadata_block -> BEGIN_CODE . code END_CODE END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## metadata_block -> BEGIN_CODE . option(law_text) code END_CODE option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## BEGIN_CODE @@ -24,9 +24,9 @@ expected a declaration or a scope use source_file_or_master: BEGIN_METADATA YEAR ## -## Ends in an error in state: 14. +## Ends in an error in state: 17. ## -## source_file_item -> BEGIN_METADATA . metadata_block [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## source_file_item -> BEGIN_METADATA . option(law_text) metadata_block [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## BEGIN_METADATA @@ -36,7 +36,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 268. +## Ends in an error in state: 273. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -49,7 +49,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 263. +## Ends in an error in state: 268. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -61,7 +61,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 262. +## Ends in an error in state: 267. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -73,7 +73,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 261. +## Ends in an error in state: 266. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -85,7 +85,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 260. +## Ends in an error in state: 265. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -97,7 +97,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 259. +## Ends in an error in state: 264. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -109,7 +109,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 258. +## Ends in an error in state: 263. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -121,7 +121,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 258. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -133,7 +133,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 251. +## Ends in an error in state: 256. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -145,7 +145,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 255. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -157,7 +157,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 255. +## Ends in an error in state: 260. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -170,7 +170,7 @@ expected the next context item, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 248. +## Ends in an error in state: 253. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -182,7 +182,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 247. +## Ends in an error in state: 252. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -196,7 +196,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 246. +## Ends in an error in state: 251. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -210,7 +210,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 245. +## Ends in an error in state: 250. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -222,7 +222,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 244. +## Ends in an error in state: 249. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -234,7 +234,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 243. +## Ends in an error in state: 248. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -246,7 +246,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 230. +## Ends in an error in state: 235. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -258,7 +258,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR ## -## Ends in an error in state: 227. +## Ends in an error in state: 232. ## ## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -270,7 +270,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 238. +## Ends in an error in state: 243. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 234. +## Ends in an error in state: 239. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -294,7 +294,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 233. +## Ends in an error in state: 238. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -306,7 +306,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 240. +## Ends in an error in state: 245. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -318,7 +318,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 216. +## Ends in an error in state: 221. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -330,7 +330,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 220. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -342,7 +342,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 214. +## Ends in an error in state: 219. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +354,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 213. +## Ends in an error in state: 218. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -366,7 +366,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 212. +## Ends in an error in state: 217. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -378,7 +378,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 211. +## Ends in an error in state: 216. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -390,7 +390,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 210. +## Ends in an error in state: 215. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -404,7 +404,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 207. +## Ends in an error in state: 212. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -416,23 +416,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 204, spurious reduction of production assertion_base -> expression -## In state 205, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 206, spurious reduction of production scope_item -> ASSERTION assertion +## In state 49, spurious reduction of production primitive_expression -> CARDINAL +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression +## In state 209, spurious reduction of production assertion_base -> expression +## In state 210, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 211, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 201. +## Ends in an error in state: 206. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -444,7 +444,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 200. +## Ends in an error in state: 205. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -455,15 +455,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 204. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -475,7 +475,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 203. +## Ends in an error in state: 208. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -487,7 +487,7 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 172. +## Ends in an error in state: 177. ## ## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -498,21 +498,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 165, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 49, spurious reduction of production primitive_expression -> CARDINAL +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression +## In state 170, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 164. +## Ends in an error in state: 169. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -524,7 +524,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 192. +## Ends in an error in state: 197. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -535,15 +535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 194. +## Ends in an error in state: 199. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -554,15 +554,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 193. +## Ends in an error in state: 198. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -574,7 +574,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 191. +## Ends in an error in state: 196. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -586,7 +586,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 190. +## Ends in an error in state: 195. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -598,7 +598,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 187. +## Ends in an error in state: 192. ## ## definition -> qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -610,7 +610,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 185. +## Ends in an error in state: 190. ## ## definition -> qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -622,7 +622,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 186. +## Ends in an error in state: 191. ## ## definition -> qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -634,7 +634,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 184. +## Ends in an error in state: 189. ## ## definition -> qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -645,15 +645,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 183. +## Ends in an error in state: 188. ## ## scope_item -> DEFINITION . definition [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -665,7 +665,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 181. +## Ends in an error in state: 186. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -677,7 +677,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 169. +## Ends in an error in state: 174. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -689,7 +689,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 163. +## Ends in an error in state: 168. ## ## rule -> rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -701,7 +701,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 176. +## Ends in an error in state: 181. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -713,7 +713,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 166. +## Ends in an error in state: 171. ## ## rule -> rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -725,7 +725,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 175. +## Ends in an error in state: 180. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -736,15 +736,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 180, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 162, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 180. +## Ends in an error in state: 185. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -757,7 +757,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 166. ## ## scope_item -> RULE . rule [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -769,7 +769,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 165. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -781,7 +781,7 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 44. +## Ends in an error in state: 49. ## ## aggregate_func -> CARDINAL . [ FOR ] ## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -794,7 +794,7 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON CARDINAL ALT YEAR ## -## Ends in an error in state: 69. +## Ends in an error in state: 74. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RPAREN ] ## @@ -806,7 +806,7 @@ expected another field of the struct source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON CARDINAL THEN ## -## Ends in an error in state: 68. +## Ends in an error in state: 73. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RPAREN ] ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RPAREN ] @@ -818,20 +818,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 44, spurious reduction of production primitive_expression -> CARDINAL -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 104, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 49, spurious reduction of production primitive_expression -> CARDINAL +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 109, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another field of the struct or the end of the struct literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON YEAR ## -## Ends in an error in state: 72. +## Ends in an error in state: 77. ## ## struct_content_field -> ident COLON . logical_expression [ RPAREN ALT ] ## @@ -843,7 +843,7 @@ expected an expression for the field of the struct source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT YEAR ## -## Ends in an error in state: 71. +## Ends in an error in state: 76. ## ## struct_content_field -> ident . COLON logical_expression [ RPAREN ALT ] ## @@ -855,7 +855,7 @@ expected a colon and then the expression for the field of the struct source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT YEAR ## -## Ends in an error in state: 67. +## Ends in an error in state: 72. ## ## struct_or_enum_inject_content -> CONTENT LPAREN ALT . separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -867,7 +867,7 @@ expected the name of field of the struct that you are building source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN YEAR ## -## Ends in an error in state: 66. +## Ends in an error in state: 71. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## struct_or_enum_inject_content -> CONTENT LPAREN . ALT separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -880,7 +880,7 @@ expected a struct field creation introduced by a dash source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 130. +## Ends in an error in state: 135. ## ## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -894,7 +894,7 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 65. +## Ends in an error in state: 70. ## ## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## struct_or_enum_inject_content -> CONTENT . LPAREN ALT separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -907,7 +907,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 64. +## Ends in an error in state: 69. ## ## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -919,7 +919,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 120. +## Ends in an error in state: 125. ## ## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -931,7 +931,7 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 126. +## Ends in an error in state: 131. ## ## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -943,7 +943,7 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 125. +## Ends in an error in state: 130. ## ## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -954,14 +954,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 124. +## Ends in an error in state: 129. ## ## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -973,7 +973,7 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 123. +## Ends in an error in state: 128. ## ## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -985,7 +985,7 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 122. +## Ends in an error in state: 127. ## ## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -997,7 +997,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 113. +## Ends in an error in state: 118. ## ## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1009,7 +1009,7 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 117. +## Ends in an error in state: 122. ## ## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1020,14 +1020,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 116. +## Ends in an error in state: 121. ## ## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1039,7 +1039,7 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 115. +## Ends in an error in state: 120. ## ## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1051,7 +1051,7 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 114. +## Ends in an error in state: 119. ## ## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1063,7 +1063,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 39. +## Ends in an error in state: 44. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -1075,7 +1075,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 137. +## Ends in an error in state: 142. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1086,20 +1086,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 140. +## Ends in an error in state: 145. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1111,7 +1111,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 139. +## Ends in an error in state: 144. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1122,20 +1122,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 138. +## Ends in an error in state: 143. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1147,7 +1147,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 37. +## Ends in an error in state: 42. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1159,7 +1159,7 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 57. +## Ends in an error in state: 62. ## ## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1171,7 +1171,7 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 128. +## Ends in an error in state: 133. ## ## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1182,20 +1182,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 35. +## Ends in an error in state: 40. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1207,7 +1207,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 142. +## Ends in an error in state: 147. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1218,14 +1218,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 145. +## Ends in an error in state: 150. ## ## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1236,20 +1236,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 103, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 149, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 108, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 154, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 148. +## Ends in an error in state: 153. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1261,7 +1261,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 153. +## Ends in an error in state: 158. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1273,7 +1273,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 147. +## Ends in an error in state: 152. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1285,7 +1285,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 151. +## Ends in an error in state: 156. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1298,7 +1298,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 150. +## Ends in an error in state: 155. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1310,7 +1310,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 144. +## Ends in an error in state: 149. ## ## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1322,7 +1322,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 143. +## Ends in an error in state: 148. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1334,7 +1334,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 34. +## Ends in an error in state: 39. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1346,7 +1346,7 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 45. +## Ends in an error in state: 50. ## ## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1358,7 +1358,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 102. +## Ends in an error in state: 107. ## ## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1370,7 +1370,7 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 98. +## Ends in an error in state: 103. ## ## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1382,7 +1382,7 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 97. +## Ends in an error in state: 102. ## ## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1393,14 +1393,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 95. +## Ends in an error in state: 100. ## ## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1412,7 +1412,7 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 94. +## Ends in an error in state: 99. ## ## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1424,7 +1424,7 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 93. +## Ends in an error in state: 98. ## ## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1436,7 +1436,7 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 92. +## Ends in an error in state: 97. ## ## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1448,7 +1448,7 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 51. +## Ends in an error in state: 56. ## ## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1460,7 +1460,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 159. +## Ends in an error in state: 164. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1471,22 +1471,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression -## In state 86, spurious reduction of production mult_expression -> base_expression -## In state 81, spurious reduction of production sum_expression -> mult_expression -## In state 73, spurious reduction of production compare_expression -> sum_expression -## In state 105, spurious reduction of production logical_expression -> compare_expression -## In state 112, spurious reduction of production expression -> logical_expression -## In state 157, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 158, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 91, spurious reduction of production mult_expression -> base_expression +## In state 86, spurious reduction of production sum_expression -> mult_expression +## In state 78, spurious reduction of production compare_expression -> sum_expression +## In state 110, spurious reduction of production logical_expression -> compare_expression +## In state 117, spurious reduction of production expression -> logical_expression +## In state 162, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 163, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 49. +## Ends in an error in state: 54. ## ## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1498,7 +1498,7 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 135. +## Ends in an error in state: 140. ## ## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1510,7 +1510,7 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 86. +## Ends in an error in state: 91. ## ## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1522,15 +1522,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression -## In state 53, spurious reduction of production base_expression -> primitive_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 89. +## Ends in an error in state: 94. ## ## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1542,7 +1542,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 80. +## Ends in an error in state: 85. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1554,7 +1554,7 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 56. +## Ends in an error in state: 61. ## ## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1566,7 +1566,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 108. +## Ends in an error in state: 113. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1578,7 +1578,7 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 84. +## Ends in an error in state: 89. ## ## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1590,7 +1590,7 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 53. +## Ends in an error in state: 58. ## ## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1604,14 +1604,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 48, spurious reduction of production primitive_expression -> small_expression +## In state 53, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 54. +## Ends in an error in state: 59. ## ## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1623,7 +1623,7 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 48. +## Ends in an error in state: 53. ## ## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -1637,7 +1637,7 @@ expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL DIV INT_LITERAL YEAR ## -## Ends in an error in state: 26. +## Ends in an error in state: 31. ## ## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1649,7 +1649,7 @@ expected a delimiter to finish the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL DIV YEAR ## -## Ends in an error in state: 25. +## Ends in an error in state: 30. ## ## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1661,7 +1661,7 @@ expected the third component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL YEAR ## -## Ends in an error in state: 24. +## Ends in an error in state: 29. ## ## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1673,7 +1673,7 @@ expected a "/" source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV YEAR ## -## Ends in an error in state: 23. +## Ends in an error in state: 28. ## ## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1685,7 +1685,7 @@ expected the second component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL YEAR ## -## Ends in an error in state: 22. +## Ends in an error in state: 27. ## ## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1697,7 +1697,7 @@ expected a "/" source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL YEAR ## -## Ends in an error in state: 20. +## Ends in an error in state: 25. ## ## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1709,7 +1709,7 @@ expected the first component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION YEAR ## -## Ends in an error in state: 19. +## Ends in an error in state: 24. ## ## scope_use_condition -> UNDER_CONDITION . expression [ COLON ] ## @@ -1721,7 +1721,7 @@ expected an expression which will act as the condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 18. +## Ends in an error in state: 23. ## ## code_item -> SCOPE constructor . option(scope_use_condition) COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1733,7 +1733,7 @@ expected a scope use precondition or a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE YEAR ## -## Ends in an error in state: 16. +## Ends in an error in state: 21. ## ## code_item -> SCOPE . constructor option(scope_use_condition) COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1745,7 +1745,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 290. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1757,7 +1757,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 289. +## Ends in an error in state: 295. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1769,7 +1769,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 288. ## ## source_file_article -> law_article . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1781,9 +1781,9 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 277. +## Ends in an error in state: 283. ## -## source_file_after_text -> source_file_item . list(law_text) source_file_after_text [ # ] +## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## ## The known suffix of the stack is as follows: ## source_file_item @@ -1793,9 +1793,9 @@ expected some text, another heading or a law article source_file_or_master: MASTER_FILE LAW_INCLUDE YEAR ## -## Ends in an error in state: 5. +## Ends in an error in state: 7. ## -## master_file_includes -> master_file_include . master_file_includes [ # ] +## master_file_includes -> master_file_include . option(law_text) master_file_includes [ # ] ## ## The known suffix of the stack is as follows: ## master_file_include @@ -1808,7 +1808,7 @@ source_file_or_master: MASTER_FILE YEAR ## ## Ends in an error in state: 1. ## -## source_file_or_master -> MASTER_FILE . master_file_includes [ # ] +## source_file_or_master -> MASTER_FILE . option(law_text) master_file_includes [ # ] ## ## The known suffix of the stack is as follows: ## MASTER_FILE diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index f1d4a156..af3b1115 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -494,13 +494,13 @@ code: | code = list(code_item) { (code, $sloc) } metadata_block: -| BEGIN_CODE code_and_pos = code text = END_CODE END_METADATA { +| BEGIN_CODE option(law_text) code_and_pos = code text = END_CODE option(law_text) END_METADATA { let (code, pos) = code_and_pos in (code, (text, pos)) } law_article_item: -| text = LAW_TEXT { LawText text } +| text = law_text { LawText text } | BEGIN_CODE code_and_pos = code text = END_CODE { let (code, pos) = code_and_pos in CodeBlock (code, (text, pos)) @@ -530,7 +530,11 @@ law_articles_items: | { [] } law_text: -| text = LAW_TEXT { LawStructure (IntermediateText text) } +| text = LAW_TEXT { String.trim text } + +law_intermediate_text: +| text = law_text { LawStructure (IntermediateText text) } + source_file_article: | article = law_article items = law_articles_items { @@ -541,7 +545,7 @@ source_file_item: | heading = law_heading { LawStructure (LawHeading (heading, [])) } -| BEGIN_METADATA code = metadata_block { +| BEGIN_METADATA option(law_text) code = metadata_block { let (code, source_repr) = code in LawStructure (MetadataBlock (code, source_repr)) } @@ -550,13 +554,13 @@ source_file_after_text: | i = source_file_article f = source_file_after_text { i::f } -| i = source_file_item l = list(law_text) f = source_file_after_text { +| i = source_file_item l = list(law_intermediate_text) f = source_file_after_text { i::l@f } | EOF { [] } source_file: -| l = list(law_text) f = source_file_after_text { l@f } +| l = list(law_intermediate_text) f = source_file_after_text { l@f } master_file_include: | includ = LAW_INCLUDE { @@ -566,11 +570,11 @@ master_file_include: } master_file_includes: -| i = master_file_include is = master_file_includes { i::is } +| i = master_file_include option(law_text) is = master_file_includes { i::is } | EOF { [] } source_file_or_master: -| MASTER_FILE is = master_file_includes { MasterFile is } +| MASTER_FILE option(law_text) is = master_file_includes { MasterFile is } | f = source_file { (* now here the heading structure is completely flat because of the diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 7f475a19..f4d6dc7b 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -8,155 +8,155 @@ let message s = | 1 -> "expected an inclusion of a Catala file, since this file is a master file which can only \ contain inclusions of other Catala files\n" - | 5 -> + | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 277 -> "expected some text, another heading or a law article\n" - | 282 -> "expected a code block, a metadata block, more law text or a heading\n" - | 289 -> "expected a code block, a metadata block, more law text or a heading\n" - | 285 -> "expected a declaration or a scope use\n" - | 16 -> "expected the name of the scope you want to use\n" - | 18 -> "expected a scope use precondition or a colon\n" - | 19 -> "expected an expression which will act as the condition\n" - | 20 -> "expected the first component of the date literal\n" - | 22 -> "expected a \"/\"\n" - | 23 -> "expected the second component of the date literal\n" - | 24 -> "expected a \"/\"\n" - | 25 -> "expected the third component of the date literal\n" - | 26 -> "expected a delimiter to finish the date literal\n" - | 48 -> "expected an operator to compose the expression on the left with\n" - | 54 -> "expected an enum constructor to test if the expression on the left\n" + | 283 -> "expected some text, another heading or a law article\n" + | 288 -> "expected a code block, a metadata block, more law text or a heading\n" + | 295 -> "expected a code block, a metadata block, more law text or a heading\n" + | 290 -> "expected a declaration or a scope use\n" + | 21 -> "expected the name of the scope you want to use\n" + | 23 -> "expected a scope use precondition or a colon\n" + | 24 -> "expected an expression which will act as the condition\n" + | 25 -> "expected the first component of the date literal\n" + | 27 -> "expected a \"/\"\n" + | 28 -> "expected the second component of the date literal\n" + | 29 -> "expected a \"/\"\n" + | 30 -> "expected the third component of the date literal\n" + | 31 -> "expected a delimiter to finish the date literal\n" | 53 -> "expected an operator to compose the expression on the left with\n" - | 84 -> "expected an expression on the right side of the sum or minus operator\n" - | 108 -> "expected an expression on the right side of the logical operator\n" - | 56 -> "expected an expression for the argument of this function call\n" - | 80 -> "expected an expression on the right side of the comparison operator\n" - | 89 -> "expected an expression on the right side of the multiplication or division operator\n" - | 86 -> "expected an operator to compose the expression on the left\n" - | 135 -> "expected an expression standing for the set you want to test for membership\n" - | 49 -> "expected an identifier standing for a struct field or a subscope name\n" - | 159 -> "expected a colon after the scope use precondition\n" - | 51 -> "expected a constructor, to get the payload of this enum case\n" - | 92 -> "expected the \"for\" keyword to spell the aggregation\n" - | 93 -> "expected an identifier for the aggregation bound variable\n" - | 94 -> "expected the \"in\" keyword\n" - | 95 -> + | 59 -> "expected an enum constructor to test if the expression on the left\n" + | 58 -> "expected an operator to compose the expression on the left with\n" + | 89 -> "expected an expression on the right side of the sum or minus operator\n" + | 113 -> "expected an expression on the right side of the logical operator\n" + | 61 -> "expected an expression for the argument of this function call\n" + | 85 -> "expected an expression on the right side of the comparison operator\n" + | 94 -> "expected an expression on the right side of the multiplication or division operator\n" + | 91 -> "expected an operator to compose the expression on the left\n" + | 140 -> "expected an expression standing for the set you want to test for membership\n" + | 54 -> "expected an identifier standing for a struct field or a subscope name\n" + | 164 -> "expected a colon after the scope use precondition\n" + | 56 -> "expected a constructor, to get the payload of this enum case\n" + | 97 -> "expected the \"for\" keyword to spell the aggregation\n" + | 98 -> "expected an identifier for the aggregation bound variable\n" + | 99 -> "expected the \"in\" keyword\n" + | 100 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 97 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 98 -> "expected an expression to compute its aggregation over the set\n" - | 102 -> "expected an expression to take the negation of\n" - | 45 -> "expected an expression to take the opposite of\n" - | 34 -> "expected an expression to match with\n" - | 143 -> "expected a pattern matching case\n" - | 144 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 150 -> + | 102 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 103 -> "expected an expression to compute its aggregation over the set\n" + | 107 -> "expected an expression to take the negation of\n" + | 50 -> "expected an expression to take the opposite of\n" + | 39 -> "expected an expression to match with\n" + | 148 -> "expected a pattern matching case\n" + | 149 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 155 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 151 -> "expected an identifier for this enum case binding\n" - | 147 -> "expected a colon and then the expression for this matching case\n" - | 153 -> "expected a colon or a binding for the enum constructor payload\n" - | 148 -> "expected an expression for this pattern matching case\n" - | 145 -> + | 156 -> "expected an identifier for this enum case binding\n" + | 152 -> "expected a colon and then the expression for this matching case\n" + | 158 -> "expected a colon or a binding for the enum constructor payload\n" + | 153 -> "expected an expression for this pattern matching case\n" + | 150 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 142 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 35 -> "expected an expression inside the parenthesis\n" - | 128 -> "unmatched parenthesis that should have been closed by here\n" - | 57 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 37 -> "expected an expression for the test of the conditional\n" - | 138 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 139 -> + | 147 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 40 -> "expected an expression inside the parenthesis\n" + | 133 -> "unmatched parenthesis that should have been closed by here\n" + | 62 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 42 -> "expected an expression for the test of the conditional\n" + | 143 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 144 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 140 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 137 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 39 -> + | 145 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 142 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 44 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 114 -> "expected an identifier for the bound variable of the universal test\n" - | 115 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 116 -> "expected the expression designating the set on which to perform the universal test\n" - | 117 -> "expected the \"we have\" keyword for this universal test\n" - | 113 -> "expected an expression for the universal test\n" - | 122 -> "expected an identifier that will designate the existential witness for the test\n" - | 123 -> "expected the \"in\" keyword to continue this existential test\n" - | 124 -> "expected an expression that designates the set subject to the existential test\n" - | 125 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 126 -> "expected a keyword to complete the \"such that\" construction\n" - | 120 -> "expected an expression for the existential test\n" - | 64 -> + | 119 -> "expected an identifier for the bound variable of the universal test\n" + | 120 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 121 -> "expected the expression designating the set on which to perform the universal test\n" + | 122 -> "expected the \"we have\" keyword for this universal test\n" + | 118 -> "expected an expression for the universal test\n" + | 127 -> "expected an identifier that will designate the existential witness for the test\n" + | 128 -> "expected the \"in\" keyword to continue this existential test\n" + | 129 -> "expected an expression that designates the set subject to the existential test\n" + | 130 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 131 -> "expected a keyword to complete the \"such that\" construction\n" + | 125 -> "expected an expression for the existential test\n" + | 69 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 65 -> "expected an expression for the content of this enum case\n" - | 130 -> + | 70 -> "expected an expression for the content of this enum case\n" + | 135 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 66 -> "expected a struct field creation introduced by a dash\n" - | 67 -> "expected the name of field of the struct that you are building\n" - | 71 -> "expected a colon and then the expression for the field of the struct\n" - | 72 -> "expected an expression for the field of the struct\n" - | 68 -> "expected another field of the struct or the end of the struct literal\n" - | 69 -> "expected another field of the struct\n" - | 44 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 160 -> "expected a scope use item: a rule, definition or assertion\n" - | 161 -> "expected the name of the variable subject to the rule\n" - | 180 -> + | 71 -> "expected a struct field creation introduced by a dash\n" + | 72 -> "expected the name of field of the struct that you are building\n" + | 76 -> "expected a colon and then the expression for the field of the struct\n" + | 77 -> "expected an expression for the field of the struct\n" + | 73 -> "expected another field of the struct or the end of the struct literal\n" + | 74 -> "expected another field of the struct\n" + | 49 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 165 -> "expected a scope use item: a rule, definition or assertion\n" + | 166 -> "expected the name of the variable subject to the rule\n" + | 185 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 175 -> "expected a condition or a consequence for this rule\n" - | 166 -> "expected filled or not filled for a rule consequence\n" - | 176 -> "expected the name of the parameter for this dependent variable \n" - | 163 -> "expected the expression of the rule\n" - | 169 -> "expected the filled keyword the this rule \n" - | 181 -> "expected a struct field or a sub-scope context item after the dot\n" - | 183 -> "expected the name of the variable you want to define\n" - | 184 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 186 -> "expected an expression for the consequence of this definition under condition\n" - | 185 -> + | 180 -> "expected a condition or a consequence for this rule\n" + | 171 -> "expected filled or not filled for a rule consequence\n" + | 181 -> "expected the name of the parameter for this dependent variable \n" + | 168 -> "expected the expression of the rule\n" + | 174 -> "expected the filled keyword the this rule \n" + | 186 -> "expected a struct field or a sub-scope context item after the dot\n" + | 188 -> "expected the name of the variable you want to define\n" + | 189 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 191 -> "expected an expression for the consequence of this definition under condition\n" + | 190 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 187 -> "expected an expression for the definition\n" - | 190 -> "expected an expression that shoud be asserted during execution\n" - | 191 -> "expecting the name of the varying variable\n" - | 193 -> "the variable varies with an expression that was expected here\n" - | 194 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 192 -> "expected an indication about what this variable varies with\n" - | 164 -> "expected an expression for this condition\n" - | 172 -> "expected a consequence for this definition under condition\n" - | 203 -> "expected an expression for this definition under condition\n" - | 199 -> "expected the name of the variable that should be fixed\n" - | 200 -> "expected the legislative text by which the value of the variable is fixed\n" - | 201 -> "expected the legislative text by which the value of the variable is fixed\n" - | 207 -> "expected a new scope use item \n" - | 210 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 211 -> "expected the struct name\n" - | 212 -> "expected a colon\n" - | 213 -> "expected struct data or condition\n" - | 214 -> "expected the name of this struct data \n" - | 215 -> "expected the type of this struct data, introduced by the content keyword\n" - | 216 -> "expected the type of this struct data\n" - | 240 -> "expected the name of this struct condition\n" - | 233 -> "expected a new struct data, or another declaration or scope use\n" - | 234 -> "expected the type of the parameter of this struct data function\n" + | 192 -> "expected an expression for the definition\n" + | 195 -> "expected an expression that shoud be asserted during execution\n" + | 196 -> "expecting the name of the varying variable\n" + | 198 -> "the variable varies with an expression that was expected here\n" + | 199 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 197 -> "expected an indication about what this variable varies with\n" + | 169 -> "expected an expression for this condition\n" + | 177 -> "expected a consequence for this definition under condition\n" + | 208 -> "expected an expression for this definition under condition\n" + | 204 -> "expected the name of the variable that should be fixed\n" + | 205 -> "expected the legislative text by which the value of the variable is fixed\n" + | 206 -> "expected the legislative text by which the value of the variable is fixed\n" + | 212 -> "expected a new scope use item \n" + | 215 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 216 -> "expected the struct name\n" + | 217 -> "expected a colon\n" + | 218 -> "expected struct data or condition\n" + | 219 -> "expected the name of this struct data \n" + | 220 -> "expected the type of this struct data, introduced by the content keyword\n" + | 221 -> "expected the type of this struct data\n" + | 245 -> "expected the name of this struct condition\n" | 238 -> "expected a new struct data, or another declaration or scope use\n" - | 227 -> "expected a new struct data, or another declaration or scope use\n" - | 230 -> "expected a new struct data, or another declaration or scope use\n" - | 243 -> "expected the name of the scope you are declaring\n" - | 244 -> "expected a colon followed by the list of context items of this scope\n" - | 245 -> "expected a context item introduced by \"context\"\n" - | 246 -> "expected the name of this new context item\n" - | 247 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 248 -> "expected the name of the subscope for this context item\n" - | 255 -> "expected the next context item, or another declaration or scope use\n" - | 250 -> "expected the type of this context item\n" - | 251 -> "expected the next context item or a dependency declaration for this item\n" - | 253 -> "expected the next context item or a dependency declaration for this item\n" - | 258 -> "expected the name of your enum\n" - | 259 -> "expected a colon\n" - | 260 -> "expected an enum case\n" - | 261 -> "expected the name of an enum case \n" - | 262 -> "expected a payload for your enum case, or another case or declaration \n" - | 263 -> "expected a content type\n" - | 268 -> "expected another enum case, or a new declaration or scope use\n" - | 14 -> "expected a declaration or a scope use\n" - | 15 -> "expected a declaration or a scope use\n" - | 274 -> + | 239 -> "expected the type of the parameter of this struct data function\n" + | 243 -> "expected a new struct data, or another declaration or scope use\n" + | 232 -> "expected a new struct data, or another declaration or scope use\n" + | 235 -> "expected a new struct data, or another declaration or scope use\n" + | 248 -> "expected the name of the scope you are declaring\n" + | 249 -> "expected a colon followed by the list of context items of this scope\n" + | 250 -> "expected a context item introduced by \"context\"\n" + | 251 -> "expected the name of this new context item\n" + | 252 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 253 -> "expected the name of the subscope for this context item\n" + | 260 -> "expected the next context item, or another declaration or scope use\n" + | 255 -> "expected the type of this context item\n" + | 256 -> "expected the next context item or a dependency declaration for this item\n" + | 258 -> "expected the next context item or a dependency declaration for this item\n" + | 263 -> "expected the name of your enum\n" + | 264 -> "expected a colon\n" + | 265 -> "expected an enum case\n" + | 266 -> "expected the name of an enum case \n" + | 267 -> "expected a payload for your enum case, or another case or declaration \n" + | 268 -> "expected a content type\n" + | 273 -> "expected another enum case, or a new declaration or scope use\n" + | 17 -> "expected a declaration or a scope use\n" + | 19 -> "expected a declaration or a scope use\n" + | 279 -> "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" | _ -> raise Not_found diff --git a/src/catala/literate_programming/html.ml b/src/catala/literate_programming/html.ml index 8496df3e..74cc9bdb 100644 --- a/src/catala/literate_programming/html.ml +++ b/src/catala/literate_programming/html.ml @@ -23,7 +23,11 @@ module P = Printf module R = Re.Pcre module C = Cli -let pre_html (s : string) = s +let pre_html (s : string) = + let s = String.trim s in + let doublenewline = R.regexp "\n\n" in + let s = R.substitute ~rex:doublenewline ~subst:(fun _ -> "
\n") s in + s let raise_failed_pygments (command : string) (error_code : int) : 'a = Errors.raise_error @@ -126,7 +130,9 @@ type program_state = InsideArticle | OutsideArticle let law_article_item_to_html (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (i : A.law_article_item) : unit = match i with - | A.LawText t -> Format.fprintf fmt "

%s

" (pre_html t) + | A.LawText t -> + let t = pre_html t in + if t = "" then () else Format.fprintf fmt "

%s

" t | A.CodeBlock (_, c) -> let date = "\\d\\d/\\d\\d/\\d\\d\\d\\d" in let syms = R.regexp (date ^ "|!=|<=|>=|--|->|\\*|\\/") in @@ -175,7 +181,9 @@ let rec law_structure_to_html (custom_pygments : string option) (language : C.ba Format.fprintf fmt "\n" | A.MetadataBlock (b, c) -> law_article_item_to_html custom_pygments language fmt (A.CodeBlock (b, c)) - | A.IntermediateText t -> Format.fprintf fmt "

%s

" (pre_html t) + | A.IntermediateText t -> + let t = pre_html t in + if t = "" then () else Format.fprintf fmt "

%s

" t let program_item_to_html (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (i : A.program_item) : unit = diff --git a/src/catala/utils/pos.ml b/src/catala/utils/pos.ml index d0734fe1..a0d6470d 100644 --- a/src/catala/utils/pos.ml +++ b/src/catala/utils/pos.ml @@ -86,18 +86,18 @@ let retrieve_loc_text (pos : t) : string = if line_no = sline && line_no = eline then Cli.print_with_style error_indicator_style "%*s" (get_end_column pos - 1) - (String.make (get_end_column pos - get_start_column pos) '^') + (String.make (max (get_end_column pos - get_start_column pos) 0) '^') else if line_no = sline && line_no <> eline then Cli.print_with_style error_indicator_style "%*s" (String.length line - 1) - (String.make (String.length line - get_start_column pos) '^') + (String.make (max (String.length line - get_start_column pos) 0) '^') else if line_no <> sline && line_no <> eline then Cli.print_with_style error_indicator_style "%*s%s" line_indent "" - (String.make (String.length line - line_indent) '^') + (String.make (max (String.length line - line_indent) 0) '^') else if line_no <> sline && line_no = eline then Cli.print_with_style error_indicator_style "%*s%*s" line_indent "" (get_end_column pos - 1 - line_indent) - (String.make (get_end_column pos - line_indent) '^') + (String.make (max (get_end_column pos - line_indent) 0) '^') else assert false (* should not happen *) else "" in From 43829d65a6e25be40e181124aee306aab45dbde4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 3 Dec 2020 18:59:14 +0100 Subject: [PATCH 042/142] Added more tests --- examples/Makefile.common | 7 ++++ src/catala/desugared/dependency.ml | 2 +- tests/Makefile | 14 +++++++ tests/test_func/recursive.catala | 9 +++++ .../recursive.catala.RecursiveFunc.out | 6 +++ tests/test_scope/cycle_in_scope.catala | 15 ++++++++ tests/test_scope/cycle_in_scope.catala.A.out | 37 +++++++++++++++++++ tests/test_scope/cyclic_scopes.catala | 17 +++++++++ tests/test_scope/cyclic_scopes.catala.A.out | 6 +++ tests/test_scope/grand_parent_caller.catala | 18 ++++++--- .../grand_parent_caller.catala.A.out | 1 + .../grand_parent_caller.catala.B.out | 2 + .../grand_parent_caller.catala.C.out | 2 + tests/test_scope/sub_vars_in_sub_var.catala | 14 +++++++ .../sub_vars_in_sub_var.catala.A.out | 6 +++ 15 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 tests/test_func/recursive.catala create mode 100644 tests/test_func/recursive.catala.RecursiveFunc.out create mode 100644 tests/test_scope/cycle_in_scope.catala create mode 100644 tests/test_scope/cycle_in_scope.catala.A.out create mode 100644 tests/test_scope/cyclic_scopes.catala create mode 100644 tests/test_scope/cyclic_scopes.catala.A.out create mode 100644 tests/test_scope/grand_parent_caller.catala.A.out create mode 100644 tests/test_scope/grand_parent_caller.catala.B.out create mode 100644 tests/test_scope/grand_parent_caller.catala.C.out create mode 100644 tests/test_scope/sub_vars_in_sub_var.catala create mode 100644 tests/test_scope/sub_vars_in_sub_var.catala.A.out diff --git a/examples/Makefile.common b/examples/Makefile.common index 2a5e9cd7..e88c920c 100644 --- a/examples/Makefile.common +++ b/examples/Makefile.common @@ -28,6 +28,13 @@ endif # Targets ########################################## +%.run: %.catala_$(CATALA_LANG) $(CATALA_EXE) + $(CATALA) Makefile $< + $(CATALA) \ + Interpret \ + -s $(SCOPE) \ + $< + %.tex: %.catala_$(CATALA_LANG) $(CATALA_EXE) $(CATALA) Makefile $< $(CATALA) \ diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index de5ea02b..7c5eea1b 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -71,7 +71,7 @@ let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = if List.length sccs < ScopeDependencies.nb_vertex g then let scc = List.find (fun scc -> List.length scc > 1) sccs in Errors.raise_multispanned_error - (Format.asprintf "Cyclic dependency detected between variables of scope %a !" + (Format.asprintf "Cyclic dependency detected between variables of scope %a!" Scopelang.Ast.ScopeName.format_t scope.scope_uid) (List.flatten (List.map diff --git a/tests/Makefile b/tests/Makefile index aba286bf..877873a0 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -23,11 +23,19 @@ interpret_with_scope_and_compare =\ test_bool/test_bool.catala: $(call interpret_with_scope_and_compare,nv,TestBool) + +test_func/recursive.catala: + $(call interpret_with_scope_and_compare,nv,RecursiveFunc) test_func/func.catala: $(call interpret_with_scope_and_compare,nv,S) $(call interpret_with_scope_and_compare,nv,R) + +test_scope/cyclic_scopes.catala: + $(call interpret_with_scope_and_compare,nv,A) test_scope/scope.catala: $(call interpret_with_scope_and_compare,nv,A) +test_scope/cycle_in_scope.catala: + $(call interpret_with_scope_and_compare,nv,A) test_scope/sub_scope.catala: $(call interpret_with_scope_and_compare,nv,A) $(call interpret_with_scope_and_compare,nv,B) @@ -35,3 +43,9 @@ test_scope/sub_sub_scope.catala: $(call interpret_with_scope_and_compare,nv,A) $(call interpret_with_scope_and_compare,nv,B) $(call interpret_with_scope_and_compare,nv,C) +test_scope/grand_parent_caller.catala: + $(call interpret_with_scope_and_compare,nv,A) + $(call interpret_with_scope_and_compare,nv,B) + $(call interpret_with_scope_and_compare,nv,C) +test_scope/sub_vars_in_sub_var.catala: + $(call interpret_with_scope_and_compare,nv,A) \ No newline at end of file diff --git a/tests/test_func/recursive.catala b/tests/test_func/recursive.catala new file mode 100644 index 00000000..c522aa95 --- /dev/null +++ b/tests/test_func/recursive.catala @@ -0,0 +1,9 @@ +@ Article @ + +/* +new scope RecursiveFunc: + param f type int fun of int + +scope RecursiveFunc: + def f of x := f of x + 1 +*/ \ No newline at end of file diff --git a/tests/test_func/recursive.catala.RecursiveFunc.out b/tests/test_func/recursive.catala.RecursiveFunc.out new file mode 100644 index 00000000..e3ffc0b5 --- /dev/null +++ b/tests/test_func/recursive.catala.RecursiveFunc.out @@ -0,0 +1,6 @@ +[ERROR] The variable f is used in one of its definitions, but recursion is forbidden in Catala +[ERROR] +[ERROR] --> test_func/recursive.catala +[ERROR] | +[ERROR] 8 | def f of x := f of x + 1 +[ERROR] | ^ diff --git a/tests/test_scope/cycle_in_scope.catala b/tests/test_scope/cycle_in_scope.catala new file mode 100644 index 00000000..445b73fd --- /dev/null +++ b/tests/test_scope/cycle_in_scope.catala @@ -0,0 +1,15 @@ +@ Article @ + +/* +new scope A : + param x type int + param y type int + param z type int + +scope A: + def y [x < 0] := - x + def y [x >= 0] := x + def z [y >= 1] := 10 / y + def z [y < 1] := y + def x := z +*/ \ No newline at end of file diff --git a/tests/test_scope/cycle_in_scope.catala.A.out b/tests/test_scope/cycle_in_scope.catala.A.out new file mode 100644 index 00000000..a47e7e2f --- /dev/null +++ b/tests/test_scope/cycle_in_scope.catala.A.out @@ -0,0 +1,37 @@ +[ERROR] Cyclic dependency detected between variables of scope A! +[ERROR] +[ERROR] Cycle variable z, declared: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 7 | param z type int +[ERROR] | ^ +[ERROR] +[ERROR] Used here in the definition of another cycle variable x: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 14 | def x := z +[ERROR] | ^ +[ERROR] +[ERROR] Cycle variable y, declared: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 6 | param y type int +[ERROR] | ^ +[ERROR] +[ERROR] Used here in the definition of another cycle variable z: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 13 | def z [y < 1] := y +[ERROR] | ^ +[ERROR] +[ERROR] Cycle variable x, declared: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 5 | param x type int +[ERROR] | ^ +[ERROR] +[ERROR] Used here in the definition of another cycle variable y: +[ERROR] --> test_scope/cycle_in_scope.catala +[ERROR] | +[ERROR] 11 | def y [x >= 0] := x +[ERROR] | ^ diff --git a/tests/test_scope/cyclic_scopes.catala b/tests/test_scope/cyclic_scopes.catala new file mode 100644 index 00000000..e33d61d2 --- /dev/null +++ b/tests/test_scope/cyclic_scopes.catala @@ -0,0 +1,17 @@ +@ Article @ + +/* +new scope A: + param b scope B + param x type int + +new scope B: + param a scope A + param y type int + +scope A: + def x := b.y + +scope B: + def y := a.x +*/ \ No newline at end of file diff --git a/tests/test_scope/cyclic_scopes.catala.A.out b/tests/test_scope/cyclic_scopes.catala.A.out new file mode 100644 index 00000000..8c73feb4 --- /dev/null +++ b/tests/test_scope/cyclic_scopes.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] B: unknown identifier for a scope +[ERROR] +[ERROR] --> test_scope/cyclic_scopes.catala +[ERROR] | +[ERROR] 5 | param b scope B +[ERROR] | ^ diff --git a/tests/test_scope/grand_parent_caller.catala b/tests/test_scope/grand_parent_caller.catala index c9b2cdf9..16da5e70 100644 --- a/tests/test_scope/grand_parent_caller.catala +++ b/tests/test_scope/grand_parent_caller.catala @@ -1,24 +1,30 @@ +@ Article @ + /* new scope A: param x type int new scope B: param a scope A - param y type int + param y1 type int + param y2 type int new scope C: param b scope B - param z type int + param z1 type int + param z2 type int scope A: def x := 0 scope B: - def a.x := y - def y := 1 + def a.x := y1 + def y1 := 1 + def y2 := a.x scope C: - def b.y := z - def z = 2 + def b.y1 := z1 + def z1 := 2 + def z2 := b.y2 */ \ No newline at end of file diff --git a/tests/test_scope/grand_parent_caller.catala.A.out b/tests/test_scope/grand_parent_caller.catala.A.out new file mode 100644 index 00000000..6cc0064e --- /dev/null +++ b/tests/test_scope/grand_parent_caller.catala.A.out @@ -0,0 +1 @@ +[RESULT] x -> 0 diff --git a/tests/test_scope/grand_parent_caller.catala.B.out b/tests/test_scope/grand_parent_caller.catala.B.out new file mode 100644 index 00000000..b1eb98a7 --- /dev/null +++ b/tests/test_scope/grand_parent_caller.catala.B.out @@ -0,0 +1,2 @@ +[RESULT] y1 -> 1 +[RESULT] y2 -> 1 diff --git a/tests/test_scope/grand_parent_caller.catala.C.out b/tests/test_scope/grand_parent_caller.catala.C.out new file mode 100644 index 00000000..cfc18223 --- /dev/null +++ b/tests/test_scope/grand_parent_caller.catala.C.out @@ -0,0 +1,2 @@ +[RESULT] z1 -> 2 +[RESULT] z2 -> 2 diff --git a/tests/test_scope/sub_vars_in_sub_var.catala b/tests/test_scope/sub_vars_in_sub_var.catala new file mode 100644 index 00000000..5a59fad2 --- /dev/null +++ b/tests/test_scope/sub_vars_in_sub_var.catala @@ -0,0 +1,14 @@ +@ Article @ + +/* +new scope A: + param x type bool + param y type int + +new scope B: + param a scope A + +scope B: + def a.x := true + def a.y := if a.x then 0 else 1 +*/ \ No newline at end of file diff --git a/tests/test_scope/sub_vars_in_sub_var.catala.A.out b/tests/test_scope/sub_vars_in_sub_var.catala.A.out new file mode 100644 index 00000000..3caac729 --- /dev/null +++ b/tests/test_scope/sub_vars_in_sub_var.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] The subscope a is used when defining one of its inputs, but recursion is forbidden in Catala +[ERROR] +[ERROR] --> test_scope/sub_vars_in_sub_var.catala +[ERROR] | +[ERROR] 13 | def a.y := if a.x then 0 else 1 +[ERROR] | ^^^ From 42a42fe10c777094578b9d3f21e431ae40cafee0 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 3 Dec 2020 20:11:41 +0100 Subject: [PATCH 043/142] Added sum types to default calculus --- src/catala/default_calculus/ast.ml | 3 + src/catala/default_calculus/interpreter.ml | 22 +++ src/catala/default_calculus/print.ml | 12 ++ src/catala/default_calculus/typing.ml | 204 +++++++++++++-------- 4 files changed, 166 insertions(+), 75 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 78723864..ea743955 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -19,6 +19,7 @@ type typ = | TUnit | TInt | TTuple of typ Pos.marked list + | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked type lit = LBool of bool | LEmptyError | LInt of Int64.t | LUnit @@ -33,6 +34,8 @@ type expr = | EVar of expr Bindlib.var Pos.marked | ETuple of expr Pos.marked list | ETupleAccess of expr Pos.marked * int + | EInj of expr Pos.marked * int * typ Pos.marked list + | EMatch of expr Pos.marked * expr Pos.marked list | ELit of lit | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 8fe7cfd8..4bdf7652 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -104,6 +104,28 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = if the term was well-typed)" n) (Pos.get_position e1) ) + | EInj (e1, n, ts) -> + let e1' = evaluate_expr e1 in + Pos.same_pos_as (A.EInj (e1', n, ts)) e + | EMatch (e1, es) -> ( + let e1 = evaluate_expr e1 in + match Pos.unmark e1 with + | A.EInj (e1, n, _) -> + let es_n = + match List.nth_opt es n with + | Some es_n -> es_n + | None -> + Errors.raise_spanned_error + "sum type index error (should not happend if the term was well-typed)" + (Pos.get_position e) + in + let new_e = Pos.same_pos_as (A.EApp (es_n, [ e1 ])) e in + evaluate_expr new_e + | _ -> + Errors.raise_spanned_error + "Expected a term having a sum type as an argument to a match (should not happend if \ + the term was well-typed" + (Pos.get_position e1) ) | EDefault (just, cons, subs) -> ( let just = evaluate_expr just in match Pos.unmark just with diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index ae24c768..b2ad2e6f 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -31,6 +31,10 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) ts + | TEnum ts -> + Format.fprintf fmt "(%a)" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " +@ ") format_typ) + ts | TArrow (t1, t2) -> Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 @@ -78,6 +82,14 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") format_expr) es | ETupleAccess (e1, n) -> Format.fprintf fmt "%a.%d" format_expr e1 n + | EInj (e, n, ts) -> + Format.fprintf fmt "inj[%a].%d %a" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) + ts n format_expr e + | EMatch (e, es) -> + Format.fprintf fmt "@[match %a with %a@]" format_expr e + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " |@ ") format_expr) + es | ELit l -> Format.fprintf fmt "%a" format_lit (Pos.same_pos_as l e) | EApp ((EAbs (_, binder, taus), _), args) -> let xs, body = Bindlib.unmbind binder in diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 359900a1..81eee658 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -26,6 +26,7 @@ type typ = | TBool | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem | TTuple of typ Pos.marked UnionFind.elem list + | TEnum of typ Pos.marked UnionFind.elem list | TAny let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = @@ -39,6 +40,10 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " * ") format_typ) ts + | TEnum ts -> + Format.fprintf fmt "(%a)" + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " + ") format_typ) + ts | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = @@ -51,6 +56,7 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin unify t11 t21; unify t12 t22 | (TTuple ts1, _), (TTuple ts2, _) -> List.iter2 unify ts1 ts2 + | (TEnum ts1, _), (TEnum ts2, _) -> List.iter2 unify ts1 ts2 | (TAny, _), (TAny, _) -> ignore (UnionFind.union t1 t2) | (TAny, _), t_repr | t_repr, (TAny, _) -> let t_union = UnionFind.union t1 t2 in @@ -90,6 +96,7 @@ let rec ast_to_typ (ty : A.typ) : typ = ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), UnionFind.make (Pos.map_under_mark ast_to_typ t2) ) | A.TTuple ts -> TTuple (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) + | A.TEnum ts -> TEnum (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = Pos.map_under_mark @@ -99,6 +106,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = | TBool -> A.TBool | TInt -> A.TInt | TTuple ts -> A.TTuple (List.map typ_to_ast ts) + | TEnum ts -> A.TEnum (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) | TAny -> A.TUnit) (UnionFind.get (UnionFind.find ty)) @@ -107,86 +115,106 @@ type env = typ Pos.marked A.VarMap.t let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem = - (* Cli.debug_print (Format.asprintf "Up begin: %a" Print.format_expr e); *) - let out = - match Pos.unmark e with - | EVar v -> ( - match A.VarMap.find_opt (Pos.unmark v) env with - | Some t -> UnionFind.make t - | None -> - Errors.raise_spanned_error "Variable not found in the current context" - (Pos.get_position e) ) - | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) - | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) - | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) - | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) - | ETuple es -> - let ts = List.map (typecheck_expr_bottom_up env) es in - UnionFind.make (Pos.same_pos_as (TTuple ts) e) - | ETupleAccess (e1, n) -> ( - let t1 = typecheck_expr_bottom_up env e1 in - match Pos.unmark (UnionFind.get (UnionFind.find t1)) with - | TTuple ts -> ( - match List.nth_opt ts n with - | Some t' -> t' - | None -> - Errors.raise_spanned_error - (Format.asprintf - "expression should have a tuple type with at least %d elements but only has %d" - n (List.length ts)) - (Pos.get_position e1) ) - | _ -> - Errors.raise_spanned_error - (Format.asprintf "exprected a tuple, got a %a" format_typ t1) - (Pos.get_position e1) ) - | EAbs (pos_binder, binder, taus) -> - let xs, body = Bindlib.unmbind binder in - if Array.length xs = List.length taus then - let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - let env = - List.fold_left - (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) - env xstaus - in - List.fold_right - (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> - UnionFind.make - (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) - taus - (typecheck_expr_bottom_up env body) - else + match Pos.unmark e with + | EVar v -> ( + match A.VarMap.find_opt (Pos.unmark v) env with + | Some t -> UnionFind.make t + | None -> + Errors.raise_spanned_error "Variable not found in the current context" + (Pos.get_position e) ) + | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) + | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) + | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) + | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) + | ETuple es -> + let ts = List.map (typecheck_expr_bottom_up env) es in + UnionFind.make (Pos.same_pos_as (TTuple ts) e) + | ETupleAccess (e1, n) -> ( + let t1 = typecheck_expr_bottom_up env e1 in + match Pos.unmark (UnionFind.get (UnionFind.find t1)) with + | TTuple ts -> ( + match List.nth_opt ts n with + | Some t' -> t' + | None -> + Errors.raise_spanned_error + (Format.asprintf + "Expression should have a tuple type with at least %d elements but only has %d" n + (List.length ts)) + (Pos.get_position e1) ) + | _ -> Errors.raise_spanned_error - (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) - (List.length taus)) - pos_binder - | EApp (e1, args) -> - let t_args = List.map (typecheck_expr_bottom_up env) args in - let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in - let t_app = - List.fold_right - (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) - t_args t_ret + (Format.asprintf "Expected a tuple, got a %a" format_typ t1) + (Pos.get_position e1) ) + | EInj (e1, n, ts) -> + let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in + let ts_n = + match List.nth_opt ts n with + | Some ts_n -> ts_n + | None -> + Errors.raise_spanned_error + (Format.asprintf + "Expression should have a sum type with at least %d cases but only has %d" n + (List.length ts)) + (Pos.get_position e) + in + typecheck_expr_top_down env e1 ts_n; + UnionFind.make (Pos.same_pos_as (TEnum ts) e) + | EMatch (e1, es) -> + let enum_cases = List.map (fun e' -> UnionFind.make (Pos.same_pos_as TAny e')) es in + let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in + typecheck_expr_top_down env e1 t_e1; + let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + List.iteri + (fun i es' -> + let enum_t = List.nth enum_cases i in + let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in + typecheck_expr_top_down env es' t_es') + es; + t_ret + | EAbs (pos_binder, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + if Array.length xs = List.length taus then + let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let env = + List.fold_left + (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) + env xstaus in - typecheck_expr_top_down env e1 t_app; - t_ret - | EOp op -> op_type (Pos.same_pos_as op e) - | EDefault (just, cons, subs) -> - typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); - let tcons = typecheck_expr_bottom_up env cons in - List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; - tcons - | EIfThenElse (cond, et, ef) -> - typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); - let tt = typecheck_expr_bottom_up env et in - typecheck_expr_top_down env ef tt; - tt - in - (* Cli.debug_print (Format.asprintf "Up result: %a | %a" Print.format_expr e format_typ out); *) - out + List.fold_right + (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> + UnionFind.make + (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) + taus + (typecheck_expr_bottom_up env body) + else + Errors.raise_spanned_error + (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) + (List.length taus)) + pos_binder + | EApp (e1, args) -> + let t_args = List.map (typecheck_expr_bottom_up env) args in + let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + let t_app = + List.fold_right + (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + t_args t_ret + in + typecheck_expr_top_down env e1 t_app; + t_ret + | EOp op -> op_type (Pos.same_pos_as op e) + | EDefault (just, cons, subs) -> + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + let tcons = typecheck_expr_bottom_up env cons in + List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; + tcons + | EIfThenElse (cond, et, ef) -> + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + let tt = typecheck_expr_bottom_up env et in + typecheck_expr_top_down env ef tt; + tt and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = - (* Cli.debug_print (Format.asprintf "Down: %a | %a" Print.format_expr e format_typ tau); *) match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt (Pos.unmark v) env with @@ -222,6 +250,32 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) Errors.raise_spanned_error (Format.asprintf "exprected a tuple , got %a" format_typ tau) (Pos.get_position e) ) + | EInj (e1, n, ts) -> + let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in + let ts_n = + match List.nth_opt ts n with + | Some ts_n -> ts_n + | None -> + Errors.raise_spanned_error + (Format.asprintf + "Expression should have a sum type with at least %d cases but only has %d" n + (List.length ts)) + (Pos.get_position e) + in + typecheck_expr_top_down env e1 ts_n; + unify (UnionFind.make (Pos.same_pos_as (TEnum ts) e)) tau + | EMatch (e1, es) -> + let enum_cases = List.map (fun e' -> UnionFind.make (Pos.same_pos_as TAny e')) es in + let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in + typecheck_expr_top_down env e1 t_e1; + let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + List.iteri + (fun i es' -> + let enum_t = List.nth enum_cases i in + let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in + typecheck_expr_top_down env es' t_es') + es; + unify tau t_ret | EAbs (pos_binder, binder, t_args) -> let xs, body = Bindlib.unmbind binder in if Array.length xs = List.length t_args then From 77b4fdf3127fa0d096aa4cb6e5b4772e85510ef9 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 3 Dec 2020 21:02:28 +0100 Subject: [PATCH 044/142] Starting to add structs and enums to scope language --- src/catala/desugared/ast.ml | 13 +++-- src/catala/scope_language/ast.ml | 62 ++++++++++++++++++--- src/catala/scope_language/print.ml | 4 ++ src/catala/scope_language/scope_to_dcalc.ml | 4 ++ 4 files changed, 70 insertions(+), 13 deletions(-) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index f091861d..039fb25d 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -103,23 +103,24 @@ let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang. type program = scope Scopelang.Ast.ScopeMap.t let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t = - let add_locs (acc : Pos.t ScopeDefMap.t) (locs : Scopelang.Ast.location Pos.marked list) : + let add_locs (acc : Pos.t ScopeDefMap.t) (locs : Scopelang.Ast.LocationSet.t) : Pos.t ScopeDefMap.t = - List.fold_left - (fun acc (loc, loc_pos) -> + Scopelang.Ast.LocationSet.fold + (fun (loc, loc_pos) acc -> ScopeDefMap.add ( match loc with | Scopelang.Ast.ScopeVar v -> ScopeDef.Var (Pos.unmark v) | Scopelang.Ast.SubScopeVar (_, sub_index, sub_var) -> ScopeDef.SubScopeVar (Pos.unmark sub_index, Pos.unmark sub_var) ) loc_pos acc) - acc locs + locs acc in RuleMap.fold (fun _ rule acc -> let locs = - Scopelang.Ast.locations_used (Bindlib.unbox rule.just) - @ Scopelang.Ast.locations_used (Bindlib.unbox rule.cons) + Scopelang.Ast.LocationSet.union + (Scopelang.Ast.locations_used (Bindlib.unbox rule.just)) + (Scopelang.Ast.locations_used (Bindlib.unbox rule.cons)) in add_locs acc locs) def ScopeDefMap.empty diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index a6f000b9..0e89898b 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -30,13 +30,47 @@ module ScopeVar = Uid.Make (Uid.MarkedString) () module ScopeVarSet = Set.Make (ScopeVar) module ScopeVarMap = Map.Make (ScopeVar) +module StructName = Uid.Make (Uid.MarkedString) () + +module StructMap = Map.Make (StructName) + +module StructFieldName = Uid.Make (Uid.MarkedString) () + +module StructFieldMap = Map.Make (StructFieldName) + +module EnumName = Uid.Make (Uid.MarkedString) () + +module EnumMap = Map.Make (EnumName) + +module EnumConstructor = Uid.Make (Uid.MarkedString) () + +module EnumConstructorMap = Map.Make (EnumConstructor) + type location = | ScopeVar of ScopeVar.t Pos.marked | SubScopeVar of ScopeName.t * SubScopeName.t Pos.marked * ScopeVar.t Pos.marked +module LocationSet = Set.Make (struct + type t = location Pos.marked + + let compare x y = + match (Pos.unmark x, Pos.unmark y) with + | ScopeVar (vx, _), ScopeVar (vy, _) -> ScopeVar.compare vx vy + | SubScopeVar (_, (xsubindex, _), (xsubvar, _)), SubScopeVar (_, (ysubindex, _), (ysubvar, _)) + -> + let c = SubScopeName.compare xsubindex ysubindex in + if c = 0 then ScopeVar.compare xsubvar ysubvar else c + | ScopeVar _, SubScopeVar _ -> -1 + | SubScopeVar _, ScopeVar _ -> 1 +end) + type expr = | ELocation of location | EVar of expr Bindlib.var Pos.marked + | EStruct of StructName.t * expr Pos.marked StructFieldMap.t + | EStructAccess of expr Pos.marked * StructFieldName.t * StructName.t + | EEnumInj of expr Pos.marked * EnumConstructor.t * EnumName.t + | EMatch of expr Pos.marked * EnumName.t * expr Pos.marked EnumConstructorMap.t | ELit of Dcalc.Ast.lit | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list @@ -44,20 +78,34 @@ type expr = | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked -let rec locations_used (e : expr Pos.marked) : location Pos.marked list = +let rec locations_used (e : expr Pos.marked) : LocationSet.t = match Pos.unmark e with - | ELocation l -> [ (l, Pos.get_position e) ] - | EVar _ | ELit _ | EOp _ -> [] + | ELocation l -> LocationSet.singleton (l, Pos.get_position e) + | EVar _ | ELit _ | EOp _ -> LocationSet.empty | EAbs (_, binder, _) -> let _, body = Bindlib.unmbind binder in locations_used body + | EStruct (_, es) -> + StructFieldMap.fold + (fun _ e' acc -> LocationSet.union acc (locations_used e')) + es LocationSet.empty + | EStructAccess (e1, _, _) -> locations_used e1 + | EEnumInj (e1, _, _) -> locations_used e1 + | EMatch (e1, _, es) -> + EnumConstructorMap.fold + (fun _ e' acc -> LocationSet.union acc (locations_used e')) + es (locations_used e1) | EApp (e1, args) -> - List.fold_left (fun acc arg -> locations_used arg @ acc) (locations_used e1) args - | EIfThenElse (e1, e2, e3) -> locations_used e1 @ locations_used e2 @ locations_used e3 + List.fold_left + (fun acc arg -> LocationSet.union (locations_used arg) acc) + (locations_used e1) args + | EIfThenElse (e1, e2, e3) -> + LocationSet.union (locations_used e1) + (LocationSet.union (locations_used e2) (locations_used e3)) | EDefault (just, cons, subs) -> List.fold_left - (fun acc sub -> locations_used sub @ acc) - (locations_used just @ locations_used cons) + (fun acc sub -> LocationSet.union (locations_used sub) acc) + (LocationSet.union (locations_used just) (locations_used cons)) subs module Var = struct diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 08d9d3d8..a0c4f2f5 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -37,6 +37,10 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | ELocation l -> Format.fprintf fmt "%a" format_location l | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ELit l -> Format.fprintf fmt "%a" Dcalc.Print.format_lit (Pos.same_pos_as l e) + | EStruct (_, _) -> assert false + | EStructAccess (_, _, _) -> assert false + | EEnumInj (_, _, _) -> assert false + | EMatch (_, _, _) -> assert false | EApp ((EAbs (_, binder, taus), _), args) -> let xs, body = Bindlib.unmbind binder in let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index d9276379..3fdf6b0b 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -62,6 +62,10 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po ( match Pos.unmark e with | EVar v -> Bindlib.box_var (Ast.VarMap.find (Pos.unmark v) ctx.local_vars) | ELit l -> Bindlib.box (Dcalc.Ast.ELit l) + | EStruct (_, _) -> assert false + | EStructAccess (_, _, _) -> assert false + | EEnumInj (_, _, _) -> assert false + | EMatch (_, _, _) -> assert false | EApp (e1, args) -> Bindlib.box_apply2 (fun e u -> Dcalc.Ast.EApp (e, u)) From b170b043f1c4b3be6884115f77c494958de1dfc6 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 3 Dec 2020 21:29:22 +0100 Subject: [PATCH 045/142] Print structs and enums in scopelang --- src/catala/scope_language/print.ml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index a0c4f2f5..558b909a 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -37,10 +37,26 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | ELocation l -> Format.fprintf fmt "%a" format_location l | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ELit l -> Format.fprintf fmt "%a" Dcalc.Print.format_lit (Pos.same_pos_as l e) - | EStruct (_, _) -> assert false - | EStructAccess (_, _, _) -> assert false - | EEnumInj (_, _, _) -> assert false - | EMatch (_, _, _) -> assert false + | EStruct (name, fields) -> + Format.fprintf fmt "@[%a @[{@ %a@ }@]@]" Ast.StructName.format_t name + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ") + (fun fmt (field_name, field_expr) -> + Format.fprintf fmt "%a = %a" Ast.StructFieldName.format_t field_name format_expr + field_expr)) + (Ast.StructFieldMap.bindings fields) + | EStructAccess (e1, field, _) -> + Format.fprintf fmt "%a.%a" format_expr e1 Ast.StructFieldName.format_t field + | EEnumInj (e1, cons, _) -> + Format.fprintf fmt "%a@ %a" Ast.EnumConstructor.format_t cons format_expr e1 + | EMatch (e1, _, cases) -> + Format.fprintf fmt "@[@[match@ %a@ with@]@ %a@]" format_expr e1 + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ |@ ") + (fun fmt (cons_name, case_expr) -> + Format.fprintf fmt "@[%a@ →@ %a@]" Ast.EnumConstructor.format_t cons_name + format_expr case_expr)) + (Ast.EnumConstructorMap.bindings cases) | EApp ((EAbs (_, binder, taus), _), args) -> let xs, body = Bindlib.unmbind binder in let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in From c4192a219f829db4d18798aaa33bb791ef9596d1 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 4 Dec 2020 14:41:20 +0100 Subject: [PATCH 046/142] Added translation scope -> dcalc in presence of ctx --- src/catala/scope_language/scope_to_dcalc.ml | 116 ++++++++++++++++++-- 1 file changed, 107 insertions(+), 9 deletions(-) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 3fdf6b0b..c8bbdaa0 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -18,15 +18,23 @@ module Cli = Utils.Cli type scope_sigs_ctx = ((Ast.ScopeVar.t * Dcalc.Ast.typ) list * Dcalc.Ast.Var.t) Ast.ScopeMap.t +type struct_ctx = (Ast.StructFieldName.t * Dcalc.Ast.typ Pos.marked) list Ast.StructMap.t + +type enum_ctx = (Ast.EnumConstructor.t * Dcalc.Ast.typ Pos.marked) list Ast.EnumMap.t + type ctx = { + structs : struct_ctx; + enums : enum_ctx; scopes_parameters : scope_sigs_ctx; scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; local_vars : Dcalc.Ast.Var.t Ast.VarMap.t; } -let empty_ctx (scopes_ctx : scope_sigs_ctx) = +let empty_ctx (struct_ctx : struct_ctx) (enum_ctx : enum_ctx) (scopes_ctx : scope_sigs_ctx) = { + structs = struct_ctx; + enums = enum_ctx; scopes_parameters = scopes_ctx; scope_vars = Ast.ScopeVarMap.empty; subscope_vars = Ast.SubScopeMap.empty; @@ -62,10 +70,98 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po ( match Pos.unmark e with | EVar v -> Bindlib.box_var (Ast.VarMap.find (Pos.unmark v) ctx.local_vars) | ELit l -> Bindlib.box (Dcalc.Ast.ELit l) - | EStruct (_, _) -> assert false - | EStructAccess (_, _, _) -> assert false - | EEnumInj (_, _, _) -> assert false - | EMatch (_, _, _) -> assert false + | EStruct (struct_name, e_fields) -> + let struct_sig = Ast.StructMap.find struct_name ctx.structs in + let d_fields, remaining_e_fields = + List.fold_right + (fun (field_name, _) (d_fields, e_fields) -> + let field_e = + Option.value + ~default: + (Errors.raise_spanned_error + (Format.asprintf "The field %a does not belong to the structure %a" + Ast.StructFieldName.format_t field_name Ast.StructName.format_t + struct_name) + (Pos.get_position e)) + (Ast.StructFieldMap.find_opt field_name e_fields) + in + let field_d = translate_expr ctx field_e in + (field_d :: d_fields, Ast.StructFieldMap.remove field_name e_fields)) + struct_sig ([], e_fields) + in + if Ast.StructFieldMap.cardinal remaining_e_fields > 0 then + Errors.raise_spanned_error + (Format.asprintf "Missing fields for structure %a: %a" Ast.StructName.format_t + struct_name + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") + (fun fmt (field_name, _) -> + Format.fprintf fmt "%a" Ast.StructFieldName.format_t field_name)) + (Ast.StructFieldMap.bindings remaining_e_fields)) + (Pos.get_position e) + else + Bindlib.box_apply (fun d_fields -> Dcalc.Ast.ETuple d_fields) (Bindlib.box_list d_fields) + | EStructAccess (e1, field_name, struct_name) -> + let struct_sig = Ast.StructMap.find struct_name ctx.structs in + let _, field_index = + Option.value + ~default: + (Errors.raise_spanned_error + (Format.asprintf "The field %a does not belong to the structure %a" + Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) + (Pos.get_position e)) + (List.assoc_opt field_name (List.mapi (fun i (x, y) -> (x, (y, i))) struct_sig)) + in + let e1 = translate_expr ctx e1 in + Bindlib.box_apply (fun e1 -> Dcalc.Ast.ETupleAccess (e1, field_index)) e1 + | EEnumInj (e1, constructor, enum_name) -> + let enum_sig = Ast.EnumMap.find enum_name ctx.enums in + let _, constructor_index = + Option.value + ~default: + (Errors.raise_spanned_error + (Format.asprintf "The constructor %a does not belong to the enum %a" + Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) + (Pos.get_position e)) + (List.assoc_opt constructor (List.mapi (fun i (x, y) -> (x, (y, i))) enum_sig)) + in + let e1 = translate_expr ctx e1 in + Bindlib.box_apply + (fun e1 -> Dcalc.Ast.EInj (e1, constructor_index, List.map snd enum_sig)) + e1 + | EMatch (e1, enum_name, cases) -> + let enum_sig = Ast.EnumMap.find enum_name ctx.enums in + let d_cases, remaining_e_cases = + List.fold_right + (fun (constructor, _) (d_cases, e_cases) -> + let case_e = + Option.value + ~default: + (Errors.raise_spanned_error + (Format.asprintf "The constructor %a does not belong to the enum %a" + Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) + (Pos.get_position e)) + (Ast.EnumConstructorMap.find_opt constructor e_cases) + in + let case_d = translate_expr ctx case_e in + (case_d :: d_cases, Ast.EnumConstructorMap.remove constructor e_cases)) + enum_sig ([], cases) + in + if Ast.EnumConstructorMap.cardinal remaining_e_cases > 0 then + Errors.raise_spanned_error + (Format.asprintf "Patter matching is incomplete for enum %a: missing cases %a" + Ast.EnumName.format_t enum_name + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") + (fun fmt (case_name, _) -> + Format.fprintf fmt "%a" Ast.EnumConstructor.format_t case_name)) + (Ast.EnumConstructorMap.bindings remaining_e_cases)) + (Pos.get_position e) + else + let e1 = translate_expr ctx e1 in + Bindlib.box_apply2 + (fun d_fields e1 -> Dcalc.Ast.EMatch (e1, d_fields)) + (Bindlib.box_list d_cases) e1 | EApp (e1, args) -> Bindlib.box_apply2 (fun e u -> Dcalc.Ast.EApp (e, u)) @@ -263,9 +359,9 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : (return_exp, ctx) | hd :: tl -> translate_rule ctx hd tl pos_sigma -let translate_scope_decl (sctx : scope_sigs_ctx) (sigma : Ast.scope_decl) : - Dcalc.Ast.expr Pos.marked Bindlib.box = - let ctx = empty_ctx sctx in +let translate_scope_decl (struct_ctx : struct_ctx) (enum_ctx : enum_ctx) (sctx : scope_sigs_ctx) + (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = + let ctx = empty_ctx struct_ctx enum_ctx sctx in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in let rules, ctx = translate_rules ctx sigma.scope_decl_rules pos_sigma in let scope_variables, _ = Ast.ScopeMap.find sigma.scope_decl_name sctx in @@ -308,6 +404,8 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName scope_dvar )) prgm in + let struct_ctx = assert false in + let enum_ctx = assert false in (* the final expression on which we build on is the variable of the top-level scope that we are returning *) let acc = Dcalc.Ast.make_var (snd (Ast.ScopeMap.find top_level_scope_name sctx), Pos.no_pos) in @@ -319,7 +417,7 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> let scope = Ast.ScopeMap.find scope_name prgm in let pos_scope = Pos.get_position (Ast.ScopeName.get_info scope.scope_decl_name) in - let scope_expr = translate_scope_decl sctx scope in + let scope_expr = translate_scope_decl struct_ctx enum_ctx sctx scope in let scope_sig, dvar = Ast.ScopeMap.find scope_name sctx in let scope_typ = build_scope_typ_from_sig scope_sig pos_scope in Dcalc.Ast.make_let_in dvar scope_typ scope_expr acc) From 7e674fa69dd30b00a27740d52a2928808c1c0b56 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 4 Dec 2020 15:14:29 +0100 Subject: [PATCH 047/142] Tabs to spaces --- tests/test_bool/test_bool.catala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_bool/test_bool.catala b/tests/test_bool/test_bool.catala index 4d7e6edf..0ce58f64 100644 --- a/tests/test_bool/test_bool.catala +++ b/tests/test_bool/test_bool.catala @@ -2,8 +2,8 @@ /* new scope TestBool : - param foo type bool - param bar type int + param foo type bool + param bar type int scope TestBool : def bar := 1 From b5af8d175e20fb8544e94cb831e73b94adffdebb Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 4 Dec 2020 16:40:17 +0100 Subject: [PATCH 048/142] Enum and struct context to fill in name resolution --- src/catala/catala_surface/desugaring.ml | 31 +++++++++++++++----- src/catala/catala_surface/name_resolution.ml | 17 +++++++++++ src/catala/desugared/ast.ml | 6 +++- src/catala/desugared/desugared_to_scope.ml | 6 +++- src/catala/scope_language/ast.ml | 10 ++++++- src/catala/scope_language/dependency.ml | 4 +-- src/catala/scope_language/scope_to_dcalc.ml | 24 +++++++-------- 7 files changed, 72 insertions(+), 26 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index d17e7a9d..7b009a00 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -195,7 +195,7 @@ let add_var_to_def_idmap (ctxt : Name_resolution.context) (scope_uid : Scopelang let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (def : Ast.definition) : Desugared.Ast.program = - let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm in + let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm.program_scopes in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in let default_pos = Pos.get_position def.definition_expr in let def_key = @@ -246,7 +246,10 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) scope_defs = Desugared.Ast.ScopeDefMap.add def_key (x_def, x_type) scope.scope_defs; } in - Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm + { + prgm with + program_scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm.program_scopes; + } (** Process a rule from the surface language *) let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) @@ -285,19 +288,33 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.pro in (* Make sure the scope exists *) let prgm = - match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm with + match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm.program_scopes with | Some _ -> prgm | None -> - Scopelang.Ast.ScopeMap.add scope_uid - (Desugared.Ast.empty_scope scope_uid scope_vars scope_ctxt.sub_scopes) - prgm + { + prgm with + program_scopes = + Scopelang.Ast.ScopeMap.add scope_uid + (Desugared.Ast.empty_scope scope_uid scope_vars scope_ctxt.sub_scopes) + prgm.program_scopes; + } in let precond = use.scope_use_condition in List.fold_left (process_scope_use_item precond scope_uid ctxt) prgm use.scope_use_items (** Scopes processing *) let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desugared.Ast.program = - let empty_prgm = Scopelang.Ast.ScopeMap.empty in + let empty_prgm = + { + Desugared.Ast.program_structs = + Scopelang.Ast.StructMap.map Scopelang.Ast.StructFieldMap.bindings + ctxt.Name_resolution.structs; + Desugared.Ast.program_enums = + Scopelang.Ast.EnumMap.map Scopelang.Ast.EnumConstructorMap.bindings + ctxt.Name_resolution.enums; + Desugared.Ast.program_scopes = Scopelang.Ast.ScopeMap.empty; + } + in let processer_article_item (prgm : Desugared.Ast.program) (item : Ast.law_article_item) : Desugared.Ast.program = match item with diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 5d22cebd..0da4a800 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -35,9 +35,20 @@ type scope_context = { } (** Inside a scope, we distinguish between the variables and the subscopes. *) +type struct_context = typ Pos.marked Scopelang.Ast.StructFieldMap.t + +type enum_context = typ Pos.marked Scopelang.Ast.EnumConstructorMap.t + type context = { scope_idmap : Scopelang.Ast.ScopeName.t Desugared.Ast.IdentMap.t; scopes : scope_context Scopelang.Ast.ScopeMap.t; + structs : struct_context Scopelang.Ast.StructMap.t; + struct_idmap : Scopelang.Ast.StructName.t Desugared.Ast.IdentMap.t; + field_idmap : Scopelang.Ast.StructFieldName.t Scopelang.Ast.StructMap.t Desugared.Ast.IdentMap.t; + enums : enum_context Scopelang.Ast.EnumMap.t; + enum_idmap : Scopelang.Ast.EnumName.t Desugared.Ast.IdentMap.t; + constructor_idmap : + Scopelang.Ast.EnumConstructor.t Scopelang.Ast.EnumMap.t Desugared.Ast.IdentMap.t; var_typs : typ Pos.marked Scopelang.Ast.ScopeVarMap.t; } @@ -274,6 +285,12 @@ let form_context (prgm : Ast.program) : context = scope_idmap = Desugared.Ast.IdentMap.empty; scopes = Scopelang.Ast.ScopeMap.empty; var_typs = Scopelang.Ast.ScopeVarMap.empty; + structs = Scopelang.Ast.StructMap.empty; + struct_idmap = Desugared.Ast.IdentMap.empty; + field_idmap = Desugared.Ast.IdentMap.empty; + enums = Scopelang.Ast.EnumMap.empty; + enum_idmap = Desugared.Ast.IdentMap.empty; + constructor_idmap = Desugared.Ast.IdentMap.empty; } in let ctxt = diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 039fb25d..6542ca7a 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -100,7 +100,11 @@ let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang. scope_meta_assertions = []; } -type program = scope Scopelang.Ast.ScopeMap.t +type program = { + program_scopes : scope Scopelang.Ast.ScopeMap.t; + program_enums : Scopelang.Ast.enum_ctx; + program_structs : Scopelang.Ast.struct_ctx; +} let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t = let add_locs (acc : Pos.t ScopeDefMap.t) (locs : Scopelang.Ast.LocationSet.t) : diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 0cb846da..a297722a 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -216,4 +216,8 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = } let translate_program (pgrm : Ast.program) : Scopelang.Ast.program = - Scopelang.Ast.ScopeMap.map translate_scope pgrm + { + Scopelang.Ast.program_scopes = Scopelang.Ast.ScopeMap.map translate_scope pgrm.program_scopes; + Scopelang.Ast.program_structs = pgrm.program_structs; + Scopelang.Ast.program_enums = pgrm.program_enums; + } diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 0e89898b..34c37dfb 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -144,4 +144,12 @@ type scope_decl = { scope_decl_rules : rule list; } -type program = scope_decl ScopeMap.t +type struct_ctx = (StructFieldName.t * Dcalc.Ast.typ Pos.marked) list StructMap.t + +type enum_ctx = (EnumConstructor.t * Dcalc.Ast.typ Pos.marked) list EnumMap.t + +type program = { + program_scopes : scope_decl ScopeMap.t; + program_enums : enum_ctx; + program_structs : struct_ctx; +} diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index ba598cb2..8568ee00 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -47,7 +47,7 @@ module SCC = Graph.Components.Make (Dependencies) let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = let g = Dependencies.empty in - let g = Ast.ScopeMap.fold (fun v _ g -> Dependencies.add_vertex g v) prgm g in + let g = Ast.ScopeMap.fold (fun v _ g -> Dependencies.add_vertex g v) prgm.program_scopes g in Ast.ScopeMap.fold (fun scope_name scope g -> let subscopes = @@ -72,7 +72,7 @@ let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = let edge = Dependencies.E.create subscope pos scope_name in Dependencies.add_edge_e g edge) subscopes g) - prgm g + prgm.program_scopes g let check_for_cycle (g : Dependencies.t) : unit = (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index c8bbdaa0..fe078cb9 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -18,20 +18,17 @@ module Cli = Utils.Cli type scope_sigs_ctx = ((Ast.ScopeVar.t * Dcalc.Ast.typ) list * Dcalc.Ast.Var.t) Ast.ScopeMap.t -type struct_ctx = (Ast.StructFieldName.t * Dcalc.Ast.typ Pos.marked) list Ast.StructMap.t - -type enum_ctx = (Ast.EnumConstructor.t * Dcalc.Ast.typ Pos.marked) list Ast.EnumMap.t - type ctx = { - structs : struct_ctx; - enums : enum_ctx; + structs : Ast.struct_ctx; + enums : Ast.enum_ctx; scopes_parameters : scope_sigs_ctx; scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; local_vars : Dcalc.Ast.Var.t Ast.VarMap.t; } -let empty_ctx (struct_ctx : struct_ctx) (enum_ctx : enum_ctx) (scopes_ctx : scope_sigs_ctx) = +let empty_ctx (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) (scopes_ctx : scope_sigs_ctx) + = { structs = struct_ctx; enums = enum_ctx; @@ -64,7 +61,6 @@ let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Pos.marked Bindlib.box = - (* Cli.debug_print (Format.asprintf "Translating: %a" Print.format_expr e); *) Bindlib.box_apply (fun (x : Dcalc.Ast.expr) -> Pos.same_pos_as x e) ( match Pos.unmark e with @@ -359,8 +355,8 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : (return_exp, ctx) | hd :: tl -> translate_rule ctx hd tl pos_sigma -let translate_scope_decl (struct_ctx : struct_ctx) (enum_ctx : enum_ctx) (sctx : scope_sigs_ctx) - (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = +let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) + (sctx : scope_sigs_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = let ctx = empty_ctx struct_ctx enum_ctx sctx in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in let rules, ctx = translate_rules ctx sigma.scope_decl_rules pos_sigma in @@ -402,10 +398,10 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName (fun (scope_var, tau) -> (scope_var, Pos.unmark tau)) (Ast.ScopeVarMap.bindings scope.scope_sig), scope_dvar )) - prgm + prgm.program_scopes in - let struct_ctx = assert false in - let enum_ctx = assert false in + let struct_ctx = prgm.program_structs in + let enum_ctx = prgm.program_enums in (* the final expression on which we build on is the variable of the top-level scope that we are returning *) let acc = Dcalc.Ast.make_var (snd (Ast.ScopeMap.find top_level_scope_name sctx), Pos.no_pos) in @@ -415,7 +411,7 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName (let acc = List.fold_right (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> - let scope = Ast.ScopeMap.find scope_name prgm in + let scope = Ast.ScopeMap.find scope_name prgm.program_scopes in let pos_scope = Pos.get_position (Ast.ScopeName.get_info scope.scope_decl_name) in let scope_expr = translate_scope_decl struct_ctx enum_ctx sctx scope in let scope_sig, dvar = Ast.ScopeMap.find scope_name sctx in From 0f853909efd750e479e8fb4f62f2627bbd5b4c95 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 4 Dec 2020 18:02:49 +0100 Subject: [PATCH 049/142] Implemented name resolution --- src/catala/catala_surface/lexer.ml | 2 +- src/catala/catala_surface/name_resolution.ml | 93 +++++++++++++++++++- tests/Makefile | 5 +- tests/test_struct/simple.catala | 16 ++++ 4 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 tests/test_struct/simple.catala diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index d7367d9e..dd416a60 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -206,7 +206,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "type" -> update_acc lexbuf; CONTENT - | "structure" -> + | "struct" -> update_acc lexbuf; STRUCT | "option" -> diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 0da4a800..95706d27 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -239,16 +239,105 @@ let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = | _ -> raise_unsupported_feature "unsupported item" (Pos.get_position use_item)) ctxt use.scope_use_items -(** Process a code item : for now it only handles scope decls *) let process_use_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = match Pos.unmark item with | ScopeDecl _ -> ctxt | ScopeUse use -> process_scope_use ctxt use | _ -> raise_unsupported_feature "item not supported" (Pos.get_position item) +let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = + let s_uid = Scopelang.Ast.StructName.fresh sdecl.struct_decl_name in + let ctxt = + { + ctxt with + struct_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark sdecl.struct_decl_name) s_uid ctxt.struct_idmap; + } + in + List.fold_left + (fun ctxt (fdecl, _) -> + let f_uid = Scopelang.Ast.StructFieldName.fresh fdecl.Ast.struct_decl_field_name in + let ctxt = + { + ctxt with + field_idmap = + Desugared.Ast.IdentMap.update + (Pos.unmark fdecl.Ast.struct_decl_field_name) + (fun uids -> + match uids with + | None -> Some (Scopelang.Ast.StructMap.singleton s_uid f_uid) + | Some uids -> Some (Scopelang.Ast.StructMap.add s_uid f_uid uids)) + ctxt.field_idmap; + } + in + { + ctxt with + structs = + Scopelang.Ast.StructMap.update s_uid + (fun fields -> + match fields with + | None -> + Some + (Scopelang.Ast.StructFieldMap.singleton f_uid + (process_type fdecl.Ast.struct_decl_field_typ)) + | Some fields -> + Some + (Scopelang.Ast.StructFieldMap.add f_uid + (process_type fdecl.Ast.struct_decl_field_typ) + fields)) + ctxt.structs; + }) + ctxt sdecl.struct_decl_fields + +let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = + let e_uid = Scopelang.Ast.EnumName.fresh edecl.enum_decl_name in + let ctxt = + { + ctxt with + enum_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark edecl.enum_decl_name) e_uid ctxt.enum_idmap; + } + in + List.fold_left + (fun ctxt (cdecl, cdecl_pos) -> + let c_uid = Scopelang.Ast.EnumConstructor.fresh cdecl.Ast.enum_decl_case_name in + let ctxt = + { + ctxt with + constructor_idmap = + Desugared.Ast.IdentMap.update + (Pos.unmark cdecl.Ast.enum_decl_case_name) + (fun uids -> + match uids with + | None -> Some (Scopelang.Ast.EnumMap.singleton e_uid c_uid) + | Some uids -> Some (Scopelang.Ast.EnumMap.add e_uid c_uid uids)) + ctxt.constructor_idmap; + } + in + { + ctxt with + enums = + Scopelang.Ast.EnumMap.update e_uid + (fun cases -> + let typ = + match cdecl.Ast.enum_decl_case_typ with + | None -> (Dcalc.Ast.TUnit, cdecl_pos) + | Some typ -> process_type typ + in + match cases with + | None -> Some (Scopelang.Ast.EnumConstructorMap.singleton c_uid typ) + | Some fields -> Some (Scopelang.Ast.EnumConstructorMap.add c_uid typ fields)) + ctxt.enums; + }) + ctxt edecl.enum_decl_cases + (** Process a code item : for now it only handles scope decls *) let process_decl_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = - match Pos.unmark item with ScopeDecl decl -> process_scope_decl ctxt decl | _ -> ctxt + match Pos.unmark item with + | ScopeDecl decl -> process_scope_decl ctxt decl + | StructDecl sdecl -> process_struct_decl ctxt sdecl + | EnumDecl edecl -> process_enum_decl ctxt edecl + | ScopeUse _ -> ctxt (** Process a code block *) let process_code_block (ctxt : context) (block : Ast.code_block) diff --git a/tests/Makefile b/tests/Makefile index 877873a0..52375180 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -48,4 +48,7 @@ test_scope/grand_parent_caller.catala: $(call interpret_with_scope_and_compare,nv,B) $(call interpret_with_scope_and_compare,nv,C) test_scope/sub_vars_in_sub_var.catala: - $(call interpret_with_scope_and_compare,nv,A) \ No newline at end of file + $(call interpret_with_scope_and_compare,nv,A) + +test_struct/simple.catala: + $(call interpret_with_scope,nv,A) \ No newline at end of file diff --git a/tests/test_struct/simple.catala b/tests/test_struct/simple.catala new file mode 100644 index 00000000..2a8efcb5 --- /dev/null +++ b/tests/test_struct/simple.catala @@ -0,0 +1,16 @@ +@Article@ + +/* +new struct S: + data x type int + data y type int + +new scope A: + param s type S + param z type int + +scope A: + def s.x := 1 + def s.y := 2 + def z := s.x + s.y +*/ \ No newline at end of file From ef5dd18bc7842040b9c6219147d97fdce55386ca Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 4 Dec 2020 18:48:16 +0100 Subject: [PATCH 050/142] Introduce intermediate typ structure with named structs and enums --- src/catala/catala_surface/desugaring.ml | 4 +- src/catala/catala_surface/name_resolution.ml | 51 +++++++++++--------- src/catala/desugared/ast.ml | 6 +-- src/catala/desugared/desugared_to_scope.ml | 6 +-- src/catala/scope_language/ast.ml | 20 +++++--- src/catala/scope_language/print.ml | 22 +++++++-- src/catala/scope_language/scope_to_dcalc.ml | 33 +++++++++++-- 7 files changed, 98 insertions(+), 44 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 7b009a00..a75d2506 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -145,8 +145,8 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop parameter = (let def_key_typ = Name_resolution.get_def_typ ctxt def_key in match (Pos.unmark def_key_typ, param_uid) with - | Dcalc.Ast.TArrow (t_in, _), Some param_uid -> Some (Pos.unmark param_uid, t_in) - | Dcalc.Ast.TArrow _, None -> + | Scopelang.Ast.TArrow (t_in, _), Some param_uid -> Some (Pos.unmark param_uid, t_in) + | Scopelang.Ast.TArrow _, None -> Errors.raise_spanned_error "this definition has a function type but the parameter is missing" (Pos.get_position (Bindlib.unbox cons)) diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 95706d27..e6b44b2f 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -20,7 +20,7 @@ module Errors = Utils.Errors type ident = string -type typ = Dcalc.Ast.typ +type typ = Scopelang.Ast.typ type def_context = { var_idmap : Scopelang.Ast.Var.t Desugared.Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern @@ -95,30 +95,41 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } -let process_base_typ ((typ, typ_pos) : Ast.base_typ Pos.marked) : Dcalc.Ast.typ Pos.marked = +let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : + Scopelang.Ast.typ Pos.marked = match typ with - | Ast.Condition -> (Dcalc.Ast.TBool, typ_pos) + | Ast.Condition -> (Scopelang.Ast.TBool, typ_pos) | Ast.Data (Ast.Collection _) -> raise_unsupported_feature "collection type" typ_pos | Ast.Data (Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos | Ast.Data (Ast.Primitive prim) -> ( match prim with - | Ast.Integer -> (Dcalc.Ast.TInt, typ_pos) + | Ast.Integer -> (Scopelang.Ast.TInt, typ_pos) | Ast.Decimal | Ast.Money | Ast.Date -> raise_unsupported_feature "value type" typ_pos - | Ast.Boolean -> (Dcalc.Ast.TBool, typ_pos) + | Ast.Boolean -> (Scopelang.Ast.TBool, typ_pos) | Ast.Text -> raise_unsupported_feature "text type" typ_pos - | Ast.Named _ -> raise_unsupported_feature "struct or enum types" typ_pos ) + | Ast.Named ident -> ( + match Desugared.Ast.IdentMap.find_opt ident ctxt.struct_idmap with + | Some s_uid -> (Scopelang.Ast.TStruct s_uid, typ_pos) + | None -> ( + match Desugared.Ast.IdentMap.find_opt ident ctxt.enum_idmap with + | Some e_uid -> (Scopelang.Ast.TEnum e_uid, typ_pos) + | None -> + Errors.raise_spanned_error + "Unknown type, not a struct or enum previously declared" typ_pos ) ) ) -let process_type ((typ, typ_pos) : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = +let process_type (ctxt : context) ((typ, typ_pos) : Ast.typ Pos.marked) : + Scopelang.Ast.typ Pos.marked = match typ with - | Ast.Base base_typ -> process_base_typ (base_typ, typ_pos) + | Ast.Base base_typ -> process_base_typ ctxt (base_typ, typ_pos) | Ast.Func { arg_typ; return_typ } -> - (Dcalc.Ast.TArrow (process_base_typ arg_typ, process_base_typ return_typ), typ_pos) + ( Scopelang.Ast.TArrow (process_base_typ ctxt arg_typ, process_base_typ ctxt return_typ), + typ_pos ) (** Process data declaration *) let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Ast.scope_decl_context_data) : context = (* First check the type of the context data *) - let data_typ = process_type decl.scope_decl_context_item_typ in + let data_typ = process_type ctxt decl.scope_decl_context_item_typ in let name, pos = decl.scope_decl_context_item_name in let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in match Desugared.Ast.IdentMap.find_opt name scope_ctxt.var_idmap with @@ -203,17 +214,14 @@ let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with | None -> raise_unknown_identifier "for a var of the scope" x | Some id -> Desugared.Ast.ScopeDef.Var id ) - | [ s; x ] -> ( - let sub_scope_uid = - match Desugared.Ast.IdentMap.find_opt (Pos.unmark s) scope_ctxt.sub_scopes_idmap with - | None -> raise_unknown_identifier "for a subscope of this scope" s - | Some id -> id - in + | [ s; x ] when Desugared.Ast.IdentMap.mem (Pos.unmark s) scope_ctxt.sub_scopes_idmap -> ( + let sub_scope_uid = Desugared.Ast.IdentMap.find (Pos.unmark s) scope_ctxt.sub_scopes_idmap in let real_sub_scope_uid = Scopelang.Ast.SubScopeMap.find sub_scope_uid scope_ctxt.sub_scopes in let sub_scope_ctx = Scopelang.Ast.ScopeMap.find real_sub_scope_uid ctxt.scopes in match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with | None -> raise_unknown_identifier "for a var of this subscope" x | Some id -> Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) + | [ s; _ ] -> raise_unsupported_feature "not a subscope" (Pos.get_position s) | _ -> raise_unsupported_feature "wrong qident" (Pos.get_position id) let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = @@ -241,9 +249,8 @@ let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = let process_use_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = match Pos.unmark item with - | ScopeDecl _ -> ctxt + | ScopeDecl _ | StructDecl _ | EnumDecl _ -> ctxt | ScopeUse use -> process_scope_use ctxt use - | _ -> raise_unsupported_feature "item not supported" (Pos.get_position item) let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = let s_uid = Scopelang.Ast.StructName.fresh sdecl.struct_decl_name in @@ -279,11 +286,11 @@ let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = | None -> Some (Scopelang.Ast.StructFieldMap.singleton f_uid - (process_type fdecl.Ast.struct_decl_field_typ)) + (process_type ctxt fdecl.Ast.struct_decl_field_typ)) | Some fields -> Some (Scopelang.Ast.StructFieldMap.add f_uid - (process_type fdecl.Ast.struct_decl_field_typ) + (process_type ctxt fdecl.Ast.struct_decl_field_typ) fields)) ctxt.structs; }) @@ -321,8 +328,8 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = (fun cases -> let typ = match cdecl.Ast.enum_decl_case_typ with - | None -> (Dcalc.Ast.TUnit, cdecl_pos) - | Some typ -> process_type typ + | None -> (Scopelang.Ast.TUnit, cdecl_pos) + | Some typ -> process_type ctxt typ in match cases with | None -> Some (Scopelang.Ast.EnumConstructorMap.singleton c_uid typ) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 6542ca7a..03c21b85 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -55,11 +55,11 @@ module ScopeDefSet = Set.Make (ScopeDef) type rule = { just : Scopelang.Ast.expr Pos.marked Bindlib.box; cons : Scopelang.Ast.expr Pos.marked Bindlib.box; - parameter : (Scopelang.Ast.Var.t * Dcalc.Ast.typ Pos.marked) option; + parameter : (Scopelang.Ast.Var.t * Scopelang.Ast.typ Pos.marked) option; parent_rule : RuleName.t option; } -let empty_rule (pos : Pos.t) (have_parameter : Dcalc.Ast.typ Pos.marked option) : rule = +let empty_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked option) : rule = { just = Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); cons = Bindlib.box (Scopelang.Ast.ELit Dcalc.Ast.LEmptyError, pos); @@ -84,7 +84,7 @@ type scope = { scope_vars : Scopelang.Ast.ScopeVarSet.t; scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; scope_uid : Scopelang.Ast.ScopeName.t; - scope_defs : (rule RuleMap.t * Dcalc.Ast.typ Pos.marked) ScopeDefMap.t; + scope_defs : (rule RuleMap.t * Scopelang.Ast.typ Pos.marked) ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index a297722a..abcc3440 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -90,7 +90,7 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked let is_func _ (r : Ast.rule) : bool = Option.is_some r.Ast.parameter in let all_rules_func = Ast.RuleMap.for_all is_func def in let all_rules_not_func = Ast.RuleMap.for_all (fun n r -> not (is_func n r)) def in - let is_def_func : Dcalc.Ast.typ Pos.marked option = + let is_def_func : Scopelang.Ast.typ Pos.marked option = if all_rules_func then let typ = (snd (Ast.RuleMap.choose def)).Ast.parameter in match typ with @@ -99,12 +99,12 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked if Ast.RuleMap.for_all is_typ def then Some typ else Errors.raise_multispanned_error - "the type of these parameters should be the same, but they \n are different" + "the type of these parameters should be the same, but they are different" (List.map (fun (_, r) -> ( Some (Format.asprintf "The type of the parameter of this expression is %a" - Dcalc.Print.format_typ typ), + Scopelang.Print.format_typ typ), Pos.get_position (Bindlib.unbox r.Ast.cons) )) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_typ n r)) def))) | None -> assert false (* should not happen *) diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 34c37dfb..5a8c45c0 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -64,6 +64,14 @@ module LocationSet = Set.Make (struct | SubScopeVar _, ScopeVar _ -> 1 end) +type typ = + | TBool + | TUnit + | TInt + | TStruct of StructName.t + | TEnum of EnumName.t + | TArrow of typ Pos.marked * typ Pos.marked + type expr = | ELocation of location | EVar of expr Bindlib.var Pos.marked @@ -72,7 +80,7 @@ type expr = | EEnumInj of expr Pos.marked * EnumConstructor.t * EnumName.t | EMatch of expr Pos.marked * EnumName.t * expr Pos.marked EnumConstructorMap.t | ELit of Dcalc.Ast.lit - | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * Dcalc.Ast.typ Pos.marked list + | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of Dcalc.Ast.operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list @@ -125,7 +133,7 @@ let make_var ((x, pos) : Var.t Pos.marked) : expr Pos.marked Bindlib.box = Bindlib.box_apply (fun v -> (v, pos)) (Bindlib.box_var x) let make_abs (xs : vars) (e : expr Pos.marked Bindlib.box) (pos_binder : Pos.t) - (taus : Dcalc.Ast.typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = + (taus : typ Pos.marked list) (pos : Pos.t) : expr Pos.marked Bindlib.box = Bindlib.box_apply (fun b -> (EAbs (pos_binder, b, taus), pos)) (Bindlib.bind_mvar xs e) let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box list) (pos : Pos.t) @@ -135,18 +143,18 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box module VarMap = Map.Make (Var) type rule = - | Definition of location Pos.marked * Dcalc.Ast.typ Pos.marked * expr Pos.marked + | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked | Call of ScopeName.t * SubScopeName.t type scope_decl = { scope_decl_name : ScopeName.t; - scope_sig : Dcalc.Ast.typ Pos.marked ScopeVarMap.t; + scope_sig : typ Pos.marked ScopeVarMap.t; scope_decl_rules : rule list; } -type struct_ctx = (StructFieldName.t * Dcalc.Ast.typ Pos.marked) list StructMap.t +type struct_ctx = (StructFieldName.t * typ Pos.marked) list StructMap.t -type enum_ctx = (EnumConstructor.t * Dcalc.Ast.typ Pos.marked) list EnumMap.t +type enum_ctx = (EnumConstructor.t * typ Pos.marked) list EnumMap.t type program = { program_scopes : scope_decl ScopeMap.t; diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 558b909a..6b4d2bed 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -28,6 +28,23 @@ let format_location (fmt : Format.formatter) (l : location) : unit = Format.fprintf fmt "%a.%a" SubScopeName.format_t (Pos.unmark subindex) ScopeVar.format_t (Pos.unmark subvar) +let typ_needs_parens (e : typ Pos.marked) : bool = + match Pos.unmark e with TArrow _ -> true | _ -> false + +let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = + let format_typ_with_parens (fmt : Format.formatter) (t : typ Pos.marked) = + if typ_needs_parens t then Format.fprintf fmt "(%a)" format_typ t + else Format.fprintf fmt "%a" format_typ t + in + match Pos.unmark typ with + | TUnit -> Format.fprintf fmt "unit" + | TBool -> Format.fprintf fmt "bool" + | TInt -> Format.fprintf fmt "int" + | TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s + | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e + | TArrow (t1, t2) -> + Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 + let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = if needs_parens e then Format.fprintf fmt "(%a)" format_expr e @@ -66,7 +83,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") (fun fmt (x, tau, arg) -> Format.fprintf fmt "@[@[let@ %a@ :@ %a@ =@ %a@]@ in@\n@]" format_var x - Dcalc.Print.format_typ tau format_expr arg)) + format_typ tau format_expr arg)) xs_tau_arg format_expr body | EAbs (_, binder, taus) -> let xs, body = Bindlib.unmbind binder in @@ -74,8 +91,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = Format.fprintf fmt "@[λ@ %a@ →@ %a@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") - (fun fmt (x, tau) -> - Format.fprintf fmt "@[(%a:@ %a)@]" format_var x Dcalc.Print.format_typ tau)) + (fun fmt (x, tau) -> Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau)) xs_tau format_expr body | EApp ((EOp (Binop op), _), [ arg1; arg2 ]) -> Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 Dcalc.Print.format_binop diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index fe078cb9..355f7710 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -42,6 +42,21 @@ type scope_ctx = Dcalc.Ast.Var.t Ast.ScopeMap.t let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("·", Pos.no_pos) +let rec translate_typ (ctx : ctx) (t : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = + Pos.same_pos_as + ( match Pos.unmark t with + | Ast.TUnit -> Dcalc.Ast.TUnit + | Ast.TBool -> Dcalc.Ast.TBool + | Ast.TInt -> Dcalc.Ast.TInt + | Ast.TArrow (t1, t2) -> Dcalc.Ast.TArrow (translate_typ ctx t1, translate_typ ctx t2) + | Ast.TStruct s_uid -> + let s_fields = Ast.StructMap.find s_uid ctx.structs in + Dcalc.Ast.TTuple (List.map (fun (_, t) -> translate_typ ctx t) s_fields) + | Ast.TEnum e_uid -> + let e_cases = Ast.EnumMap.find e_uid ctx.enums in + Dcalc.Ast.TEnum (List.map (fun (_, t) -> translate_typ ctx t) e_cases) ) + t + let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) (callee : Dcalc.Ast.expr Pos.marked Bindlib.box) : Dcalc.Ast.expr Pos.marked Bindlib.box = let caller = @@ -123,7 +138,9 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po in let e1 = translate_expr ctx e1 in Bindlib.box_apply - (fun e1 -> Dcalc.Ast.EInj (e1, constructor_index, List.map snd enum_sig)) + (fun e1 -> + Dcalc.Ast.EInj + (e1, constructor_index, List.map (fun (_, t) -> translate_typ ctx t) enum_sig)) e1 | EMatch (e1, enum_name, cases) -> let enum_sig = Ast.EnumMap.find enum_name ctx.enums in @@ -179,7 +196,9 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po body in let binder = Bindlib.bind_mvar new_xs body in - Bindlib.box_apply (fun b -> Dcalc.Ast.EAbs (pos_binder, b, typ)) binder + Bindlib.box_apply + (fun b -> Dcalc.Ast.EAbs (pos_binder, b, List.map (translate_typ ctx) typ)) + binder | EDefault (just, cons, subs) -> Bindlib.box_apply3 (fun j c s -> Dcalc.Ast.EDefault (j, c, s)) @@ -213,6 +232,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos | Definition ((ScopeVar a, var_def_pos), tau, e) -> let a_name = Ast.ScopeVar.get_info (Pos.unmark a) in let a_var = Dcalc.Ast.Var.make a_name in + let tau = translate_typ ctx tau in let new_ctx = { ctx with @@ -232,6 +252,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos (Ast.SubScopeName.get_info (Pos.unmark subs_index)) in let a_var = (Dcalc.Ast.Var.make a_name, var_def_pos) in + let tau = translate_typ ctx tau in let new_ctx = { ctx with @@ -390,18 +411,20 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let scope_dependencies = Dependency.build_program_dep_graph prgm in Dependency.check_for_cycle scope_dependencies; let scope_ordering = Dependency.get_scope_ordering scope_dependencies in + let struct_ctx = prgm.program_structs in + let enum_ctx = prgm.program_enums in let sctx : scope_sigs_ctx = Ast.ScopeMap.map (fun scope -> let scope_dvar = Dcalc.Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name) in ( List.map - (fun (scope_var, tau) -> (scope_var, Pos.unmark tau)) + (fun (scope_var, tau) -> + let tau = translate_typ (empty_ctx struct_ctx enum_ctx Ast.ScopeMap.empty) tau in + (scope_var, Pos.unmark tau)) (Ast.ScopeVarMap.bindings scope.scope_sig), scope_dvar )) prgm.program_scopes in - let struct_ctx = prgm.program_structs in - let enum_ctx = prgm.program_enums in (* the final expression on which we build on is the variable of the top-level scope that we are returning *) let acc = Dcalc.Ast.make_var (snd (Ast.ScopeMap.find top_level_scope_name sctx), Pos.no_pos) in From 70aa8ae2c1cca687f51db28d192b629aea43b217 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sat, 5 Dec 2020 17:27:08 +0100 Subject: [PATCH 051/142] Simple struct test passing --- src/catala/catala_surface/ast.ml | 1 + src/catala/catala_surface/desugaring.ml | 59 ++++++++++++++++++-- src/catala/catala_surface/lexer.ml | 8 +++ src/catala/catala_surface/lexer_en.ml | 6 ++ src/catala/catala_surface/lexer_fr.ml | 6 ++ src/catala/catala_surface/name_resolution.ml | 16 ++++-- src/catala/catala_surface/parser.mly | 6 +- src/catala/scope_language/scope_to_dcalc.ml | 40 ++++++------- tests/Makefile | 4 +- tests/test_struct/simple.catala | 6 +- 10 files changed, 115 insertions(+), 37 deletions(-) diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 446c7ea6..9900508e 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -109,6 +109,7 @@ and expression = | Literal of literal | EnumInject of constructor Pos.marked * expression Pos.marked option | EnumProject of expression Pos.marked * constructor Pos.marked + | StructLit of constructor Pos.marked * (ident Pos.marked * expression Pos.marked) list | Ident of ident | Dotted of expression Pos.marked * ident Pos.marked (* Dotted is for both struct field projection and sub-scope variables *) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index a75d2506..e19d6882 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -36,6 +36,8 @@ let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | Minus -> Minus +module LiftStructFieldMap = Bindlib.Lift (Scopelang.Ast.StructFieldMap) + let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Desugared.Ast.ScopeDef.t option) (ctxt : Name_resolution.context) ((expr, pos) : Ast.expression Pos.marked) : Scopelang.Ast.expr Pos.marked Bindlib.box = @@ -87,9 +89,9 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) ) | Dotted (e, x) -> ( - (* For now we only accept dotted identifiers of the type y.x where y is a sub-scope *) match Pos.unmark e with - | Ident y -> + | Ident y when Name_resolution.is_subscope_uid scope ctxt y -> + (* In this case, y.x is a subscope variable *) let subscope_uid : Scopelang.Ast.SubScopeName.t = Name_resolution.get_subscope_uid scope ctxt (Pos.same_pos_as y e) in @@ -102,13 +104,60 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (SubScopeVar (subscope_real_uid, (subscope_uid, pos), (subscope_var_uid, pos))), pos ) | _ -> - Name_resolution.raise_unsupported_feature - "left hand side of a dotted expression should be an\n\n identifier" pos ) + (* In this case e.x is the struct field x access of expression e *) + let e = translate_expr scope def_key ctxt e in + let x_possible_structs = + try Desugared.Ast.IdentMap.find (Pos.unmark x) ctxt.field_idmap + with Not_found -> + Errors.raise_spanned_error "This identifier should refer to a struct field" + (Pos.get_position x) + in + if Scopelang.Ast.StructMap.cardinal x_possible_structs > 1 then + Errors.raise_spanned_error + (Format.asprintf + "This struct field name is ambiguous, it can belong to %a. Desambiguate 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" Scopelang.Ast.StructName.format_t s_name)) + (Scopelang.Ast.StructMap.bindings x_possible_structs)) + (Pos.get_position x) + else + let s_uid, f_uid = Scopelang.Ast.StructMap.choose x_possible_structs in + Bindlib.box_apply (fun e -> (Scopelang.Ast.EStructAccess (e, f_uid, s_uid), pos)) e ) | FunCall (f, arg) -> Bindlib.box_apply2 (fun f arg -> (Scopelang.Ast.EApp (f, [ arg ]), pos)) (rec_helper f) (rec_helper arg) - | _ -> Name_resolution.raise_unsupported_feature "unsupported expression" pos + | StructLit (s_name, fields) -> + let s_uid = + try Desugared.Ast.IdentMap.find (Pos.unmark s_name) ctxt.struct_idmap + with Not_found -> + Errors.raise_spanned_error "This identifier should refer to a struct name" + (Pos.get_position s_name) + in + let s_fields = + List.fold_left + (fun s_fields (f_name, f_e) -> + let f_uid = + try + Scopelang.Ast.StructMap.find s_uid + (Desugared.Ast.IdentMap.find (Pos.unmark f_name) ctxt.field_idmap) + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "This identifier should refer to a field of struct %s" + (Pos.unmark s_name)) + (Pos.get_position f_name) + in + let f_e = translate_expr scope def_key ctxt f_e in + Scopelang.Ast.StructFieldMap.add f_uid f_e s_fields) + Scopelang.Ast.StructFieldMap.empty fields + in + Bindlib.box_apply + (fun s_fields -> (Scopelang.Ast.EStruct (s_uid, s_fields), pos)) + (LiftStructFieldMap.lift_box s_fields) + | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented" pos (* Translation from the parsed ast to the scope language *) diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index dd416a60..0eec827f 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -38,6 +38,8 @@ let token_list_language_agnostic : (string * token) list = ("=", EQUAL); ("(", LPAREN); (")", RPAREN); + ("{", LBRACKET); + ("}", RBRACKET); ("+", PLUS); ("-", MINUS); ("*", MULT); @@ -322,6 +324,12 @@ let rec lex_code (lexbuf : lexbuf) : token = | ')' -> update_acc lexbuf; RPAREN + | '{' -> + update_acc lexbuf; + LBRACKET + | '}' -> + update_acc lexbuf; + RBRACKET | '+' -> update_acc lexbuf; PLUS diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 32294fdf..fed03b2c 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -294,6 +294,12 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | ')' -> L.update_acc lexbuf; RPAREN + | '{' -> + L.update_acc lexbuf; + LBRACKET + | '}' -> + L.update_acc lexbuf; + RBRACKET | '+' -> L.update_acc lexbuf; PLUS diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 04265166..acd61889 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -303,6 +303,12 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | ')' -> L.update_acc lexbuf; RPAREN + | '{' -> + L.update_acc lexbuf; + LBRACKET + | '}' -> + L.update_acc lexbuf; + RBRACKET | '+' -> L.update_acc lexbuf; PLUS diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index e6b44b2f..b9bc328f 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -53,7 +53,7 @@ type context = { } let raise_unsupported_feature (msg : string) (pos : Pos.t) = - Errors.raise_spanned_error (Printf.sprintf "unsupported feature: %s" msg) pos + Errors.raise_spanned_error (Printf.sprintf "Unsupported feature: %s" msg) pos let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = Errors.raise_spanned_error @@ -72,7 +72,7 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in match Desugared.Ast.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with | Some use -> - Errors.raise_multispanned_error "subscope name already used" + Errors.raise_multispanned_error "Subscope name already used" [ (Some "first use", Pos.get_position (Scopelang.Ast.SubScopeName.get_info use)); (Some "second use", s_pos); @@ -221,8 +221,12 @@ let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with | None -> raise_unknown_identifier "for a var of this subscope" x | Some id -> Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) - | [ s; _ ] -> raise_unsupported_feature "not a subscope" (Pos.get_position s) - | _ -> raise_unsupported_feature "wrong qident" (Pos.get_position id) + | [ s; _ ] -> + Errors.raise_spanned_error "This identifier should refer to a subscope, but does not" + (Pos.get_position s) + | _ -> + Errors.raise_spanned_error "Only scope vars or subscope vars can be defined" + (Pos.get_position id) let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = let scope_uid = @@ -414,6 +418,10 @@ let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) | None -> raise_unknown_identifier "for a subscope of this scope" (y, pos) | Some sub_uid -> sub_uid +let is_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) (y : ident) : bool = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + Desugared.Ast.IdentMap.mem y scope.sub_scopes_idmap + (** Checks if the var_uid belongs to the scope scope_uid *) let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) (scope_uid : Scopelang.Ast.ScopeName.t) : bool = diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index af3b1115..a355585f 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -53,7 +53,7 @@ %token STRUCT CONTENT IF THEN DEPENDS DECLARATION %token CONTEXT ENUM ELSE DATE SUM %token BEGIN_METADATA END_METADATA MONEY DECIMAL -%token UNDER_CONDITION CONSEQUENCE +%token UNDER_CONDITION CONSEQUENCE LBRACKET RBRACKET %type source_file_or_master @@ -120,7 +120,7 @@ enum_inject_content: struct_or_enum_inject_content: | e = option(enum_inject_content) { EnumContent e } -| CONTENT LPAREN ALT fields = separated_nonempty_list(ALT, struct_content_field) RPAREN { +| LBRACKET ALT fields = separated_nonempty_list(ALT, struct_content_field) RBRACKET { StructContent fields } @@ -129,7 +129,7 @@ struct_or_enum_inject: match data with | EnumContent data -> (EnumInject (c, data), $sloc) - | _ -> assert false (* should not happen *) + | StructContent fields -> (StructLit (c, fields), $sloc) } primitive_expression: diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 355f7710..1fa84b4b 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -87,14 +87,12 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po List.fold_right (fun (field_name, _) (d_fields, e_fields) -> let field_e = - Option.value - ~default: - (Errors.raise_spanned_error - (Format.asprintf "The field %a does not belong to the structure %a" - Ast.StructFieldName.format_t field_name Ast.StructName.format_t - struct_name) - (Pos.get_position e)) - (Ast.StructFieldMap.find_opt field_name e_fields) + try Ast.StructFieldMap.find field_name e_fields + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "The field %a does not belong to the structure %a" + Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) + (Pos.get_position e) in let field_d = translate_expr ctx field_e in (field_d :: d_fields, Ast.StructFieldMap.remove field_name e_fields)) @@ -115,26 +113,24 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po | EStructAccess (e1, field_name, struct_name) -> let struct_sig = Ast.StructMap.find struct_name ctx.structs in let _, field_index = - Option.value - ~default: - (Errors.raise_spanned_error - (Format.asprintf "The field %a does not belong to the structure %a" - Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) - (Pos.get_position e)) - (List.assoc_opt field_name (List.mapi (fun i (x, y) -> (x, (y, i))) struct_sig)) + try List.assoc field_name (List.mapi (fun i (x, y) -> (x, (y, i))) struct_sig) + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "The field %a does not belong to the structure %a" + Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) + (Pos.get_position e) in let e1 = translate_expr ctx e1 in Bindlib.box_apply (fun e1 -> Dcalc.Ast.ETupleAccess (e1, field_index)) e1 | EEnumInj (e1, constructor, enum_name) -> let enum_sig = Ast.EnumMap.find enum_name ctx.enums in let _, constructor_index = - Option.value - ~default: - (Errors.raise_spanned_error - (Format.asprintf "The constructor %a does not belong to the enum %a" - Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) - (Pos.get_position e)) - (List.assoc_opt constructor (List.mapi (fun i (x, y) -> (x, (y, i))) enum_sig)) + try List.assoc constructor (List.mapi (fun i (x, y) -> (x, (y, i))) enum_sig) + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "The constructor %a does not belong to the enum %a" + Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) + (Pos.get_position e) in let e1 = translate_expr ctx e1 in Bindlib.box_apply diff --git a/tests/Makefile b/tests/Makefile index 52375180..dee90e00 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,7 +2,9 @@ # Preamble ############################################ -CATALA=dune exec --no-print-director ../src/catala.exe -- Interpret +CATALA_OPTS?= + +CATALA=dune exec --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) tests: $(wildcard */*.catala) diff --git a/tests/test_struct/simple.catala b/tests/test_struct/simple.catala index 2a8efcb5..254e121a 100644 --- a/tests/test_struct/simple.catala +++ b/tests/test_struct/simple.catala @@ -10,7 +10,9 @@ new scope A: param z type int scope A: - def s.x := 1 - def s.y := 2 + def s := S { + -- x : 1 + -- y : 2 + } def z := s.x + s.y */ \ No newline at end of file From fb592fa7350ba592bc6f0c756b73766c9f52dd4d Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sat, 5 Dec 2020 18:12:53 +0100 Subject: [PATCH 052/142] Field and constructor names appear in default calculus --- src/catala/default_calculus/ast.ml | 13 +++++--- src/catala/default_calculus/interpreter.ml | 16 ++++----- src/catala/default_calculus/print.ml | 24 +++++++++---- src/catala/default_calculus/typing.ml | 20 +++++------ src/catala/scope_language/scope_to_dcalc.ml | 37 +++++++++++++++------ src/catala/utils/uid.ml | 13 +++----- src/catala/utils/uid.mli | 2 +- 7 files changed, 75 insertions(+), 50 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index ea743955..c3909cd5 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -13,6 +13,7 @@ the License. *) module Pos = Utils.Pos +module Uid = Utils.Uid type typ = | TBool @@ -32,10 +33,14 @@ type operator = Binop of binop | Unop of unop type expr = | EVar of expr Bindlib.var Pos.marked - | ETuple of expr Pos.marked list - | ETupleAccess of expr Pos.marked * int - | EInj of expr Pos.marked * int * typ Pos.marked list - | EMatch of expr Pos.marked * expr Pos.marked list + | ETuple of (expr Pos.marked * Uid.MarkedString.info option) list + (** The [MarkedString.info] is the former struct field name*) + | ETupleAccess of expr Pos.marked * int * Uid.MarkedString.info option + (** The [MarkedString.info] is the former struct field name*) + | EInj of expr Pos.marked * int * Uid.MarkedString.info * typ Pos.marked list + (** The [MarkedString.info] is the former enum case name *) + | EMatch of expr Pos.marked * (expr Pos.marked * Uid.MarkedString.info) list + (** The [MarkedString.info] is the former enum case name *) | ELit of lit | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 4bdf7652..b85b8363 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -83,13 +83,13 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = term was well-typed" (Pos.get_position e) ) | EAbs _ | ELit _ | EOp _ -> e (* thse are values *) - | ETuple es -> Pos.same_pos_as (A.ETuple (List.map evaluate_expr es)) e - | ETupleAccess (e1, n) -> ( + | ETuple es -> Pos.same_pos_as (A.ETuple (List.map (fun (e', i) -> (evaluate_expr e', i)) es)) e + | ETupleAccess (e1, n, _) -> ( let e1 = evaluate_expr e1 in match Pos.unmark e1 with | ETuple es -> ( match List.nth_opt es n with - | Some e' -> e' + | Some (e', _) -> e' | None -> Errors.raise_spanned_error (Format.asprintf @@ -104,14 +104,14 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = if the term was well-typed)" n) (Pos.get_position e1) ) - | EInj (e1, n, ts) -> + | EInj (e1, n, i, ts) -> let e1' = evaluate_expr e1 in - Pos.same_pos_as (A.EInj (e1', n, ts)) e + Pos.same_pos_as (A.EInj (e1', n, i, ts)) e | EMatch (e1, es) -> ( let e1 = evaluate_expr e1 in match Pos.unmark e1 with - | A.EInj (e1, n, _) -> - let es_n = + | A.EInj (e1, n, _, _) -> + let es_n, _ = match List.nth_opt es n with | Some es_n -> es_n | None -> @@ -190,7 +190,7 @@ let interpret_program (e : Ast.expr Pos.marked) : (Ast.Var.t * Ast.expr Pos.mark match Pos.unmark (evaluate_expr to_interpret) with | Ast.ETuple args -> let vars, _ = Bindlib.unmbind binder in - List.map2 (fun arg var -> (var, arg)) args (Array.to_list vars) + List.map2 (fun (arg, _) var -> (var, arg)) args (Array.to_list vars) | _ -> Errors.raise_spanned_error "The interpretation of a program should always yield a tuple" (Pos.get_position e) ) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index b2ad2e6f..39b95de2 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -79,16 +79,26 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ETuple es -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") format_expr) + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") + (fun fmt (e, struct_field) -> + match struct_field with + | Some struct_field -> + Format.fprintf fmt "@[\"%a\":@ %a@]" Uid.MarkedString.format_info + struct_field format_expr e + | None -> Format.fprintf fmt "@[%a@]" format_expr e)) es - | ETupleAccess (e1, n) -> Format.fprintf fmt "%a.%d" format_expr e1 n - | EInj (e, n, ts) -> - Format.fprintf fmt "inj[%a].%d %a" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) - ts n format_expr e + | ETupleAccess (e1, n, i) -> ( + match i with + | None -> Format.fprintf fmt "%a.%d" format_expr e1 n + | Some i -> Format.fprintf fmt "%a.\"%a\"" format_expr e1 Uid.MarkedString.format_info i ) + | EInj (e, _n, i, _ts) -> Format.fprintf fmt "%a %a" Uid.MarkedString.format_info i format_expr e | EMatch (e, es) -> Format.fprintf fmt "@[match %a with %a@]" format_expr e - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " |@ ") format_expr) + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " |@ ") + (fun fmt (e, c) -> + Format.fprintf fmt "%a %a" Uid.MarkedString.format_info c format_expr e)) es | ELit l -> Format.fprintf fmt "%a" format_lit (Pos.same_pos_as l e) | EApp ((EAbs (_, binder, taus), _), args) -> diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 81eee658..30e58bad 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -127,9 +127,9 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> - let ts = List.map (typecheck_expr_bottom_up env) es in + let ts = List.map (fun (e, _) -> typecheck_expr_bottom_up env e) es in UnionFind.make (Pos.same_pos_as (TTuple ts) e) - | ETupleAccess (e1, n) -> ( + | ETupleAccess (e1, n, _) -> ( let t1 = typecheck_expr_bottom_up env e1 in match Pos.unmark (UnionFind.get (UnionFind.find t1)) with | TTuple ts -> ( @@ -145,7 +145,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m Errors.raise_spanned_error (Format.asprintf "Expected a tuple, got a %a" format_typ t1) (Pos.get_position e1) ) - | EInj (e1, n, ts) -> + | EInj (e1, n, _, ts) -> let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in let ts_n = match List.nth_opt ts n with @@ -160,12 +160,12 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m typecheck_expr_top_down env e1 ts_n; UnionFind.make (Pos.same_pos_as (TEnum ts) e) | EMatch (e1, es) -> - let enum_cases = List.map (fun e' -> UnionFind.make (Pos.same_pos_as TAny e')) es in + let enum_cases = List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as TAny e')) es in let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in typecheck_expr_top_down env e1 t_e1; let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in List.iteri - (fun i es' -> + (fun i (es', _) -> let enum_t = List.nth enum_cases i in let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in typecheck_expr_top_down env es' t_es') @@ -229,12 +229,12 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | ETuple es -> ( let tau' = UnionFind.get (UnionFind.find tau) in match Pos.unmark tau' with - | TTuple ts -> List.iter2 (typecheck_expr_top_down env) es ts + | TTuple ts -> List.iter2 (fun (e, _) t -> typecheck_expr_top_down env e t) es ts | _ -> Errors.raise_spanned_error (Format.asprintf "exprected %a, got a tuple" format_typ tau) (Pos.get_position e) ) - | ETupleAccess (e1, n) -> ( + | ETupleAccess (e1, n, _) -> ( let t1 = typecheck_expr_bottom_up env e1 in match Pos.unmark (UnionFind.get (UnionFind.find t1)) with | TTuple t1s -> ( @@ -250,7 +250,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) Errors.raise_spanned_error (Format.asprintf "exprected a tuple , got %a" format_typ tau) (Pos.get_position e) ) - | EInj (e1, n, ts) -> + | EInj (e1, n, _, ts) -> let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in let ts_n = match List.nth_opt ts n with @@ -265,12 +265,12 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env e1 ts_n; unify (UnionFind.make (Pos.same_pos_as (TEnum ts) e)) tau | EMatch (e1, es) -> - let enum_cases = List.map (fun e' -> UnionFind.make (Pos.same_pos_as TAny e')) es in + let enum_cases = List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as TAny e')) es in let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in typecheck_expr_top_down env e1 t_e1; let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in List.iteri - (fun i es' -> + (fun i (es', _) -> let enum_t = List.nth enum_cases i in let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in typecheck_expr_top_down env es' t_es') diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 1fa84b4b..c5a485cd 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -95,6 +95,11 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (Pos.get_position e) in let field_d = translate_expr ctx field_e in + let field_d = + Bindlib.box_apply + (fun field_d -> (field_d, Some (Ast.StructFieldName.get_info field_name))) + field_d + in (field_d :: d_fields, Ast.StructFieldMap.remove field_name e_fields)) struct_sig ([], e_fields) in @@ -121,7 +126,10 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (Pos.get_position e) in let e1 = translate_expr ctx e1 in - Bindlib.box_apply (fun e1 -> Dcalc.Ast.ETupleAccess (e1, field_index)) e1 + Bindlib.box_apply + (fun e1 -> + Dcalc.Ast.ETupleAccess (e1, field_index, Some (Ast.StructFieldName.get_info field_name))) + e1 | EEnumInj (e1, constructor, enum_name) -> let enum_sig = Ast.EnumMap.find enum_name ctx.enums in let _, constructor_index = @@ -136,7 +144,10 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po Bindlib.box_apply (fun e1 -> Dcalc.Ast.EInj - (e1, constructor_index, List.map (fun (_, t) -> translate_typ ctx t) enum_sig)) + ( e1, + constructor_index, + Ast.EnumConstructor.get_info constructor, + List.map (fun (_, t) -> translate_typ ctx t) enum_sig )) e1 | EMatch (e1, enum_name, cases) -> let enum_sig = Ast.EnumMap.find enum_name ctx.enums in @@ -144,15 +155,19 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po List.fold_right (fun (constructor, _) (d_cases, e_cases) -> let case_e = - Option.value - ~default: - (Errors.raise_spanned_error - (Format.asprintf "The constructor %a does not belong to the enum %a" - Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) - (Pos.get_position e)) - (Ast.EnumConstructorMap.find_opt constructor e_cases) + try Ast.EnumConstructorMap.find constructor e_cases + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "The constructor %a does not belong to the enum %a" + Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) + (Pos.get_position e) in let case_d = translate_expr ctx case_e in + let case_d = + Bindlib.box_apply + (fun case_d -> (case_d, Ast.EnumConstructor.get_info constructor)) + case_d + in (case_d :: d_cases, Ast.EnumConstructorMap.remove constructor e_cases)) enum_sig ([], cases) in @@ -343,7 +358,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos (fun (_, tau, dvar) (acc, i) -> let result_access = Bindlib.box_apply - (fun r -> (Dcalc.Ast.ETupleAccess (r, i), pos_sigma)) + (fun r -> (Dcalc.Ast.ETupleAccess (r, i, None), pos_sigma)) (Dcalc.Ast.make_var (result_tuple_var, pos_sigma)) in (Dcalc.Ast.make_let_in dvar (tau, pos_sigma) result_access acc, i - 1)) @@ -363,7 +378,7 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : let scope_variables = Ast.ScopeVarMap.bindings ctx.scope_vars in let return_exp = Bindlib.box_apply - (fun args -> (Dcalc.Ast.ETuple args, pos_sigma)) + (fun args -> (Dcalc.Ast.ETuple (List.map (fun arg -> (arg, None)) args), pos_sigma)) (Bindlib.box_list (List.map (fun (_, (dcalc_var, _)) -> Dcalc.Ast.make_var (dcalc_var, pos_sigma)) diff --git a/src/catala/utils/uid.ml b/src/catala/utils/uid.ml index 5c6f1781..ad5580db 100644 --- a/src/catala/utils/uid.ml +++ b/src/catala/utils/uid.ml @@ -15,7 +15,7 @@ module type Info = sig type info - val format_info : info -> string + val format_info : Format.formatter -> info -> unit end module type Id = sig @@ -34,12 +34,7 @@ module type Id = sig val hash : t -> int end -module Make (X : sig - type info - - val format_info : info -> string -end) -() : Id with type info = X.info = struct +module Make (X : Info) () : Id with type info = X.info = struct type t = { id : int; info : X.info } type info = X.info @@ -55,7 +50,7 @@ end) let compare (x : t) (y : t) : int = compare x.id y.id let format_t (fmt : Format.formatter) (x : t) : unit = - Format.fprintf fmt "%s" (X.format_info x.info) + Format.fprintf fmt "%a" X.format_info x.info let hash (x : t) : int = x.id end @@ -63,5 +58,5 @@ end module MarkedString = struct type info = string Pos.marked - let format_info (s, _) = s + let format_info fmt (s, _) = Format.fprintf fmt "%s" s end diff --git a/src/catala/utils/uid.mli b/src/catala/utils/uid.mli index 791a7801..7c9c8242 100644 --- a/src/catala/utils/uid.mli +++ b/src/catala/utils/uid.mli @@ -15,7 +15,7 @@ module type Info = sig type info - val format_info : info -> string + val format_info : Format.formatter -> info -> unit end module MarkedString : Info with type info = string Pos.marked From 8abe20849de997a19c6b2a7c3ceb5e6bd19cc867 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 11:42:47 +0100 Subject: [PATCH 053/142] Passing simple test --- tests/Makefile | 2 +- tests/test_struct/simple.catala.A.out | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 tests/test_struct/simple.catala.A.out diff --git a/tests/Makefile b/tests/Makefile index dee90e00..c53646db 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -53,4 +53,4 @@ test_scope/sub_vars_in_sub_var.catala: $(call interpret_with_scope_and_compare,nv,A) test_struct/simple.catala: - $(call interpret_with_scope,nv,A) \ No newline at end of file + $(call interpret_with_scope_and_compare,nv,A) \ No newline at end of file diff --git a/tests/test_struct/simple.catala.A.out b/tests/test_struct/simple.catala.A.out new file mode 100644 index 00000000..3921742f --- /dev/null +++ b/tests/test_struct/simple.catala.A.out @@ -0,0 +1,2 @@ +[RESULT] s -> ("x": 1,"y": 2) +[RESULT] z -> 3 From ee0cb1eefcf7c55860ba83312992b1ce2f04aad8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 12:32:36 +0100 Subject: [PATCH 054/142] Preventing recursive type definitions --- src/catala/scope_language/dependency.ml | 165 ++++++++++++++++-- src/catala/scope_language/scope_to_dcalc.ml | 3 +- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 26 +-- .../nv/vscode/syntaxes/catalavs.xml | 2 +- tests/Makefile | 4 + tests/test_struct/nested.catala | 12 ++ tests/test_struct/nested.catala.A.out | 6 + tests/test_struct/nested2.catala | 11 ++ tests/test_struct/nested2.catala.A.out | 6 + 11 files changed, 206 insertions(+), 33 deletions(-) create mode 100644 tests/test_struct/nested.catala create mode 100644 tests/test_struct/nested.catala.A.out create mode 100644 tests/test_struct/nested2.catala create mode 100644 tests/test_struct/nested2.catala.A.out diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 8568ee00..5a4b1f12 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -18,12 +18,12 @@ module Pos = Utils.Pos module Errors = Utils.Errors -module Vertex = struct +module SVertex = struct type t = Ast.ScopeName.t let hash x = Ast.ScopeName.hash x - let compare = compare + let compare = Ast.ScopeName.compare let equal x y = Ast.ScopeName.compare x y = 0 @@ -31,7 +31,7 @@ module Vertex = struct end (** On the edges, the label is the expression responsible for the use of the function *) -module Edge = struct +module SEdge = struct type t = Pos.t let compare = compare @@ -39,15 +39,15 @@ module Edge = struct let default = Pos.no_pos end -module Dependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge) -module TopologicalTraversal = Graph.Topological.Make (Dependencies) +module SDependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (SVertex) (SEdge) +module STopologicalTraversal = Graph.Topological.Make (SDependencies) -module SCC = Graph.Components.Make (Dependencies) +module SSCC = Graph.Components.Make (SDependencies) (** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) -let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = - let g = Dependencies.empty in - let g = Ast.ScopeMap.fold (fun v _ g -> Dependencies.add_vertex g v) prgm.program_scopes g in +let build_program_dep_graph (prgm : Ast.program) : SDependencies.t = + let g = SDependencies.empty in + let g = Ast.ScopeMap.fold (fun v _ g -> SDependencies.add_vertex g v) prgm.program_scopes g in Ast.ScopeMap.fold (fun scope_name scope g -> let subscopes = @@ -58,8 +58,10 @@ let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = | Ast.Call (subscope, subindex) -> if subscope = scope_name then Errors.raise_spanned_error - "The scope %a is calling into itself as a subscope, which is forbidden since \ - Catala does not provide recursion" + (Format.asprintf + "The scope %a is calling into itself as a subscope, which is forbidden \ + since Catala does not provide recursion" + Ast.ScopeName.format_t scope.Ast.scope_decl_name) (Pos.get_position (Ast.ScopeName.get_info scope.Ast.scope_decl_name)) else Ast.ScopeMap.add subscope @@ -69,15 +71,15 @@ let build_program_dep_graph (prgm : Ast.program) : Dependencies.t = in Ast.ScopeMap.fold (fun subscope pos g -> - let edge = Dependencies.E.create subscope pos scope_name in - Dependencies.add_edge_e g edge) + let edge = SDependencies.E.create subscope pos scope_name in + SDependencies.add_edge_e g edge) subscopes g) prgm.program_scopes g -let check_for_cycle (g : Dependencies.t) : unit = +let check_for_cycle_in_scope (g : SDependencies.t) : unit = (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) - let sccs = SCC.scc_list g in - if List.length sccs < Dependencies.nb_vertex g then + let sccs = SSCC.scc_list g in + if List.length sccs < SDependencies.nb_vertex g then let scc = List.find (fun scc -> List.length scc > 1) sccs in Errors.raise_multispanned_error "Cyclic dependency detected between scopes!" (List.flatten @@ -86,7 +88,7 @@ let check_for_cycle (g : Dependencies.t) : unit = let var_str, var_info = (Format.asprintf "%a" Ast.ScopeName.format_t v, Ast.ScopeName.get_info v) in - let succs = Dependencies.succ_e g v in + let succs = SDependencies.succ_e g v in let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in let succ_str = Format.asprintf "%a" Ast.ScopeName.format_t succ in [ @@ -96,5 +98,130 @@ let check_for_cycle (g : Dependencies.t) : unit = ]) scc)) -let get_scope_ordering (g : Dependencies.t) : Ast.ScopeName.t list = - List.rev (TopologicalTraversal.fold (fun sd acc -> sd :: acc) g []) +let get_scope_ordering (g : SDependencies.t) : Ast.ScopeName.t list = + List.rev (STopologicalTraversal.fold (fun sd acc -> sd :: acc) g []) + +module TVertex = struct + type t = Struct of Ast.StructName.t | Enum of Ast.EnumName.t + + let hash x = match x with Struct x -> Ast.StructName.hash x | Enum x -> Ast.EnumName.hash x + + let compare x y = + match (x, y) with + | Struct x, Struct y -> Ast.StructName.compare x y + | Enum x, Enum y -> Ast.EnumName.compare x y + | Struct _, Enum _ -> 1 + | Enum _, Struct _ -> -1 + + let equal x y = + match (x, y) with + | Struct x, Struct y -> Ast.StructName.compare x y = 0 + | Enum x, Enum y -> Ast.EnumName.compare x y = 0 + | _ -> false + + let format_t (fmt : Format.formatter) (x : t) : unit = + match x with Struct x -> Ast.StructName.format_t fmt x | Enum x -> Ast.EnumName.format_t fmt x + + let get_info (x : t) = + match x with Struct x -> Ast.StructName.get_info x | Enum x -> Ast.EnumName.get_info x +end + +module TVertexSet = Set.Make (TVertex) + +(** On the edges, the label is the expression responsible for the use of the function *) +module TEdge = struct + type t = Pos.t + + let compare = compare + + let default = Pos.no_pos +end + +module TDependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (TVertex) (TEdge) +module TTopologicalTraversal = Graph.Topological.Make (TDependencies) + +module TSCC = Graph.Components.Make (TDependencies) +(** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) + +let rec get_structs_or_enums_in_type (t : Ast.typ Pos.marked) : TVertexSet.t = + match Pos.unmark t with + | Ast.TStruct s -> TVertexSet.singleton (TVertex.Struct s) + | Ast.TEnum e -> TVertexSet.singleton (TVertex.Enum e) + | Ast.TArrow (t1, t2) -> + TVertexSet.union (get_structs_or_enums_in_type t1) (get_structs_or_enums_in_type t2) + | Ast.TBool | Ast.TUnit | Ast.TInt -> TVertexSet.empty + +let build_type_graph (structs : Ast.struct_ctx) (enums : Ast.enum_ctx) : TDependencies.t = + let g = TDependencies.empty in + let g = + Ast.StructMap.fold + (fun s fields g -> + List.fold_left + (fun g (_, typ) -> + let def = TVertex.Struct s in + let g = TDependencies.add_vertex g def in + let used = get_structs_or_enums_in_type typ in + TVertexSet.fold + (fun used g -> + if TVertex.equal used def then + Errors.raise_spanned_error + (Format.asprintf + "The type %a is defined using itself, which is forbidden since Catala does \ + not provide recursive types" + TVertex.format_t used) + (Pos.get_position typ) + else + let edge = TDependencies.E.create used (Pos.get_position typ) def in + TDependencies.add_edge_e g edge) + used g) + g fields) + structs g + in + let g = + Ast.EnumMap.fold + (fun e cases g -> + List.fold_left + (fun g (_, typ) -> + let def = TVertex.Enum e in + let g = TDependencies.add_vertex g def in + let used = get_structs_or_enums_in_type typ in + TVertexSet.fold + (fun used g -> + if TVertex.equal used def then + Errors.raise_spanned_error + (Format.asprintf + "The type %a is defined using itself, which is forbidden since Catala does \ + not provide recursive types" + TVertex.format_t used) + (Pos.get_position typ) + else + let edge = TDependencies.E.create used (Pos.get_position typ) def in + TDependencies.add_edge_e g edge) + used g) + g cases) + enums g + in + g + +let check_type_cycles (structs : Ast.struct_ctx) (enums : Ast.enum_ctx) : unit = + let g = build_type_graph structs enums in + (* if there is a cycle, there will be an strongly connected component of cardinality > 1 *) + let sccs = TSCC.scc_list g in + if List.length sccs < TDependencies.nb_vertex g then + let scc = List.find (fun scc -> List.length scc > 1) sccs in + Errors.raise_multispanned_error "Cyclic dependency detected between types!" + (List.flatten + (List.map + (fun v -> + let var_str, var_info = + (Format.asprintf "%a" TVertex.format_t v, TVertex.get_info v) + in + let succs = TDependencies.succ_e g v in + let _, edge_pos, succ = List.find (fun (_, _, succ) -> List.mem succ scc) succs in + let succ_str = Format.asprintf "%a" TVertex.format_t succ in + [ + (Some ("Cycle type " ^ var_str ^ ", declared:"), Pos.get_position var_info); + ( Some ("Used here in the definition of another cycle type " ^ succ_str ^ ":"), + edge_pos ); + ]) + scc)) diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index c5a485cd..4d36a51c 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -420,7 +420,8 @@ let build_scope_typ_from_sig (scope_sig : (Ast.ScopeVar.t * Dcalc.Ast.typ) list) let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : Dcalc.Ast.expr Pos.marked = let scope_dependencies = Dependency.build_program_dep_graph prgm in - Dependency.check_for_cycle scope_dependencies; + Dependency.check_for_cycle_in_scope scope_dependencies; + Dependency.check_type_cycles prgm.program_structs prgm.program_enums; let scope_ordering = Dependency.get_scope_ordering scope_dependencies in let struct_ctx = prgm.program_structs in let enum_ctx = prgm.program_enums in diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index 4e70b4f4..770c7d76 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -100,7 +100,7 @@ 'name' : 'keyword.control.catala_nv' } { - 'match' : '\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enume|param|rule|condition|data|ok|assert|def)\\b' + 'match' : '\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b' 'name' : 'keyword.other.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index b2a7c1dd..c50ce05e 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -213,7 +213,7 @@ code : context { } : pattern { - regex \= \b(scope|fun\s+of|new|includes|set|type|option|struct|enume|param|rule|condition|data|ok|assert|def)\b + regex \= \b(scope|fun\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\b styles [] = .keyword_rule ; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index f3e0860f..fae75c8b 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -3,7 +3,8 @@ from pygments.token import * import re -__all__=['CatalaNvLexer'] +__all__ = ['CatalaNvLexer'] + class CatalaNvLexer(RegexLexer): name = 'CatalaNv' @@ -12,7 +13,7 @@ class CatalaNvLexer(RegexLexer): flags = re.MULTILINE | re.UNICODE tokens = { - 'root' : [ + 'root': [ (u'(@@)', bygroups(Generic.Heading), 'main__1'), (u'(@)', bygroups(Generic.Heading), 'main__2'), (u'([^\\/\\n\\r])', bygroups(Text)), @@ -20,17 +21,22 @@ class CatalaNvLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'code' : [ + 'code': [ (u'(\\s*\\#.*$)', bygroups(Comment.Single)), - (u'(param)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), + (u'(param)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', + bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(match|with|fixed|by|decreasing|increasing|varies|with\\s+param|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b', bygroups(Keyword.Reserved)), - (u'\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enume|param|rule|condition|data|ok|assert|def)\\b', bygroups(Keyword.Declaration)), + (u'\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b', + bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), - (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[|\\])', bygroups(Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\\\$|%|year|month|day)', bygroups(Operator)), - (u'\\b(int|bool|date|amount|text|decimal|number|sum|now)\\b', bygroups(Keyword.Type)), + (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[|\\])', + bygroups(Operator)), + (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\\\$|%|year|month|day)', + bygroups(Operator)), + (u'\\b(int|bool|date|amount|text|decimal|number|sum|now)\\b', + bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Variable)), @@ -38,12 +44,12 @@ class CatalaNvLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__1' : [ + 'main__1': [ (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__2' : [ + 'main__2': [ (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), ('.', Text), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index 001e198a..bc8533f6 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -161,7 +161,7 @@ match - \b(scope|fun\s+of|new|includes|set|type|option|struct|enume|param|rule|condition|data|ok|assert|def)\b + \b(scope|fun\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\b name keyword.other.catala_nv diff --git a/tests/Makefile b/tests/Makefile index c53646db..210e0b1f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -53,4 +53,8 @@ test_scope/sub_vars_in_sub_var.catala: $(call interpret_with_scope_and_compare,nv,A) test_struct/simple.catala: + $(call interpret_with_scope_and_compare,nv,A) +test_struct/nested.catala: + $(call interpret_with_scope_and_compare,nv,A) +test_struct/nested2.catala: $(call interpret_with_scope_and_compare,nv,A) \ No newline at end of file diff --git a/tests/test_struct/nested.catala b/tests/test_struct/nested.catala new file mode 100644 index 00000000..0f485b72 --- /dev/null +++ b/tests/test_struct/nested.catala @@ -0,0 +1,12 @@ +@Article@ + +/* +new struct S: + data x type S + +new scope A: + param y type S + +scope A: + def y := S { -- x: 1 } +*/ \ No newline at end of file diff --git a/tests/test_struct/nested.catala.A.out b/tests/test_struct/nested.catala.A.out new file mode 100644 index 00000000..142af226 --- /dev/null +++ b/tests/test_struct/nested.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] The type S is defined using itself, which is forbidden since Catala does not provide recursive types +[ERROR] +[ERROR] --> test_struct/nested.catala +[ERROR] | +[ERROR] 5 | data x type S +[ERROR] | ^ diff --git a/tests/test_struct/nested2.catala b/tests/test_struct/nested2.catala new file mode 100644 index 00000000..f2c26af1 --- /dev/null +++ b/tests/test_struct/nested2.catala @@ -0,0 +1,11 @@ +@Article@ + +/* +new struct S: + data x type E + data y type int + +new enum E: + -- Case1 type bool + -- Case2 type S +*/ \ No newline at end of file diff --git a/tests/test_struct/nested2.catala.A.out b/tests/test_struct/nested2.catala.A.out new file mode 100644 index 00000000..a2324089 --- /dev/null +++ b/tests/test_struct/nested2.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] Unknown type, not a struct or enum previously declared +[ERROR] +[ERROR] --> test_struct/nested2.catala +[ERROR] | +[ERROR] 5 | data x type E +[ERROR] | ^ From 9170630a6e57bc8033e7f4bd601efbac3603d071 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 13:00:38 +0100 Subject: [PATCH 055/142] Added better test --- tests/Makefile | 5 +++- tests/test_struct/nested3.catala | 35 ++++++++++++++++++++++++++ tests/test_struct/nested3.catala.A.out | 1 + tests/test_struct/nested3.catala.B.out | 2 ++ 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 tests/test_struct/nested3.catala create mode 100644 tests/test_struct/nested3.catala.A.out create mode 100644 tests/test_struct/nested3.catala.B.out diff --git a/tests/Makefile b/tests/Makefile index 210e0b1f..dd64d866 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -57,4 +57,7 @@ test_struct/simple.catala: test_struct/nested.catala: $(call interpret_with_scope_and_compare,nv,A) test_struct/nested2.catala: - $(call interpret_with_scope_and_compare,nv,A) \ No newline at end of file + $(call interpret_with_scope_and_compare,nv,A) +test_struct/nested3.catala: + $(call interpret_with_scope_and_compare,nv,A) + $(call interpret_with_scope_and_compare,nv,B) \ No newline at end of file diff --git a/tests/test_struct/nested3.catala b/tests/test_struct/nested3.catala new file mode 100644 index 00000000..6d7a47b2 --- /dev/null +++ b/tests/test_struct/nested3.catala @@ -0,0 +1,35 @@ +@Article@ + +/* +new struct S: + data x type int + data y type bool + +new struct T: + data a type S + data b type S + +new scope A: + param t type T + +new scope B: + param t type T + param a scope A + param out type int + +scope A: + def t := T { + -- a : S { + -- x : 0 + -- y : false + } + -- b : S { + -- x : 1 + -- y : true + } + } + +scope B: + def t := a.t + def out := if t.a.y then t.a.x else (if t.b.y then t.b.x else 42) +*/ \ No newline at end of file diff --git a/tests/test_struct/nested3.catala.A.out b/tests/test_struct/nested3.catala.A.out new file mode 100644 index 00000000..d8f09825 --- /dev/null +++ b/tests/test_struct/nested3.catala.A.out @@ -0,0 +1 @@ +[RESULT] t -> ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) diff --git a/tests/test_struct/nested3.catala.B.out b/tests/test_struct/nested3.catala.B.out new file mode 100644 index 00000000..7c755661 --- /dev/null +++ b/tests/test_struct/nested3.catala.B.out @@ -0,0 +1,2 @@ +[RESULT] out -> 1 +[RESULT] t -> ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) From 4da1c7f9c8f06b93b120fdaf61f7e92383da11fa Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 17:48:15 +0100 Subject: [PATCH 056/142] Implmemented enum desugaring but parser error --- src/catala/catala_surface/ast.ml | 9 +- src/catala/catala_surface/desugaring.ml | 170 +++++++++++++------ src/catala/catala_surface/lexer.ml | 2 +- src/catala/catala_surface/name_resolution.ml | 55 +----- tests/Makefile | 66 ++----- tests/test_enum/simple.catala | 17 ++ 6 files changed, 166 insertions(+), 153 deletions(-) create mode 100644 tests/test_enum/simple.catala diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 9900508e..9b078376 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -90,11 +90,6 @@ type match_case = { and match_cases = match_case Pos.marked list -and struct_inject = { - struct_inject_name : constructor Pos.marked; - struct_inject_fields : (ident Pos.marked * expression Pos.marked) list; -} - and expression = | MatchWith of expression Pos.marked * match_cases Pos.marked | IfThenElse of expression Pos.marked * expression Pos.marked * expression Pos.marked @@ -112,8 +107,8 @@ and expression = | StructLit of constructor Pos.marked * (ident Pos.marked * expression Pos.marked) list | Ident of ident | Dotted of expression Pos.marked * ident Pos.marked - (* Dotted is for both struct field projection and sub-scope variables *) - | StructInject of struct_inject + +(* Dotted is for both struct field projection and sub-scope variables *) type rule = { rule_parameter : ident Pos.marked option; diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index e19d6882..c608cf4d 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -37,6 +37,7 @@ let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | Minus -> Minus module LiftStructFieldMap = Bindlib.Lift (Scopelang.Ast.StructFieldMap) +module LiftEnumConstructorMap = Bindlib.Lift (Scopelang.Ast.EnumConstructorMap) let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (def_key : Desugared.Ast.ScopeDef.t option) (ctxt : Name_resolution.context) @@ -71,22 +72,15 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) Bindlib.box (untyped_term, pos) | Ident x -> ( (* first we check whether this is a local var, then we resort to scope-wide variables *) - match def_key with - | Some def_key -> ( - let def_ctxt = Desugared.Ast.ScopeDefMap.find def_key scope_ctxt.definitions in - match Desugared.Ast.IdentMap.find_opt x def_ctxt.var_idmap with - | None -> ( - match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with - | Some uid -> Bindlib.box (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) - | None -> - Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" - (x, pos) ) - | Some uid -> Scopelang.Ast.make_var (uid, pos) - (* the whole box thing is to accomodate for this case *) ) + match Desugared.Ast.IdentMap.find_opt x ctxt.local_var_idmap with | None -> ( match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> Bindlib.box (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) - | None -> Name_resolution.raise_unknown_identifier "for a scope-wide variable" (x, pos) ) + | None -> + Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" + (x, pos) ) + | Some uid -> + Scopelang.Ast.make_var (uid, pos) (* the whole box thing is to accomodate for this case *) ) | Dotted (e, x) -> ( match Pos.unmark e with @@ -157,7 +151,118 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) Bindlib.box_apply (fun s_fields -> (Scopelang.Ast.EStruct (s_uid, s_fields), pos)) (LiftStructFieldMap.lift_box s_fields) - | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented" pos + | EnumInject (constructor, payload) -> + let possible_c_uids = + try Desugared.Ast.IdentMap.find (Pos.unmark constructor) ctxt.constructor_idmap + with Not_found -> + Errors.raise_spanned_error + "The name of this constructor has not been defined before, maybe it is a typo?" + (Pos.get_position constructor) + in + if Scopelang.Ast.EnumMap.cardinal possible_c_uids > 1 then + Errors.raise_spanned_error + (Format.asprintf + "This constuctor name is ambiguous, it can belong to %a. Desambiguate it by prefixing \ + it with the enum name." + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " or ") + (fun fmt (s_name, _) -> + Format.fprintf fmt "%a" Scopelang.Ast.EnumName.format_t s_name)) + (Scopelang.Ast.EnumMap.bindings possible_c_uids)) + (Pos.get_position constructor) + else + let e_uid, c_uid = Scopelang.Ast.EnumMap.choose possible_c_uids in + let payload = Option.map (translate_expr scope def_key ctxt) payload in + Bindlib.box_apply + (fun payload -> + ( Scopelang.Ast.EEnumInj + ( ( match payload with + | Some e' -> e' + | None -> (Scopelang.Ast.ELit Dcalc.Ast.LUnit, Pos.get_position constructor) ), + c_uid, + e_uid ), + pos )) + (Bindlib.box_opt payload) + | MatchWith (e1, (cases, _cases_pos)) -> + let e1 = translate_expr scope def_key ctxt e1 in + let cases_d, e_uid = + List.fold_left + (fun (cases_d, e_uid) (case, pos_case) -> + match Pos.unmark case.Ast.match_case_pattern with + | [ constructor ], binding -> + let possible_c_uids = + try Desugared.Ast.IdentMap.find (Pos.unmark constructor) ctxt.constructor_idmap + with Not_found -> + Errors.raise_spanned_error + "The name of this constructor has not been defined before, maybe it is a \ + typo?" + (Pos.get_position constructor) + in + if e_uid = None && Scopelang.Ast.EnumMap.cardinal possible_c_uids > 1 then + Errors.raise_spanned_error + (Format.asprintf + "This constuctor name is ambiguous, it can belong to %a. Desambiguate it by \ + prefixing it with the enum name." + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt " or ") + (fun fmt (s_name, _) -> + Format.fprintf fmt "%a" Scopelang.Ast.EnumName.format_t s_name)) + (Scopelang.Ast.EnumMap.bindings possible_c_uids)) + (Pos.get_position constructor) + else + let e_uid, c_uid = + match e_uid with + | Some e_uid -> ( + ( e_uid, + try Scopelang.Ast.EnumMap.find e_uid possible_c_uids + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "This constructor is not part of the %a enumeration" + Scopelang.Ast.EnumName.format_t e_uid) + (Pos.get_position constructor) ) ) + | None -> Scopelang.Ast.EnumMap.choose possible_c_uids + in + let ctxt, param_var = + match binding with + | None -> (ctxt, None) + | Some param -> + let ctxt, param_var = Name_resolution.add_def_local_var ctxt param in + (ctxt, Some (param_var, Pos.get_position param)) + in + let case_body = translate_expr scope def_key ctxt case.Ast.match_case_expr in + let case_expr = + match param_var with + | None -> case_body + | Some (param_var, param_pos) -> + let e_binder = Bindlib.bind_mvar (Array.of_list [ param_var ]) case_body in + Bindlib.box_apply2 + (fun e_binder case_body -> + Pos.same_pos_as + (Scopelang.Ast.EAbs + ( param_pos, + e_binder, + [ + Scopelang.Ast.EnumConstructorMap.find c_uid + (Scopelang.Ast.EnumMap.find e_uid ctxt.Name_resolution.enums); + ] )) + case_body) + e_binder case_body + in + (Scopelang.Ast.EnumConstructorMap.add c_uid case_expr cases_d, Some e_uid) + | _ :: _, _ -> + Errors.raise_spanned_error + "The deep pattern matching syntactic sugar is not yet supported" pos_case + | [], _ -> assert false + (* should not happen *)) + (Scopelang.Ast.EnumConstructorMap.empty, None) + cases + in + Bindlib.box_apply2 + (fun e1 cases_d -> (Scopelang.Ast.EMatch (e1, Option.get e_uid, cases_d), pos)) + e1 + (LiftEnumConstructorMap.lift_box cases_d) + | _ -> + Name_resolution.raise_unsupported_feature "desugaring not implemented for this expression" pos (* Translation from the parsed ast to the scope language *) @@ -208,38 +313,6 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); } -let add_var_to_def_idmap (ctxt : Name_resolution.context) (scope_uid : Scopelang.Ast.ScopeName.t) - (def_key : Desugared.Ast.ScopeDef.t) (name : string Pos.marked) (var : Scopelang.Ast.Var.t) : - Name_resolution.context = - { - ctxt with - scopes = - Scopelang.Ast.ScopeMap.update scope_uid - (fun scope_ctxt -> - match scope_ctxt with - | Some scope_ctxt -> - Some - { - scope_ctxt with - Name_resolution.definitions = - Desugared.Ast.ScopeDefMap.update def_key - (fun def_ctxt -> - match def_ctxt with - | None -> assert false (* should not happen *) - | Some (def_ctxt : Name_resolution.def_context) -> - Some - { - Name_resolution.var_idmap = - Desugared.Ast.IdentMap.add (Pos.unmark name) var - def_ctxt.Name_resolution.var_idmap; - }) - scope_ctxt.Name_resolution.definitions; - } - | None -> assert false - (* should not happen *)) - ctxt.scopes; - } - (* Process a definition *) let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) @@ -268,9 +341,8 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) match def.definition_parameter with | None -> (None, ctxt) | Some param -> - let param_var = Scopelang.Ast.Var.make param in - ( Some (Pos.same_pos_as param_var param), - add_var_to_def_idmap ctxt scope_uid def_key param param_var ) + let ctxt, param_var = Name_resolution.add_def_local_var ctxt param in + (Some (Pos.same_pos_as param_var param), ctxt) in let scope_updated = let x_def, x_type = diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 0eec827f..b4ec0294 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -181,7 +181,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "varies" -> update_acc lexbuf; VARIES - | "with" -> + | "withv" -> update_acc lexbuf; WITH_V | "match" -> diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index b9bc328f..b6f3ff89 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -22,7 +22,6 @@ type ident = string type typ = Scopelang.Ast.typ -type def_context = { var_idmap : Scopelang.Ast.Var.t Desugared.Ast.IdentMap.t } (** Inside a definition, local variables can be introduced by functions arguments or pattern matching *) @@ -30,8 +29,6 @@ type scope_context = { var_idmap : Scopelang.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Desugared.Ast.IdentMap.t; sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; - definitions : def_context Desugared.Ast.ScopeDefMap.t; - (** Contains the local variables in all the definitions *) } (** Inside a scope, we distinguish between the variables and the subscopes. *) @@ -40,6 +37,7 @@ type struct_context = typ Pos.marked Scopelang.Ast.StructFieldMap.t type enum_context = typ Pos.marked Scopelang.Ast.EnumConstructorMap.t type context = { + local_var_idmap : Scopelang.Ast.Var.t Desugared.Ast.IdentMap.t; scope_idmap : Scopelang.Ast.ScopeName.t Desugared.Ast.IdentMap.t; scopes : scope_context Scopelang.Ast.ScopeMap.t; structs : struct_context Scopelang.Ast.StructMap.t; @@ -158,21 +156,16 @@ let process_item_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) | Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl (** Adds a binding to the context *) -let add_def_local_var (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) - (def_uid : Desugared.Ast.ScopeDef.t) (name : ident Pos.marked) : context = - let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - let def_ctx = Desugared.Ast.ScopeDefMap.find def_uid scope_ctxt.definitions in +let add_def_local_var (ctxt : context) (name : ident Pos.marked) : context * Scopelang.Ast.Var.t = let local_var_uid = Scopelang.Ast.Var.make name in - let def_ctx = - { var_idmap = Desugared.Ast.IdentMap.add (Pos.unmark name) local_var_uid def_ctx.var_idmap } - in - let scope_ctxt = + let ctxt = { - scope_ctxt with - definitions = Desugared.Ast.ScopeDefMap.add def_uid def_ctx scope_ctxt.definitions; + ctxt with + local_var_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark name) local_var_uid ctxt.local_var_idmap; } in - { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } + (ctxt, local_var_uid) (** Process a scope declaration *) let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = @@ -196,7 +189,6 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = { var_idmap = Desugared.Ast.IdentMap.empty; sub_scopes_idmap = Desugared.Ast.IdentMap.empty; - definitions = Desugared.Ast.ScopeDefMap.empty; sub_scopes = Scopelang.Ast.SubScopeMap.empty; } ctxt.scopes; @@ -228,34 +220,6 @@ let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) Errors.raise_spanned_error "Only scope vars or subscope vars can be defined" (Pos.get_position id) -let process_scope_use (ctxt : context) (use : Ast.scope_use) : context = - let scope_uid = - match Desugared.Ast.IdentMap.find_opt (Pos.unmark use.scope_use_name) ctxt.scope_idmap with - | None -> raise_unknown_identifier "for a scope" use.scope_use_name - | Some id -> id - in - List.fold_left - (fun ctxt use_item -> - match Pos.unmark use_item with - | Ast.Definition def -> - let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - let def_uid = qident_to_scope_def ctxt scope_uid def.definition_name in - let def_ctxt = { var_idmap = Desugared.Ast.IdentMap.empty } in - let scope_ctxt = - { - scope_ctxt with - definitions = Desugared.Ast.ScopeDefMap.add def_uid def_ctxt scope_ctxt.definitions; - } - in - { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_ctxt ctxt.scopes } - | _ -> raise_unsupported_feature "unsupported item" (Pos.get_position use_item)) - ctxt use.scope_use_items - -let process_use_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = - match Pos.unmark item with - | ScopeDecl _ | StructDecl _ | EnumDecl _ -> ctxt - | ScopeUse use -> process_scope_use ctxt use - let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = let s_uid = Scopelang.Ast.StructName.fresh sdecl.struct_decl_name in let ctxt = @@ -382,6 +346,7 @@ let process_program_item (ctxt : context) (item : Ast.program_item) let form_context (prgm : Ast.program) : context = let empty_ctxt = { + local_var_idmap = Desugared.Ast.IdentMap.empty; scope_idmap = Desugared.Ast.IdentMap.empty; scopes = Scopelang.Ast.ScopeMap.empty; var_typs = Scopelang.Ast.ScopeVarMap.empty; @@ -398,9 +363,7 @@ let form_context (prgm : Ast.program) : context = (fun ctxt item -> process_program_item ctxt item process_decl_item) empty_ctxt prgm.program_items in - List.fold_left - (fun ctxt item -> process_program_item ctxt item process_use_item) - ctxt prgm.program_items + ctxt (** Get the variable uid inside the scope given in argument *) let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) diff --git a/tests/Makefile b/tests/Makefile index dd64d866..96b3920f 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -6,58 +6,24 @@ CATALA_OPTS?= CATALA=dune exec --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) -tests: $(wildcard */*.catala) +tests: $(wildcard */*.out) # Forces all the tests to be redone .FORCE: -*/*.catala: .FORCE -interpret_with_scope =\ - -$(CATALA) $(if $(filter $(1),nv),,-l $(1)) $@ -s $(2) +# Usage: make /.catala..out +# This rule runs the test and compares against the expected output. If the +# Catala program is /.catala and the scope to run is +# , then the expected output should be in the file +# /.catala..out +%.out: .FORCE + $(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) 2>&1 | \ + colordiff -u -b $@ - -interpret_with_scope_and_compare =\ - $(CATALA) $(if $(filter $(1),nv),,-l $(1)) --unstyled $@ -s $(2) 2>&1 | \ - colordiff -u -b $@.$(2).out - - -############################################ -# Tests have to be registered here -############################################ - -test_bool/test_bool.catala: - $(call interpret_with_scope_and_compare,nv,TestBool) - -test_func/recursive.catala: - $(call interpret_with_scope_and_compare,nv,RecursiveFunc) -test_func/func.catala: - $(call interpret_with_scope_and_compare,nv,S) - $(call interpret_with_scope_and_compare,nv,R) - -test_scope/cyclic_scopes.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_scope/scope.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_scope/cycle_in_scope.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_scope/sub_scope.catala: - $(call interpret_with_scope_and_compare,nv,A) - $(call interpret_with_scope_and_compare,nv,B) -test_scope/sub_sub_scope.catala: - $(call interpret_with_scope_and_compare,nv,A) - $(call interpret_with_scope_and_compare,nv,B) - $(call interpret_with_scope_and_compare,nv,C) -test_scope/grand_parent_caller.catala: - $(call interpret_with_scope_and_compare,nv,A) - $(call interpret_with_scope_and_compare,nv,B) - $(call interpret_with_scope_and_compare,nv,C) -test_scope/sub_vars_in_sub_var.catala: - $(call interpret_with_scope_and_compare,nv,A) - -test_struct/simple.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_struct/nested.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_struct/nested2.catala: - $(call interpret_with_scope_and_compare,nv,A) -test_struct/nested3.catala: - $(call interpret_with_scope_and_compare,nv,A) - $(call interpret_with_scope_and_compare,nv,B) \ No newline at end of file +# Usage: make /.catala..in +# This rule runs the test /.catala, prints its output and +# writes this output to the /.catala..out file +%.in: .FORCE + -$(CATALA) $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) + -$(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) \ + > $*.out 2>&1 \ No newline at end of file diff --git a/tests/test_enum/simple.catala b/tests/test_enum/simple.catala new file mode 100644 index 00000000..0c320ae7 --- /dev/null +++ b/tests/test_enum/simple.catala @@ -0,0 +1,17 @@ +@Article@ + +/* +new enum E: + -- Case1 type int + -- Case2 + +new scope A: + param x type E + param y type int + +scope A: + def x := Case1 of 2 + def y := match x with + -- Case1 of i : 42 + -- Case2 : 43 +*/ \ No newline at end of file From 15247aa28ac8a082f0a7e7c61835cdcf146faaa0 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 17:56:06 +0100 Subject: [PATCH 057/142] Pass simple test with enums --- src/catala/catala_surface/desugaring.ml | 35 +++++++++++-------------- src/catala/catala_surface/parser.mly | 5 ++-- tests/test_enum/simple.catala.A.out | 2 ++ 3 files changed, 20 insertions(+), 22 deletions(-) create mode 100644 tests/test_enum/simple.catala.A.out diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index c608cf4d..b6a780e3 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -222,31 +222,28 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (Pos.get_position constructor) ) ) | None -> Scopelang.Ast.EnumMap.choose possible_c_uids in - let ctxt, param_var = + let ctxt, (param_var, param_pos) = match binding with - | None -> (ctxt, None) + | None -> (ctxt, (Scopelang.Ast.Var.make ("_", Pos.no_pos), Pos.no_pos)) | Some param -> let ctxt, param_var = Name_resolution.add_def_local_var ctxt param in - (ctxt, Some (param_var, Pos.get_position param)) + (ctxt, (param_var, Pos.get_position param)) in let case_body = translate_expr scope def_key ctxt case.Ast.match_case_expr in + let e_binder = Bindlib.bind_mvar (Array.of_list [ param_var ]) case_body in let case_expr = - match param_var with - | None -> case_body - | Some (param_var, param_pos) -> - let e_binder = Bindlib.bind_mvar (Array.of_list [ param_var ]) case_body in - Bindlib.box_apply2 - (fun e_binder case_body -> - Pos.same_pos_as - (Scopelang.Ast.EAbs - ( param_pos, - e_binder, - [ - Scopelang.Ast.EnumConstructorMap.find c_uid - (Scopelang.Ast.EnumMap.find e_uid ctxt.Name_resolution.enums); - ] )) - case_body) - e_binder case_body + Bindlib.box_apply2 + (fun e_binder case_body -> + Pos.same_pos_as + (Scopelang.Ast.EAbs + ( param_pos, + e_binder, + [ + Scopelang.Ast.EnumConstructorMap.find c_uid + (Scopelang.Ast.EnumMap.find e_uid ctxt.Name_resolution.enums); + ] )) + case_body) + e_binder case_body in (Scopelang.Ast.EnumConstructorMap.add c_uid case_expr cases_d, Some e_uid) | _ :: _, _ -> diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index a355585f..6cb49f8b 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -116,7 +116,7 @@ struct_content_field: } enum_inject_content: -| CONTENT e = small_expression { e } +| OF e = small_expression { e } struct_or_enum_inject_content: | e = option(enum_inject_content) { EnumContent e } @@ -127,8 +127,7 @@ struct_or_enum_inject_content: struct_or_enum_inject: | c = constructor data = struct_or_enum_inject_content { match data with - | EnumContent data -> - (EnumInject (c, data), $sloc) + | EnumContent data -> (EnumInject (c, data), $sloc) | StructContent fields -> (StructLit (c, fields), $sloc) } diff --git a/tests/test_enum/simple.catala.A.out b/tests/test_enum/simple.catala.A.out new file mode 100644 index 00000000..9cf56e3e --- /dev/null +++ b/tests/test_enum/simple.catala.A.out @@ -0,0 +1,2 @@ +[RESULT] x -> Case1 2 +[RESULT] y -> 42 From 5abb73157fb499525174ae18b8c04cacdbb8c687 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 6 Dec 2020 18:09:48 +0100 Subject: [PATCH 058/142] Fix content/type lexer issue in nv --- src/catala/catala_surface/lexer.ml | 4 +- src/catala/catala_surface/parser.messages | 299 +++++++----------- src/catala/catala_surface/parser.mly | 2 +- src/catala/catala_surface/parser_errors.ml | 68 ++-- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 2 +- .../nv/vscode/syntaxes/catalavs.xml | 2 +- tests/test_bool/test_bool.catala | 4 +- tests/test_enum/simple.catala | 8 +- tests/test_func/func.catala | 8 +- tests/test_func/recursive.catala | 2 +- tests/test_scope/cycle_in_scope.catala | 6 +- tests/test_scope/cycle_in_scope.catala.A.out | 6 +- tests/test_scope/cyclic_scopes.catala | 4 +- tests/test_scope/grand_parent_caller.catala | 10 +- tests/test_scope/scope.catala | 6 +- tests/test_scope/sub_scope.catala | 10 +- tests/test_scope/sub_sub_scope.catala | 8 +- tests/test_scope/sub_vars_in_sub_var.catala | 4 +- tests/test_struct/nested.catala | 4 +- tests/test_struct/nested.catala.A.out | 2 +- tests/test_struct/nested2.catala | 8 +- tests/test_struct/nested2.catala.A.out | 2 +- tests/test_struct/nested3.catala | 14 +- tests/test_struct/simple.catala | 8 +- 26 files changed, 201 insertions(+), 294 deletions(-) diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index b4ec0294..1eada6a1 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -78,7 +78,7 @@ let token_list : (string * token) list = ("if", IF); ("then", THEN); ("else", ELSE); - ("type", CONTENT); + ("content", CONTENT); ("struct", STRUCT); ("option", OPTIONAL); ("assert", ASSERTION); @@ -205,7 +205,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "condition" -> update_acc lexbuf; CONDITION - | "type" -> + | "content" -> update_acc lexbuf; CONTENT | "struct" -> diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 71864ef0..68c30541 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -418,11 +418,11 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 49, spurious reduction of production primitive_expression -> CARDINAL ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## In state 209, spurious reduction of production assertion_base -> expression ## In state 210, spurious reduction of production assertion -> option(condition_consequence) assertion_base ## In state 211, spurious reduction of production scope_item -> ASSERTION assertion @@ -500,11 +500,11 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 49, spurious reduction of production primitive_expression -> CARDINAL ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## In state 170, spurious reduction of production condition -> UNDER_CONDITION expression ## @@ -784,7 +784,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## Ends in an error in state: 49. ## ## aggregate_func -> CARDINAL . [ FOR ] -## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CARDINAL @@ -792,99 +792,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION expected the keyword following cardinal to compute the number of elements in a set -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON CARDINAL ALT YEAR -## -## Ends in an error in state: 74. -## -## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RPAREN ] -## -## The known suffix of the stack is as follows: -## struct_content_field ALT -## - -expected another field of the struct - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON CARDINAL THEN -## -## Ends in an error in state: 73. -## -## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RPAREN ] -## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RPAREN ] -## -## The known suffix of the stack is as follows: -## struct_content_field -## -## WARNING: This example involves spurious reductions. -## This implies that, although the LR(1) items shown above provide an -## accurate view of the past (what has been recognized so far), they -## may provide an INCOMPLETE view of the future (what was expected next). -## In state 49, spurious reduction of production primitive_expression -> CARDINAL -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 109, spurious reduction of production struct_content_field -> ident COLON logical_expression -## - -expected another field of the struct or the end of the struct literal - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT COLON YEAR -## -## Ends in an error in state: 77. -## -## struct_content_field -> ident COLON . logical_expression [ RPAREN ALT ] -## -## The known suffix of the stack is as follows: -## ident COLON -## - -expected an expression for the field of the struct - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT IDENT YEAR -## -## Ends in an error in state: 76. -## -## struct_content_field -> ident . COLON logical_expression [ RPAREN ALT ] -## -## The known suffix of the stack is as follows: -## ident -## - -expected a colon and then the expression for the field of the struct - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN ALT YEAR -## -## Ends in an error in state: 72. -## -## struct_or_enum_inject_content -> CONTENT LPAREN ALT . separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## CONTENT LPAREN ALT -## - -expected the name of field of the struct that you are building - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT LPAREN YEAR -## -## Ends in an error in state: 71. -## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## struct_or_enum_inject_content -> CONTENT LPAREN . ALT separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## CONTENT LPAREN -## - -expected a struct field creation introduced by a dash - source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 135. +## Ends in an error in state: 117. ## -## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT small_expression @@ -894,10 +808,9 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 70. +## Ends in an error in state: 116. ## -## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## struct_or_enum_inject_content -> CONTENT . LPAREN ALT separated_nonempty_list(ALT,struct_content_field) RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT @@ -909,7 +822,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 69. ## -## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## constructor @@ -919,7 +832,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 125. +## Ends in an error in state: 132. ## ## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -931,7 +844,7 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 131. +## Ends in an error in state: 138. ## ## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -943,7 +856,7 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 130. +## Ends in an error in state: 137. ## ## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -961,7 +874,7 @@ expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 129. +## Ends in an error in state: 136. ## ## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -973,7 +886,7 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 128. +## Ends in an error in state: 135. ## ## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -985,7 +898,7 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 127. +## Ends in an error in state: 134. ## ## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -997,7 +910,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 118. +## Ends in an error in state: 125. ## ## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1009,7 +922,7 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 122. +## Ends in an error in state: 129. ## ## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1027,7 +940,7 @@ expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 121. +## Ends in an error in state: 128. ## ## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1039,7 +952,7 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 120. +## Ends in an error in state: 127. ## ## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1051,7 +964,7 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 119. +## Ends in an error in state: 126. ## ## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1075,7 +988,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 142. +## Ends in an error in state: 140. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1088,18 +1001,18 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 53, spurious reduction of production primitive_expression -> small_expression ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 145. +## Ends in an error in state: 143. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1111,7 +1024,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 144. +## Ends in an error in state: 142. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1124,18 +1037,18 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 53, spurious reduction of production primitive_expression -> small_expression ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 143. +## Ends in an error in state: 141. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1161,7 +1074,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 62. ## -## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## num_literal @@ -1171,9 +1084,9 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 133. +## Ends in an error in state: 145. ## -## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN expression @@ -1184,11 +1097,11 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 53, spurious reduction of production primitive_expression -> small_expression ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here @@ -1197,7 +1110,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 40. ## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN @@ -1238,10 +1151,10 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 53, spurious reduction of production primitive_expression -> small_expression ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 108, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 107, spurious reduction of production logical_expression -> logical_unop compare_expression ## In state 154, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## @@ -1348,7 +1261,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 50. ## -## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_unop @@ -1358,9 +1271,9 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 107. +## Ends in an error in state: 106. ## -## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## logical_unop @@ -1370,9 +1283,9 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 103. +## Ends in an error in state: 102. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression OF @@ -1382,9 +1295,9 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 102. +## Ends in an error in state: 101. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression @@ -1400,9 +1313,9 @@ expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 100. +## Ends in an error in state: 99. ## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN @@ -1412,9 +1325,9 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 99. +## Ends in an error in state: 98. ## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident @@ -1424,9 +1337,9 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 98. +## Ends in an error in state: 97. ## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR @@ -1436,9 +1349,9 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 97. +## Ends in an error in state: 96. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func @@ -1450,7 +1363,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 56. ## -## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression ARROW @@ -1473,11 +1386,11 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## may provide an INCOMPLETE view of the future (what was expected next). ## In state 53, spurious reduction of production primitive_expression -> small_expression ## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 91, spurious reduction of production mult_expression -> base_expression -## In state 86, spurious reduction of production sum_expression -> mult_expression -## In state 78, spurious reduction of production compare_expression -> sum_expression -## In state 110, spurious reduction of production logical_expression -> compare_expression -## In state 117, spurious reduction of production expression -> logical_expression +## In state 90, spurious reduction of production mult_expression -> base_expression +## In state 85, spurious reduction of production sum_expression -> mult_expression +## In state 77, spurious reduction of production compare_expression -> sum_expression +## In state 109, spurious reduction of production logical_expression -> compare_expression +## In state 124, spurious reduction of production expression -> logical_expression ## In state 162, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression ## In state 163, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## @@ -1488,7 +1401,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 54. ## -## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression DOT @@ -1498,9 +1411,9 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 140. +## Ends in an error in state: 122. ## -## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression IN @@ -1510,10 +1423,10 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 91. +## Ends in an error in state: 90. ## -## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression @@ -1530,9 +1443,9 @@ expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 94. +## Ends in an error in state: 93. ## -## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression mult_op @@ -1542,9 +1455,9 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 85. +## Ends in an error in state: 84. ## -## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_expression compare_op @@ -1556,7 +1469,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 61. ## -## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression OF @@ -1566,9 +1479,9 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 113. +## Ends in an error in state: 112. ## -## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## compare_expression logical_op @@ -1578,9 +1491,9 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 89. +## Ends in an error in state: 88. ## -## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## mult_expression sum_op @@ -1592,10 +1505,10 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 58. ## -## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression @@ -1613,7 +1526,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 59. ## -## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression WITH @@ -1625,9 +1538,9 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 53. ## -## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression @@ -1639,7 +1552,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 31. ## -## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV date_int @@ -1651,7 +1564,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 30. ## -## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV @@ -1663,7 +1576,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 29. ## -## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int @@ -1675,7 +1588,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 28. ## -## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV @@ -1687,7 +1600,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 27. ## -## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int @@ -1699,7 +1612,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 25. ## -## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 6cb49f8b..f0a6ddc1 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -116,7 +116,7 @@ struct_content_field: } enum_inject_content: -| OF e = small_expression { e } +| CONTENT e = small_expression { e } struct_or_enum_inject_content: | e = option(enum_inject_content) { EnumContent e } diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index f4d6dc7b..7427baca 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -27,24 +27,24 @@ let message s = | 53 -> "expected an operator to compose the expression on the left with\n" | 59 -> "expected an enum constructor to test if the expression on the left\n" | 58 -> "expected an operator to compose the expression on the left with\n" - | 89 -> "expected an expression on the right side of the sum or minus operator\n" - | 113 -> "expected an expression on the right side of the logical operator\n" + | 88 -> "expected an expression on the right side of the sum or minus operator\n" + | 112 -> "expected an expression on the right side of the logical operator\n" | 61 -> "expected an expression for the argument of this function call\n" - | 85 -> "expected an expression on the right side of the comparison operator\n" - | 94 -> "expected an expression on the right side of the multiplication or division operator\n" - | 91 -> "expected an operator to compose the expression on the left\n" - | 140 -> "expected an expression standing for the set you want to test for membership\n" + | 84 -> "expected an expression on the right side of the comparison operator\n" + | 93 -> "expected an expression on the right side of the multiplication or division operator\n" + | 90 -> "expected an operator to compose the expression on the left\n" + | 122 -> "expected an expression standing for the set you want to test for membership\n" | 54 -> "expected an identifier standing for a struct field or a subscope name\n" | 164 -> "expected a colon after the scope use precondition\n" | 56 -> "expected a constructor, to get the payload of this enum case\n" - | 97 -> "expected the \"for\" keyword to spell the aggregation\n" - | 98 -> "expected an identifier for the aggregation bound variable\n" - | 99 -> "expected the \"in\" keyword\n" - | 100 -> + | 96 -> "expected the \"for\" keyword to spell the aggregation\n" + | 97 -> "expected an identifier for the aggregation bound variable\n" + | 98 -> "expected the \"in\" keyword\n" + | 99 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 102 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 103 -> "expected an expression to compute its aggregation over the set\n" - | 107 -> "expected an expression to take the negation of\n" + | 101 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 102 -> "expected an expression to compute its aggregation over the set\n" + | 106 -> "expected an expression to take the negation of\n" | 50 -> "expected an expression to take the opposite of\n" | 39 -> "expected an expression to match with\n" | 148 -> "expected a pattern matching case\n" @@ -60,41 +60,35 @@ let message s = complete\n" | 147 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" | 40 -> "expected an expression inside the parenthesis\n" - | 133 -> "unmatched parenthesis that should have been closed by here\n" + | 145 -> "unmatched parenthesis that should have been closed by here\n" | 62 -> "expected a unit for this literal, or a valid operator to complete the expression \n" | 42 -> "expected an expression for the test of the conditional\n" - | 143 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 144 -> + | 141 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 142 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 145 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 142 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 143 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 140 -> "expected the \"then\" keyword as the conditional expression is complete\n" | 44 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 119 -> "expected an identifier for the bound variable of the universal test\n" - | 120 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 121 -> "expected the expression designating the set on which to perform the universal test\n" - | 122 -> "expected the \"we have\" keyword for this universal test\n" - | 118 -> "expected an expression for the universal test\n" - | 127 -> "expected an identifier that will designate the existential witness for the test\n" - | 128 -> "expected the \"in\" keyword to continue this existential test\n" - | 129 -> "expected an expression that designates the set subject to the existential test\n" - | 130 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 131 -> "expected a keyword to complete the \"such that\" construction\n" - | 125 -> "expected an expression for the existential test\n" + | 126 -> "expected an identifier for the bound variable of the universal test\n" + | 127 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 128 -> "expected the expression designating the set on which to perform the universal test\n" + | 129 -> "expected the \"we have\" keyword for this universal test\n" + | 125 -> "expected an expression for the universal test\n" + | 134 -> "expected an identifier that will designate the existential witness for the test\n" + | 135 -> "expected the \"in\" keyword to continue this existential test\n" + | 136 -> "expected an expression that designates the set subject to the existential test\n" + | 137 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 138 -> "expected a keyword to complete the \"such that\" construction\n" + | 132 -> "expected an expression for the existential test\n" | 69 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 70 -> "expected an expression for the content of this enum case\n" - | 135 -> + | 116 -> "expected an expression for the content of this enum case\n" + | 117 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 71 -> "expected a struct field creation introduced by a dash\n" - | 72 -> "expected the name of field of the struct that you are building\n" - | 76 -> "expected a colon and then the expression for the field of the struct\n" - | 77 -> "expected an expression for the field of the struct\n" - | 73 -> "expected another field of the struct or the end of the struct literal\n" - | 74 -> "expected another field of the struct\n" | 49 -> "expected the keyword following cardinal to compute the number of elements in a set\n" | 165 -> "expected a scope use item: a rule, definition or assertion\n" | 166 -> "expected the name of the variable subject to the rule\n" diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index 770c7d76..a069501c 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -100,7 +100,7 @@ 'name' : 'keyword.control.catala_nv' } { - 'match' : '\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b' + 'match' : '\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b' 'name' : 'keyword.other.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index c50ce05e..029ee140 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -213,7 +213,7 @@ code : context { } : pattern { - regex \= \b(scope|fun\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\b + regex \= \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\b styles [] = .keyword_rule ; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index fae75c8b..192c3c04 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -26,7 +26,7 @@ class CatalaNvLexer(RegexLexer): (u'(param)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(match|with|fixed|by|decreasing|increasing|varies|with\\s+param|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b', bygroups(Keyword.Reserved)), - (u'\\b(scope|fun\\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b', + (u'\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index bc8533f6..a3c13c45 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -161,7 +161,7 @@ match - \b(scope|fun\s+of|new|includes|set|type|option|struct|enum|param|rule|condition|data|ok|assert|def)\b + \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\b name keyword.other.catala_nv diff --git a/tests/test_bool/test_bool.catala b/tests/test_bool/test_bool.catala index 0ce58f64..0e40650f 100644 --- a/tests/test_bool/test_bool.catala +++ b/tests/test_bool/test_bool.catala @@ -2,8 +2,8 @@ /* new scope TestBool : - param foo type bool - param bar type int + param foo content bool + param bar content int scope TestBool : def bar := 1 diff --git a/tests/test_enum/simple.catala b/tests/test_enum/simple.catala index 0c320ae7..63a08612 100644 --- a/tests/test_enum/simple.catala +++ b/tests/test_enum/simple.catala @@ -2,15 +2,15 @@ /* new enum E: - -- Case1 type int + -- Case1 content int -- Case2 new scope A: - param x type E - param y type int + param x content E + param y content int scope A: - def x := Case1 of 2 + def x := Case1 content 2 def y := match x with -- Case1 of i : 42 -- Case2 : 43 diff --git a/tests/test_func/func.catala b/tests/test_func/func.catala index 979f2e83..084549f7 100644 --- a/tests/test_func/func.catala +++ b/tests/test_func/func.catala @@ -2,13 +2,13 @@ /* new scope S: - param f type int fun of int - param b type bool - param out type int + param f content int fun of int + param b content bool + param out content int new scope R: param s scope S - param r type int + param r content int scope S: def f of x [ (x >= x) ] := x + x diff --git a/tests/test_func/recursive.catala b/tests/test_func/recursive.catala index c522aa95..870af172 100644 --- a/tests/test_func/recursive.catala +++ b/tests/test_func/recursive.catala @@ -2,7 +2,7 @@ /* new scope RecursiveFunc: - param f type int fun of int + param f content int fun of int scope RecursiveFunc: def f of x := f of x + 1 diff --git a/tests/test_scope/cycle_in_scope.catala b/tests/test_scope/cycle_in_scope.catala index 445b73fd..94b1bb43 100644 --- a/tests/test_scope/cycle_in_scope.catala +++ b/tests/test_scope/cycle_in_scope.catala @@ -2,9 +2,9 @@ /* new scope A : - param x type int - param y type int - param z type int + param x content int + param y content int + param z content int scope A: def y [x < 0] := - x diff --git a/tests/test_scope/cycle_in_scope.catala.A.out b/tests/test_scope/cycle_in_scope.catala.A.out index a47e7e2f..56338bb3 100644 --- a/tests/test_scope/cycle_in_scope.catala.A.out +++ b/tests/test_scope/cycle_in_scope.catala.A.out @@ -3,7 +3,7 @@ [ERROR] Cycle variable z, declared: [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | -[ERROR] 7 | param z type int +[ERROR] 7 | param z content int [ERROR] | ^ [ERROR] [ERROR] Used here in the definition of another cycle variable x: @@ -15,7 +15,7 @@ [ERROR] Cycle variable y, declared: [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | -[ERROR] 6 | param y type int +[ERROR] 6 | param y content int [ERROR] | ^ [ERROR] [ERROR] Used here in the definition of another cycle variable z: @@ -27,7 +27,7 @@ [ERROR] Cycle variable x, declared: [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | -[ERROR] 5 | param x type int +[ERROR] 5 | param x content int [ERROR] | ^ [ERROR] [ERROR] Used here in the definition of another cycle variable y: diff --git a/tests/test_scope/cyclic_scopes.catala b/tests/test_scope/cyclic_scopes.catala index e33d61d2..e0304a1b 100644 --- a/tests/test_scope/cyclic_scopes.catala +++ b/tests/test_scope/cyclic_scopes.catala @@ -3,11 +3,11 @@ /* new scope A: param b scope B - param x type int + param x content int new scope B: param a scope A - param y type int + param y content int scope A: def x := b.y diff --git a/tests/test_scope/grand_parent_caller.catala b/tests/test_scope/grand_parent_caller.catala index 16da5e70..2efdee05 100644 --- a/tests/test_scope/grand_parent_caller.catala +++ b/tests/test_scope/grand_parent_caller.catala @@ -2,17 +2,17 @@ /* new scope A: - param x type int + param x content int new scope B: param a scope A - param y1 type int - param y2 type int + param y1 content int + param y2 content int new scope C: param b scope B - param z1 type int - param z2 type int + param z1 content int + param z2 content int scope A: diff --git a/tests/test_scope/scope.catala b/tests/test_scope/scope.catala index d2bd8eb7..10e3ddcd 100644 --- a/tests/test_scope/scope.catala +++ b/tests/test_scope/scope.catala @@ -2,9 +2,9 @@ /* new scope A: - param a type int - param b type int - param c type bool + param a content int + param b content int + param c content bool scope A: def c := false diff --git a/tests/test_scope/sub_scope.catala b/tests/test_scope/sub_scope.catala index 90ff514d..2d58c3d5 100644 --- a/tests/test_scope/sub_scope.catala +++ b/tests/test_scope/sub_scope.catala @@ -2,13 +2,13 @@ /* new scope A: - param a type int - param b type bool - param a_base type int + param a content int + param b content bool + param a_base content int new scope B: - param a type int - param b type bool + param a content int + param b content bool param scopeA scope A param scopeAbis scope A diff --git a/tests/test_scope/sub_sub_scope.catala b/tests/test_scope/sub_sub_scope.catala index 06ff9cfd..18517730 100644 --- a/tests/test_scope/sub_sub_scope.catala +++ b/tests/test_scope/sub_sub_scope.catala @@ -2,18 +2,18 @@ /* new scope A: - param x type int - param u type bool + param x content int + param u content bool new scope B: param a1 scope A param a2 scope A - param y type int + param y content int new scope C: param a scope A param b scope B - param z type int + param z content int scope A: def x := 0 diff --git a/tests/test_scope/sub_vars_in_sub_var.catala b/tests/test_scope/sub_vars_in_sub_var.catala index 5a59fad2..d881254d 100644 --- a/tests/test_scope/sub_vars_in_sub_var.catala +++ b/tests/test_scope/sub_vars_in_sub_var.catala @@ -2,8 +2,8 @@ /* new scope A: - param x type bool - param y type int + param x content bool + param y content int new scope B: param a scope A diff --git a/tests/test_struct/nested.catala b/tests/test_struct/nested.catala index 0f485b72..040f8f83 100644 --- a/tests/test_struct/nested.catala +++ b/tests/test_struct/nested.catala @@ -2,10 +2,10 @@ /* new struct S: - data x type S + data x content S new scope A: - param y type S + param y content S scope A: def y := S { -- x: 1 } diff --git a/tests/test_struct/nested.catala.A.out b/tests/test_struct/nested.catala.A.out index 142af226..9161e374 100644 --- a/tests/test_struct/nested.catala.A.out +++ b/tests/test_struct/nested.catala.A.out @@ -2,5 +2,5 @@ [ERROR] [ERROR] --> test_struct/nested.catala [ERROR] | -[ERROR] 5 | data x type S +[ERROR] 5 | data x content S [ERROR] | ^ diff --git a/tests/test_struct/nested2.catala b/tests/test_struct/nested2.catala index f2c26af1..0d15daff 100644 --- a/tests/test_struct/nested2.catala +++ b/tests/test_struct/nested2.catala @@ -2,10 +2,10 @@ /* new struct S: - data x type E - data y type int + data x content E + data y content int new enum E: - -- Case1 type bool - -- Case2 type S + -- Case1 content bool + -- Case2 content S */ \ No newline at end of file diff --git a/tests/test_struct/nested2.catala.A.out b/tests/test_struct/nested2.catala.A.out index a2324089..22ce0bdc 100644 --- a/tests/test_struct/nested2.catala.A.out +++ b/tests/test_struct/nested2.catala.A.out @@ -2,5 +2,5 @@ [ERROR] [ERROR] --> test_struct/nested2.catala [ERROR] | -[ERROR] 5 | data x type E +[ERROR] 5 | data x content E [ERROR] | ^ diff --git a/tests/test_struct/nested3.catala b/tests/test_struct/nested3.catala index 6d7a47b2..a153e36c 100644 --- a/tests/test_struct/nested3.catala +++ b/tests/test_struct/nested3.catala @@ -2,20 +2,20 @@ /* new struct S: - data x type int - data y type bool + data x content int + data y content bool new struct T: - data a type S - data b type S + data a content S + data b content S new scope A: - param t type T + param t content T new scope B: - param t type T + param t content T param a scope A - param out type int + param out content int scope A: def t := T { diff --git a/tests/test_struct/simple.catala b/tests/test_struct/simple.catala index 254e121a..c052201c 100644 --- a/tests/test_struct/simple.catala +++ b/tests/test_struct/simple.catala @@ -2,12 +2,12 @@ /* new struct S: - data x type int - data y type int + data x content int + data y content int new scope A: - param s type S - param z type int + param s content S + param z content int scope A: def s := S { From 5ff7d78a9e727333b38638607d811f03c418e99d Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 10:36:09 +0100 Subject: [PATCH 059/142] Fixed various edge cases of enums --- src/catala/catala_surface/desugaring.ml | 58 +++++++++++++++------ src/catala/default_calculus/interpreter.ml | 1 + src/catala/desugared/ast.ml | 11 ---- src/catala/desugared/desugared_to_scope.ml | 37 ++++++------- src/catala/scope_language/scope_to_dcalc.ml | 3 +- tests/test_enum/duplicate_case.catala | 19 +++++++ tests/test_enum/duplicate_case.catala.A.out | 11 ++++ tests/test_enum/missing_case.catala | 18 +++++++ tests/test_enum/missing_case.catala.A.out | 10 ++++ tests/test_enum/too_many_cases.catala | 22 ++++++++ tests/test_enum/too_many_cases.catala.A.out | 6 +++ 11 files changed, 148 insertions(+), 48 deletions(-) create mode 100644 tests/test_enum/duplicate_case.catala create mode 100644 tests/test_enum/duplicate_case.catala.A.out create mode 100644 tests/test_enum/missing_case.catala create mode 100644 tests/test_enum/missing_case.catala.A.out create mode 100644 tests/test_enum/too_many_cases.catala create mode 100644 tests/test_enum/too_many_cases.catala.A.out diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index b6a780e3..3159d0c7 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -144,6 +144,14 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (Pos.unmark s_name)) (Pos.get_position f_name) in + ( match Scopelang.Ast.StructFieldMap.find_opt f_uid s_fields with + | None -> () + | Some e_field -> + Errors.raise_multispanned_error + (Format.asprintf "The field %a has been defined twice:" + Scopelang.Ast.StructFieldName.format_t f_uid) + [ (None, Pos.get_position f_e); (None, Pos.get_position (Bindlib.unbox e_field)) ] + ); let f_e = translate_expr scope def_key ctxt f_e in Scopelang.Ast.StructFieldMap.add f_uid f_e s_fields) Scopelang.Ast.StructFieldMap.empty fields @@ -222,6 +230,16 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (Pos.get_position constructor) ) ) | None -> Scopelang.Ast.EnumMap.choose possible_c_uids in + ( match Scopelang.Ast.EnumConstructorMap.find_opt c_uid cases_d with + | None -> () + | Some e_case -> + Errors.raise_multispanned_error + (Format.asprintf "The constructor %a has been matched twice:" + Scopelang.Ast.EnumConstructor.format_t c_uid) + [ + (None, Pos.get_position case.match_case_expr); + (None, Pos.get_position (Bindlib.unbox e_case)); + ] ); let ctxt, (param_var, param_pos) = match binding with | None -> (ctxt, (Scopelang.Ast.Var.make ("_", Pos.no_pos), Pos.no_pos)) @@ -397,25 +415,12 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.pro (use : Ast.scope_use) : Desugared.Ast.program = let name = fst use.scope_use_name in let scope_uid = Desugared.Ast.IdentMap.find name ctxt.scope_idmap in - let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - let scope_vars = - List.fold_left - (fun acc (_, var) -> Scopelang.Ast.ScopeVarSet.add var acc) - Scopelang.Ast.ScopeVarSet.empty - (Desugared.Ast.IdentMap.bindings scope_ctxt.var_idmap) - in (* Make sure the scope exists *) let prgm = match Scopelang.Ast.ScopeMap.find_opt scope_uid prgm.program_scopes with | Some _ -> prgm - | None -> - { - prgm with - program_scopes = - Scopelang.Ast.ScopeMap.add scope_uid - (Desugared.Ast.empty_scope scope_uid scope_vars scope_ctxt.sub_scopes) - prgm.program_scopes; - } + | None -> assert false + (* should not happen *) in let precond = use.scope_use_condition in List.fold_left (process_scope_use_item precond scope_uid ctxt) prgm use.scope_use_items @@ -430,7 +435,28 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desu Desugared.Ast.program_enums = Scopelang.Ast.EnumMap.map Scopelang.Ast.EnumConstructorMap.bindings ctxt.Name_resolution.enums; - Desugared.Ast.program_scopes = Scopelang.Ast.ScopeMap.empty; + Desugared.Ast.program_scopes = + Scopelang.Ast.ScopeMap.mapi + (fun s_uid s_context -> + { + Desugared.Ast.scope_vars = + Desugared.Ast.IdentMap.fold + (fun _ v acc -> Scopelang.Ast.ScopeVarSet.add v acc) + s_context.Name_resolution.var_idmap Scopelang.Ast.ScopeVarSet.empty; + Desugared.Ast.scope_sub_scopes = s_context.Name_resolution.sub_scopes; + Desugared.Ast.scope_defs = + Desugared.Ast.IdentMap.fold + (fun _ v acc -> + Desugared.Ast.ScopeDefMap.add (Desugared.Ast.ScopeDef.Var v) + ( Desugared.Ast.RuleMap.empty, + Scopelang.Ast.ScopeVarMap.find v ctxt.Name_resolution.var_typs ) + acc) + s_context.Name_resolution.var_idmap Desugared.Ast.ScopeDefMap.empty; + Desugared.Ast.scope_assertions = []; + Desugared.Ast.scope_meta_assertions = []; + Desugared.Ast.scope_uid = s_uid; + }) + ctxt.Name_resolution.scopes; } in let processer_article_item (prgm : Desugared.Ast.program) (item : Ast.law_article_item) : diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index b85b8363..e89d9b1e 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -121,6 +121,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = in let new_e = Pos.same_pos_as (A.EApp (es_n, [ e1 ])) e in evaluate_expr new_e + | A.ELit A.LEmptyError -> Pos.same_pos_as (A.ELit A.LEmptyError) e | _ -> Errors.raise_spanned_error "Expected a term having a sum type as an argument to a match (should not happend if \ diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 03c21b85..4d7f6cc1 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -89,17 +89,6 @@ type scope = { scope_meta_assertions : meta_assertion list; } -let empty_scope (scope_uid : Scopelang.Ast.ScopeName.t) (scope_vars : Scopelang.Ast.ScopeVarSet.t) - (scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t) : scope = - { - scope_uid; - scope_vars; - scope_sub_scopes; - scope_defs = ScopeDefMap.empty; - scope_assertions = []; - scope_meta_assertions = []; - } - type program = { program_scopes : scope Scopelang.Ast.ScopeMap.t; program_enums : Scopelang.Ast.enum_ctx; diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index abcc3440..56fe0382 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -83,7 +83,8 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti (* should not happen *) -let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked = +let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) + (typ : Scopelang.Ast.typ Pos.marked) : Scopelang.Ast.expr Pos.marked = (* Here, we have to transform this list of rules into a default tree. *) (* Because we can have multiple rules at the top-level and our syntax does not allow that, we insert a dummy rule at the top *) @@ -91,23 +92,15 @@ let translate_def (def : Ast.rule Ast.RuleMap.t) : Scopelang.Ast.expr Pos.marked let all_rules_func = Ast.RuleMap.for_all is_func def in let all_rules_not_func = Ast.RuleMap.for_all (fun n r -> not (is_func n r)) def in let is_def_func : Scopelang.Ast.typ Pos.marked option = - if all_rules_func then - let typ = (snd (Ast.RuleMap.choose def)).Ast.parameter in - match typ with - | Some (_, typ) -> - let is_typ _ r = snd (Option.get r.Ast.parameter) = typ in - if Ast.RuleMap.for_all is_typ def then Some typ - else - Errors.raise_multispanned_error - "the type of these parameters should be the same, but they are different" - (List.map - (fun (_, r) -> - ( Some - (Format.asprintf "The type of the parameter of this expression is %a" - Scopelang.Print.format_typ typ), - Pos.get_position (Bindlib.unbox r.Ast.cons) )) - (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_typ n r)) def))) - | None -> assert false (* should not happen *) + if all_rules_func && Ast.RuleMap.cardinal def > 0 then + match Pos.unmark typ with + | Scopelang.Ast.TArrow (t_param, _) -> Some t_param + | _ -> + Errors.raise_spanned_error + (Format.asprintf + "The definitions of %a are function but its type, %a, is not a function type" + Ast.ScopeDef.format_t def_info Scopelang.Print.format_typ typ) + (Pos.get_position typ) else if all_rules_not_func then None else Errors.raise_multispanned_error @@ -149,10 +142,14 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = (fun vertex -> match vertex with | Dependency.Vertex.Var (var : Scopelang.Ast.ScopeVar.t) -> + (* Cli.debug_print (Format.asprintf "Finding %a in %a" + Scopelang.Ast.ScopeVar.format_t var (Format.pp_print_list ~pp_sep:(fun fmt () -> + Format.fprintf fmt ", ") (fun fmt (d, _) -> Format.fprintf fmt "%a" + Ast.ScopeDef.format_t d)) (Ast.ScopeDefMap.bindings scope.scope_defs)); *) let var_def, var_typ = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in - let expr_def = translate_def var_def in + let expr_def = translate_def (Ast.ScopeDef.Var var) var_def var_typ in [ Scopelang.Ast.Definition ( ( Scopelang.Ast.ScopeVar @@ -173,7 +170,7 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = match def_key with | Ast.ScopeDef.Var _ -> assert false (* should not happen *) | Ast.ScopeDef.SubScopeVar (_, sub_scope_var) -> - let expr_def = translate_def def in + let expr_def = translate_def def_key def def_typ in let subscop_real_name = Scopelang.Ast.SubScopeMap.find sub_scope_index scope.scope_sub_scopes in diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 4d36a51c..01345b4e 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -158,7 +158,8 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po try Ast.EnumConstructorMap.find constructor e_cases with Not_found -> Errors.raise_spanned_error - (Format.asprintf "The constructor %a does not belong to the enum %a" + (Format.asprintf + "The constructor %a of enum %a is missing from this pattern matching" Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) (Pos.get_position e) in diff --git a/tests/test_enum/duplicate_case.catala b/tests/test_enum/duplicate_case.catala new file mode 100644 index 00000000..849fad2b --- /dev/null +++ b/tests/test_enum/duplicate_case.catala @@ -0,0 +1,19 @@ +@Article@ + +/* +new enum E: + -- Case1 content int + -- Case2 content bool + -- Case3 + +new scope A: + param e content E + param out content bool + +scope A: + def out := match e with + -- Case1 of i : i = 0 + -- Case2 of b : b + -- Case3 : false + -- Case3 : true +*/ \ No newline at end of file diff --git a/tests/test_enum/duplicate_case.catala.A.out b/tests/test_enum/duplicate_case.catala.A.out new file mode 100644 index 00000000..448e6722 --- /dev/null +++ b/tests/test_enum/duplicate_case.catala.A.out @@ -0,0 +1,11 @@ +[ERROR] The constructor Case3 has been matched twice: +[ERROR] +[ERROR] --> test_enum/duplicate_case.catala +[ERROR] | +[ERROR] 18 | -- Case3 : true +[ERROR] | ^^^^ +[ERROR] +[ERROR] --> test_enum/duplicate_case.catala +[ERROR] | +[ERROR] 17 | -- Case3 : false +[ERROR] | ^^^^^ diff --git a/tests/test_enum/missing_case.catala b/tests/test_enum/missing_case.catala new file mode 100644 index 00000000..5e7dc16e --- /dev/null +++ b/tests/test_enum/missing_case.catala @@ -0,0 +1,18 @@ +@Article@ + +/* +new enum E: + -- Case1 content int + -- Case2 content bool + -- Case3 + +new scope A: + param e content E + param out content bool + +scope A: + def out := match e with + -- Case1 of i : i = 0 + -- Case2 of b : b +*/ + diff --git a/tests/test_enum/missing_case.catala.A.out b/tests/test_enum/missing_case.catala.A.out new file mode 100644 index 00000000..92779b77 --- /dev/null +++ b/tests/test_enum/missing_case.catala.A.out @@ -0,0 +1,10 @@ +[ERROR] The constructor Case3 of enum E is missing from this pattern matching +[ERROR] +[ERROR] --> test_enum/missing_case.catala +[ERROR] | +[ERROR] 14 | def out := match e with +[ERROR] | ^^^^^^^^^^^^ +[ERROR] 15 | -- Case1 of i : i = 0 +[ERROR] | ^^^^^^^^^^^^^^^^^^^^^ +[ERROR] 16 | -- Case2 of b : b +[ERROR] | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/test_enum/too_many_cases.catala b/tests/test_enum/too_many_cases.catala new file mode 100644 index 00000000..7621f830 --- /dev/null +++ b/tests/test_enum/too_many_cases.catala @@ -0,0 +1,22 @@ +@Article@ + +/* +new enum E: + -- Case1 content int + -- Case2 content bool + -- Case3 + +new enum F: + -- Case4 + +new scope A: + param e content E + param out content bool + +scope A: + def out := match e with + -- Case1 of i : i = 0 + -- Case2 of b : b + -- Case3 : false + -- Case4 : true +*/ \ No newline at end of file diff --git a/tests/test_enum/too_many_cases.catala.A.out b/tests/test_enum/too_many_cases.catala.A.out new file mode 100644 index 00000000..4edfc3ba --- /dev/null +++ b/tests/test_enum/too_many_cases.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] This constructor is not part of the E enumeration +[ERROR] +[ERROR] --> test_enum/too_many_cases.catala +[ERROR] | +[ERROR] 21 | -- Case4 : true +[ERROR] | ^^^^^ From 170bd7685fa3eaa82911fc4f72370d9959f166c3 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 11:23:03 +0100 Subject: [PATCH 060/142] Added error when a scope variable evaluates to empty --- src/catala/catala_surface/lexer.ml | 14 ++++++++++---- src/catala/catala_surface/lexer_en.ml | 8 ++++++-- src/catala/catala_surface/lexer_fr.ml | 8 ++++++-- src/catala/catala_surface/parser_driver.ml | 2 +- src/catala/default_calculus/ast.ml | 2 +- src/catala/default_calculus/interpreter.ml | 9 +++++++++ src/catala/default_calculus/print.ml | 3 ++- src/catala/default_calculus/typing.ml | 1 + src/catala/scope_language/scope_to_dcalc.ml | 9 +++++++++ tests/test_default/conflict.catala | 10 ++++++++++ tests/test_default/conflict.catala.A.out | 13 +++++++++++++ tests/test_default/empty.catala | 10 ++++++++++ tests/test_default/empty.catala.A.out | 6 ++++++ tests/test_default/empty_with_rules.catala | 13 +++++++++++++ tests/test_default/empty_with_rules.catala.A.out | 6 ++++++ 15 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 tests/test_default/conflict.catala create mode 100644 tests/test_default/conflict.catala.A.out create mode 100644 tests/test_default/empty.catala create mode 100644 tests/test_default/empty.catala.A.out create mode 100644 tests/test_default/empty_with_rules.catala create mode 100644 tests/test_default/empty_with_rules.catala.A.out diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 1eada6a1..4d5ddea2 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -24,8 +24,10 @@ let code_string_acc : string ref = ref "" let update_acc (lexbuf : lexbuf) : unit = code_string_acc := !code_string_acc ^ Utf8.lexeme lexbuf -let raise_lexer_error (loc : Pos.t) (token : string) (msg : string) = - Errors.raise_spanned_error (Printf.sprintf "Parsing error on token \"%s\": %s" token msg) loc +let raise_lexer_error (loc : Pos.t) (token : string) = + Errors.raise_spanned_error + (Printf.sprintf "Parsing error after token \"%s\": what comes after is unknown" token) + loc let token_list_language_agnostic : (string * token) list = [ @@ -105,6 +107,8 @@ let token_list : (string * token) list = @ token_list_language_agnostic let rec lex_code (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | white_space -> (* Whitespaces *) @@ -366,9 +370,11 @@ let rec lex_code (lexbuf : lexbuf) : token = (* Integer literal*) update_acc lexbuf; INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) - | _ -> raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> raise_lexer_error prev_pos prev_lexeme let lex_law (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | "/*" -> is_code := true; @@ -423,6 +429,6 @@ let lex_law (lexbuf : lexbuf) : token = LAW_ARTICLE (title, None, None) | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) - | _ -> raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> raise_lexer_error prev_pos prev_lexeme let lexer lexbuf = if !is_code then lex_code lexbuf else lex_law lexbuf diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index fed03b2c..56c0012f 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -75,6 +75,8 @@ let token_list_en : (string * token) list = @ L.token_list_language_agnostic let rec lex_code_en (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | white_space -> (* Whitespaces *) @@ -336,9 +338,11 @@ let rec lex_code_en (lexbuf : lexbuf) : token = (* Integer literal*) L.update_acc lexbuf; INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) - | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> L.raise_lexer_error prev_pos prev_lexeme let lex_law_en (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | "/*" -> L.is_code := true; @@ -393,6 +397,6 @@ let lex_law_en (lexbuf : lexbuf) : token = LAW_ARTICLE (title, None, None) | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) - | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> L.raise_lexer_error prev_pos prev_lexeme let lexer_en lexbuf = if !L.is_code then lex_code_en lexbuf else lex_law_en lexbuf diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index acd61889..7b9c2f62 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -75,6 +75,8 @@ let token_list_fr : (string * token) list = @ L.token_list_language_agnostic let rec lex_code_fr (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | white_space | '\n' -> (* Whitespaces *) @@ -345,9 +347,11 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = (* Integer literal*) L.update_acc lexbuf; INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) - | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> L.raise_lexer_error prev_pos prev_lexeme let lex_law_fr (lexbuf : lexbuf) : token = + let prev_lexeme = Utf8.lexeme lexbuf in + let prev_pos = lexing_positions lexbuf in match%sedlex lexbuf with | "/*" -> L.is_code := true; @@ -417,7 +421,7 @@ let lex_law_fr (lexbuf : lexbuf) : token = LAW_ARTICLE (title, article_id, article_expiration_date) | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) - | _ -> L.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "unknown token" + | _ -> L.raise_lexer_error prev_pos prev_lexeme let lexer_fr (lexbuf : lexbuf) : token = if !L.is_code then lex_code_fr lexbuf else lex_law_fr lexbuf diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index 5f66f610..e138409b 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -151,7 +151,7 @@ let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * in try loop lexer token_list lexbuf None (target_rule (fst @@ Sedlexing.lexing_positions lexbuf)) with Sedlexing.MalFormed | Sedlexing.InvalidCodepoint _ -> - Lexer.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) "malformed token" + Lexer.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) let rec parse_source_files (source_files : string list) (language : Cli.frontend_lang) : Ast.program = diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index c3909cd5..905f5a7f 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -27,7 +27,7 @@ type lit = LBool of bool | LEmptyError | LInt of Int64.t | LUnit type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq -type unop = Not | Minus +type unop = Not | Minus | ErrorOnEmpty type operator = Binop of binop | Unop of unop diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index e89d9b1e..d736c12e 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -47,8 +47,17 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) + | A.Binop _, ([ ELit LEmptyError; _ ] | [ _; ELit LEmptyError ]) -> A.ELit LEmptyError | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) | A.Unop A.Minus, [ ELit (LInt i) ] -> A.ELit (LInt (Int64.sub Int64.zero i)) + | A.Unop A.ErrorOnEmpty, [ e' ] -> + if e' = A.ELit LEmptyError then + Errors.raise_spanned_error + "This variable evaluated to an empty term (no rule that defined it applied in this \ + situation)" + (Pos.get_position op) + else e' + | A.Unop _, [ ELit LEmptyError ] -> A.ELit LEmptyError | _ -> Errors.raise_multispanned_error "operator applied to the wrong arguments (should not happen if the term was well-typed)" diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 39b95de2..cfe4ba7b 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -62,7 +62,8 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = | Gte -> ">=" ) let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = - Format.fprintf fmt "%s" (match Pos.unmark op with Minus -> "-" | Not -> "~") + Format.fprintf fmt "%s" + (match Pos.unmark op with Minus -> "-" | Not -> "~" | ErrorOnEmpty -> "error_on_empty") let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ -> true | _ -> false diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 30e58bad..578b330b 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -85,6 +85,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) | A.Unop A.Minus -> arr it it | A.Unop A.Not -> arr bt bt + | A.Unop A.ErrorOnEmpty -> arr any any let rec ast_to_typ (ty : A.typ) : typ = match ty with diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 01345b4e..baddd0f9 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -253,6 +253,15 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let new_e = translate_expr ctx e in + let new_e = + Bindlib.box_apply + (fun new_e -> + ( Dcalc.Ast.EApp + ( (Dcalc.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.ErrorOnEmpty), Pos.get_position a_name), + [ new_e ] ), + Pos.get_position new_e )) + new_e + in let a_expr = Dcalc.Ast.make_var (a_var, var_def_pos) in let merged_expr = merge_defaults a_expr new_e in let next_e = Dcalc.Ast.make_let_in a_var tau merged_expr next_e in diff --git a/tests/test_default/conflict.catala b/tests/test_default/conflict.catala new file mode 100644 index 00000000..6b5c588f --- /dev/null +++ b/tests/test_default/conflict.catala @@ -0,0 +1,10 @@ +@Article@ + +/* +new scope A: + param x content int + +scope A: + def x [true] := 1 + def x [true] := 0 +*/ \ No newline at end of file diff --git a/tests/test_default/conflict.catala.A.out b/tests/test_default/conflict.catala.A.out new file mode 100644 index 00000000..d9df4b10 --- /dev/null +++ b/tests/test_default/conflict.catala.A.out @@ -0,0 +1,13 @@ +[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] +[ERROR] This justification is true: +[ERROR] --> test_default/conflict.catala +[ERROR] | +[ERROR] 8 | def x [true] := 1 +[ERROR] | ^^^^ +[ERROR] +[ERROR] This justification is true: +[ERROR] --> test_default/conflict.catala +[ERROR] | +[ERROR] 9 | def x [true] := 0 +[ERROR] | ^^^^ diff --git a/tests/test_default/empty.catala b/tests/test_default/empty.catala new file mode 100644 index 00000000..27d15da0 --- /dev/null +++ b/tests/test_default/empty.catala @@ -0,0 +1,10 @@ +@Article@ + +/* +new scope A: + param x content int + param y content bool + +scope A: + def x := 1 +*/ \ No newline at end of file diff --git a/tests/test_default/empty.catala.A.out b/tests/test_default/empty.catala.A.out new file mode 100644 index 00000000..2224a80b --- /dev/null +++ b/tests/test_default/empty.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] This variable evaluated to an empty term (no rule that defined it applied in this situation) +[ERROR] +[ERROR] --> test_default/empty.catala +[ERROR] | +[ERROR] 6 | param y content bool +[ERROR] | ^ diff --git a/tests/test_default/empty_with_rules.catala b/tests/test_default/empty_with_rules.catala new file mode 100644 index 00000000..355136ba --- /dev/null +++ b/tests/test_default/empty_with_rules.catala @@ -0,0 +1,13 @@ +@Article@ + +/* +new scope A: + param x content int + param y content int + +scope A: + def y := 1 + def x [y = 2] := 1 + def x [y = 3] := 1 + def x [y = 4] := 1 +*/ \ No newline at end of file diff --git a/tests/test_default/empty_with_rules.catala.A.out b/tests/test_default/empty_with_rules.catala.A.out new file mode 100644 index 00000000..1d355dd6 --- /dev/null +++ b/tests/test_default/empty_with_rules.catala.A.out @@ -0,0 +1,6 @@ +[ERROR] This variable evaluated to an empty term (no rule that defined it applied in this situation) +[ERROR] +[ERROR] --> test_default/empty_with_rules.catala +[ERROR] | +[ERROR] 5 | param x content int +[ERROR] | ^ From 2e928f5629deaf26a4a06a3a906ccad22cacf818 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 11:38:04 +0100 Subject: [PATCH 061/142] Fixed typing bug --- src/catala/default_calculus/typing.ml | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 578b330b..24fe1721 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -35,7 +35,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TInt -> Format.fprintf fmt "int" - | TAny -> Format.fprintf fmt "α" + | TAny -> Format.fprintf fmt "any type" | TTuple ts -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " * ") format_typ) @@ -231,9 +231,15 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) let tau' = UnionFind.get (UnionFind.find tau) in match Pos.unmark tau' with | TTuple ts -> List.iter2 (fun (e, _) t -> typecheck_expr_top_down env e t) es ts + | TAny -> + unify tau + (UnionFind.make + (Pos.same_pos_as + (TTuple (List.map (fun (arg, _) -> typecheck_expr_bottom_up env arg) es)) + e)) | _ -> Errors.raise_spanned_error - (Format.asprintf "exprected %a, got a tuple" format_typ tau) + (Format.asprintf "expected %a, got a tuple" format_typ tau) (Pos.get_position e) ) | ETupleAccess (e1, n, _) -> ( let t1 = typecheck_expr_bottom_up env e1 in @@ -247,9 +253,15 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) "expression should have a tuple type with at least %d elements but only has %d" n (List.length t1s)) (Pos.get_position e1) ) + | TAny -> + (* Include total number of cases in ETupleAccess to continue typechecking at this point *) + Errors.raise_spanned_error + "The precise type of this expression cannot be inferred.\n\ + Please raise an issue one https://github.com/CatalaLang/catala/issues" + (Pos.get_position e1) | _ -> Errors.raise_spanned_error - (Format.asprintf "exprected a tuple , got %a" format_typ tau) + (Format.asprintf "expected a tuple , got %a" format_typ tau) (Pos.get_position e) ) | EInj (e1, n, _, ts) -> let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in From ae05498049b13c5ce469b7194eb3647ec80f8239 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 12:20:20 +0100 Subject: [PATCH 062/142] Added support for decimals --- src/catala/catala_surface/desugaring.ml | 13 ++++++++++++- src/catala/catala_surface/dune | 2 +- src/catala/catala_surface/name_resolution.ml | 3 ++- src/catala/default_calculus/ast.ml | 3 ++- src/catala/default_calculus/dune | 2 +- src/catala/default_calculus/interpreter.ml | 16 ++++++++++++++++ src/catala/default_calculus/print.ml | 2 ++ src/catala/default_calculus/typing.ml | 16 +++++++++++----- src/catala/scope_language/ast.ml | 1 + src/catala/scope_language/dependency.ml | 2 +- src/catala/scope_language/print.ml | 1 + src/catala/scope_language/scope_to_dcalc.ml | 1 + tests/test_dec/simple.catala | 13 +++++++++++++ tests/test_dec/simple.catala.A.out | 3 +++ 14 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 tests/test_dec/simple.catala create mode 100644 tests/test_dec/simple.catala.A.out diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 3159d0c7..06dc5634 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -65,7 +65,18 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) let untyped_term = match l with | Number ((Int i, _), _) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) - | Number ((Dec (_i, _f), _), _) -> Name_resolution.raise_unsupported_feature "decimal" pos + | Number ((Dec (i, f), _), _) -> + let out = + Scopelang.Ast.ELit + (Dcalc.Ast.LRat + Q.( + of_int64 i + (of_int64 f / of_float (10.0 ** ceil (log10 (Int64.to_float f)))))) + in + Cli.debug_print + (Format.asprintf "%d.%d -> %a (%s)" (Int64.to_int i) (Int64.to_int f) + Scopelang.Print.format_expr (out, Pos.no_pos) + (Q.to_string (Q.of_float (ceil (log10 (Int64.to_float f)))))); + out | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) | _ -> Name_resolution.raise_unsupported_feature "literal" pos in diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index 628afd70..08ae8ac0 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -1,6 +1,6 @@ (library (name surface) - (libraries utils menhirLib sedlex re desugared scopelang) + (libraries utils menhirLib sedlex re desugared scopelang zarith) (public_name catala.surface) (preprocess (pps sedlex.ppx))) diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index b6f3ff89..5daf1316 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -102,7 +102,8 @@ let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) | Ast.Data (Ast.Primitive prim) -> ( match prim with | Ast.Integer -> (Scopelang.Ast.TInt, typ_pos) - | Ast.Decimal | Ast.Money | Ast.Date -> raise_unsupported_feature "value type" typ_pos + | Ast.Decimal -> (Scopelang.Ast.TRat, typ_pos) + | Ast.Money | Ast.Date -> raise_unsupported_feature "value type" typ_pos | Ast.Boolean -> (Scopelang.Ast.TBool, typ_pos) | Ast.Text -> raise_unsupported_feature "text type" typ_pos | Ast.Named ident -> ( diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 905f5a7f..b1b6105e 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -19,11 +19,12 @@ type typ = | TBool | TUnit | TInt + | TRat | TTuple of typ Pos.marked list | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LBool of bool | LEmptyError | LInt of Int64.t | LUnit +type lit = LBool of bool | LEmptyError | LInt of Int64.t | LRat of Q.t | LUnit type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq diff --git a/src/catala/default_calculus/dune b/src/catala/default_calculus/dune index 1f3b7ee8..2ec7c591 100644 --- a/src/catala/default_calculus/dune +++ b/src/catala/default_calculus/dune @@ -1,7 +1,7 @@ (library (name dcalc) (public_name catala.dcalc) - (libraries bindlib unionFind utils)) + (libraries bindlib unionFind utils zarith)) (documentation (package catala)) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index d736c12e..1a656642 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -37,11 +37,27 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The division operator:", Pos.get_position op); (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] + | A.Binop A.Add, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.add i1 i2)) + | A.Binop A.Sub, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.sub i1 i2)) + | A.Binop A.Mult, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.mul i1 i2)) + | A.Binop A.Div, [ ELit (LRat i1); ELit (LRat i2) ] -> + if i2 <> Q.zero then A.ELit (LRat (Q.div i1 i2)) + else + Errors.raise_multispanned_error "division by zero at runtime" + [ + (Some "The division operator:", Pos.get_position op); + (Some "The null denominator:", Pos.get_position (List.nth args 2)); + ] | A.Binop A.Lt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) | A.Binop A.Lte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) | A.Binop A.Gt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) | A.Binop A.Gte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 >= i2)) | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) + | A.Binop A.Lt, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 < i2)) + | A.Binop A.Lte, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <= i2)) + | A.Binop A.Gt, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) + | A.Binop A.Gte, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) + | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index cfe4ba7b..67642cb9 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -27,6 +27,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TInt -> Format.fprintf fmt "int" + | TRat -> Format.fprintf fmt "dec" | TTuple ts -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) @@ -44,6 +45,7 @@ let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = | LInt i -> Format.fprintf fmt "%s" (Int64.to_string i) | LEmptyError -> Format.fprintf fmt "∅" | LUnit -> Format.fprintf fmt "()" + | LRat i -> Format.fprintf fmt "%f" (Q.to_float i) let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = Format.fprintf fmt "%s" diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 24fe1721..ff83db5e 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -24,6 +24,7 @@ type typ = | TUnit | TInt | TBool + | TRat | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem | TTuple of typ Pos.marked UnionFind.elem list | TEnum of typ Pos.marked UnionFind.elem list @@ -35,6 +36,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TInt -> Format.fprintf fmt "int" + | TRat -> Format.fprintf fmt "dec" | TAny -> Format.fprintf fmt "any type" | TTuple ts -> Format.fprintf fmt "(%a)" @@ -51,7 +53,8 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with - | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) | (TInt, _), (TInt, _) -> () + | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) | (TInt, _), (TInt, _) | (TRat, _), (TRat, _) -> + () | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> unify t11 t21; unify t12 t22 @@ -75,15 +78,14 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = let pos = Pos.get_position op in let bt = UnionFind.make (TBool, pos) in - let it = UnionFind.make (TInt, pos) in let any = UnionFind.make (TAny, pos) in let arr x y = UnionFind.make (TArrow (x, y), pos) in match Pos.unmark op with | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) - | A.Binop (A.Add | A.Sub | A.Mult | A.Div) -> arr it (arr it it) - | A.Binop (A.Lt | A.Lte | A.Gt | A.Gte) -> arr it (arr it bt) + | A.Binop (A.Add | A.Sub | A.Mult | A.Div) -> arr any (arr any any) + | A.Binop (A.Lt | A.Lte | A.Gt | A.Gte) -> arr any (arr any bt) | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) - | A.Unop A.Minus -> arr it it + | A.Unop A.Minus -> arr any any | A.Unop A.Not -> arr bt bt | A.Unop A.ErrorOnEmpty -> arr any any @@ -91,6 +93,7 @@ let rec ast_to_typ (ty : A.typ) : typ = match ty with | A.TUnit -> TUnit | A.TBool -> TBool + | A.TRat -> TRat | A.TInt -> TInt | A.TArrow (t1, t2) -> TArrow @@ -106,6 +109,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = | TUnit -> A.TUnit | TBool -> A.TBool | TInt -> A.TInt + | TRat -> A.TRat | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TEnum ts -> A.TEnum (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) @@ -125,6 +129,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m (Pos.get_position e) ) | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) + | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as TRat e) | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> @@ -225,6 +230,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (Pos.get_position e) ) | ELit (LBool _) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as TInt e)) + | ELit (LRat _) -> unify tau (UnionFind.make (Pos.same_pos_as TRat e)) | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as TUnit e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | ETuple es -> ( diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 5a8c45c0..e7b9530e 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -68,6 +68,7 @@ type typ = | TBool | TUnit | TInt + | TRat | TStruct of StructName.t | TEnum of EnumName.t | TArrow of typ Pos.marked * typ Pos.marked diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 5a4b1f12..2bf425d2 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -149,7 +149,7 @@ let rec get_structs_or_enums_in_type (t : Ast.typ Pos.marked) : TVertexSet.t = | Ast.TEnum e -> TVertexSet.singleton (TVertex.Enum e) | Ast.TArrow (t1, t2) -> TVertexSet.union (get_structs_or_enums_in_type t1) (get_structs_or_enums_in_type t2) - | Ast.TBool | Ast.TUnit | Ast.TInt -> TVertexSet.empty + | Ast.TBool | Ast.TUnit | Ast.TInt | Ast.TRat -> TVertexSet.empty let build_type_graph (structs : Ast.struct_ctx) (enums : Ast.enum_ctx) : TDependencies.t = let g = TDependencies.empty in diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 6b4d2bed..af036ac1 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -40,6 +40,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = | TUnit -> Format.fprintf fmt "unit" | TBool -> Format.fprintf fmt "bool" | TInt -> Format.fprintf fmt "int" + | TRat -> Format.fprintf fmt "dec" | TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e | TArrow (t1, t2) -> diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index baddd0f9..764f8762 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -48,6 +48,7 @@ let rec translate_typ (ctx : ctx) (t : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.m | Ast.TUnit -> Dcalc.Ast.TUnit | Ast.TBool -> Dcalc.Ast.TBool | Ast.TInt -> Dcalc.Ast.TInt + | Ast.TRat -> Dcalc.Ast.TRat | Ast.TArrow (t1, t2) -> Dcalc.Ast.TArrow (translate_typ ctx t1, translate_typ ctx t2) | Ast.TStruct s_uid -> let s_fields = Ast.StructMap.find s_uid ctx.structs in diff --git a/tests/test_dec/simple.catala b/tests/test_dec/simple.catala new file mode 100644 index 00000000..e7a907a8 --- /dev/null +++ b/tests/test_dec/simple.catala @@ -0,0 +1,13 @@ +@Article@ + +/* +new scope A: + param x content dec + param y content dec + param z content dec + +scope A: + def x := 84.648665 + def y := 4.368297 + def z := x / y +*/ \ No newline at end of file diff --git a/tests/test_dec/simple.catala.A.out b/tests/test_dec/simple.catala.A.out new file mode 100644 index 00000000..c759f2a4 --- /dev/null +++ b/tests/test_dec/simple.catala.A.out @@ -0,0 +1,3 @@ +[RESULT] x -> 84.648665 +[RESULT] y -> 4.368297 +[RESULT] z -> 19.377956 From be563a24f63758ad00dd2f369fc066916cfb0244 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 14:51:22 +0100 Subject: [PATCH 063/142] Defined operators for dec and money --- Makefile | 3 +- src/catala/catala_surface/ast.ml | 18 +- src/catala/catala_surface/desugaring.ml | 36 +- src/catala/catala_surface/lexer.ml | 82 +++- src/catala/catala_surface/lexer_en.ml | 82 +++- src/catala/catala_surface/lexer_fr.ml | 82 +++- src/catala/catala_surface/name_resolution.ml | 13 +- src/catala/catala_surface/parser.messages | 472 +++++++++---------- src/catala/catala_surface/parser.mly | 49 +- src/catala/catala_surface/parser_errors.ml | 232 ++++----- src/catala/default_calculus/ast.ml | 27 +- src/catala/default_calculus/interpreter.ml | 41 +- src/catala/default_calculus/print.ml | 28 +- src/catala/default_calculus/typing.ml | 76 +-- src/catala/scope_language/ast.ml | 5 +- src/catala/scope_language/dependency.ml | 2 +- src/catala/scope_language/print.ml | 9 +- src/catala/scope_language/scope_to_dcalc.ml | 13 +- tests/test_dec/simple.catala | 2 +- 19 files changed, 733 insertions(+), 539 deletions(-) diff --git a/Makefile b/Makefile index 8a2297cd..9e784a0a 100644 --- a/Makefile +++ b/Makefile @@ -18,10 +18,11 @@ install-dependencies-ocaml: menhirLib \ dune dune-build-info \ cmdliner obelisk \ - re reason \ + re \ obelisk \ unionfind \ bindlib \ + zarith \ ocamlgraph init-submodules: diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 9b078376..4df599f8 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -55,9 +55,23 @@ type enum_decl = { type match_case_pattern = constructor Pos.marked list * ident Pos.marked option -type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq +type op_kind = KInt | KDec | KMoney -type unop = Not | Minus +type binop = + | And + | Or + | 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 + | Eq + | Neq + +type unop = Not | Minus of op_kind type builtin_expression = Cardinal | Now diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 06dc5634..bdff831b 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -19,22 +19,26 @@ module Cli = Utils.Cli (** The optional argument subdef allows to choose between differents uids in case the expression is a redefinition of a subvariable *) +let translate_op_kind (k : Ast.op_kind) : Dcalc.Ast.op_kind = + match k with KInt -> KInt | KDec -> KRat | KMoney -> KMoney + let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = match op with | And -> And | Or -> Or - | Add -> Add - | Sub -> Sub - | Mult -> Mult - | Div -> Div - | Lt -> Lt - | Lte -> Lte - | Gt -> Gt - | Gte -> Gte + | Add l -> Add (translate_op_kind l) + | Sub l -> Sub (translate_op_kind l) + | Mult l -> Mult (translate_op_kind l) + | Div l -> Div (translate_op_kind l) + | Lt l -> Lt (translate_op_kind l) + | Lte l -> Lte (translate_op_kind l) + | Gt l -> Gt (translate_op_kind l) + | Gte l -> Gte (translate_op_kind l) | Eq -> Eq | Neq -> Neq -let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | Minus -> Minus +let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = + match op with Not -> Not | Minus l -> Minus (translate_op_kind l) module LiftStructFieldMap = Bindlib.Lift (Scopelang.Ast.StructFieldMap) module LiftEnumConstructorMap = Bindlib.Lift (Scopelang.Ast.EnumConstructorMap) @@ -66,17 +70,9 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) match l with | Number ((Int i, _), _) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) | Number ((Dec (i, f), _), _) -> - let out = - Scopelang.Ast.ELit - (Dcalc.Ast.LRat - Q.( - of_int64 i + (of_int64 f / of_float (10.0 ** ceil (log10 (Int64.to_float f)))))) - in - Cli.debug_print - (Format.asprintf "%d.%d -> %a (%s)" (Int64.to_int i) (Int64.to_int f) - Scopelang.Print.format_expr (out, Pos.no_pos) - (Q.to_string (Q.of_float (ceil (log10 (Int64.to_float f)))))); - out + Scopelang.Ast.ELit + (Dcalc.Ast.LRat + Q.(of_int64 i + (of_int64 f / of_float (10.0 ** ceil (log10 (Int64.to_float f)))))) | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) | _ -> Name_resolution.raise_unsupported_feature "literal" pos in diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 4d5ddea2..266a66cf 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -301,9 +301,54 @@ let rec lex_code (lexbuf : lexbuf) : token = | "->" -> update_acc lexbuf; ARROW - | '.' -> + | "<=", 0x24 -> update_acc lexbuf; - DOT + LESSER_EQUAL_MONEY + | '<', 0x24 -> + update_acc lexbuf; + LESSER_MONEY + | ">=", 0x24 -> + update_acc lexbuf; + GREATER_EQUAL_MONEY + | '>', 0x24 -> + update_acc lexbuf; + GREATER_MONEY + | '+', 0x24 -> + update_acc lexbuf; + PLUSMONEY + | '-', 0x24 -> + update_acc lexbuf; + MINUSMONEY + | '*', 0x24 -> + update_acc lexbuf; + MULTMONEY + | '/', 0x24 -> + update_acc lexbuf; + DIVMONEY + | "<=." -> + update_acc lexbuf; + LESSER_EQUAL_DEC + | "<." -> + update_acc lexbuf; + LESSER_DEC + | ">=." -> + update_acc lexbuf; + GREATER_EQUAL_DEC + | ">." -> + update_acc lexbuf; + GREATER_DEC + | "+." -> + update_acc lexbuf; + PLUSDEC + | "-." -> + update_acc lexbuf; + MINUSDEC + | "*." -> + update_acc lexbuf; + MULTDEC + | "/." -> + update_acc lexbuf; + DIVDEC | "<=" -> update_acc lexbuf; LESSER_EQUAL @@ -316,12 +361,27 @@ let rec lex_code (lexbuf : lexbuf) : token = | '>' -> update_acc lexbuf; GREATER + | '+' -> + update_acc lexbuf; + PLUS + | '-' -> + update_acc lexbuf; + MINUS + | '*' -> + update_acc lexbuf; + MULT + | '/' -> + update_acc lexbuf; + DIV | "!=" -> update_acc lexbuf; NOT_EQUAL | '=' -> update_acc lexbuf; EQUAL + | '%' -> + update_acc lexbuf; + PERCENT | '(' -> update_acc lexbuf; LPAREN @@ -334,21 +394,6 @@ let rec lex_code (lexbuf : lexbuf) : token = | '}' -> update_acc lexbuf; RBRACKET - | '+' -> - update_acc lexbuf; - PLUS - | '-' -> - update_acc lexbuf; - MINUS - | '*' -> - update_acc lexbuf; - MULT - | '%' -> - update_acc lexbuf; - PERCENT - | '/' -> - update_acc lexbuf; - DIV | '|' -> update_acc lexbuf; VERTICAL @@ -358,6 +403,9 @@ let rec lex_code (lexbuf : lexbuf) : token = | "--" -> update_acc lexbuf; ALT + | '.' -> + update_acc lexbuf; + DOT | uppercase, Star (uppercase | lowercase | '0' .. '9' | '_' | '\'') -> (* Name of constructor *) update_acc lexbuf; diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 56c0012f..c3f57700 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -269,9 +269,54 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "->" -> L.update_acc lexbuf; ARROW - | '.' -> + | "<=", 0x24 -> L.update_acc lexbuf; - DOT + LESSER_EQUAL_MONEY + | '<', 0x24 -> + L.update_acc lexbuf; + LESSER_MONEY + | ">=", 0x24 -> + L.update_acc lexbuf; + GREATER_EQUAL_MONEY + | '>', 0x24 -> + L.update_acc lexbuf; + GREATER_MONEY + | '+', 0x24 -> + L.update_acc lexbuf; + PLUSMONEY + | '-', 0x24 -> + L.update_acc lexbuf; + MINUSMONEY + | '*', 0x24 -> + L.update_acc lexbuf; + MULTMONEY + | '/', 0x24 -> + L.update_acc lexbuf; + DIVMONEY + | "<=." -> + L.update_acc lexbuf; + LESSER_EQUAL_DEC + | "<." -> + L.update_acc lexbuf; + LESSER_DEC + | ">=." -> + L.update_acc lexbuf; + GREATER_EQUAL_DEC + | ">." -> + L.update_acc lexbuf; + GREATER_DEC + | "+." -> + L.update_acc lexbuf; + PLUSDEC + | "-." -> + L.update_acc lexbuf; + MINUSDEC + | "*." -> + L.update_acc lexbuf; + MULTDEC + | "/." -> + L.update_acc lexbuf; + DIVDEC | "<=" -> L.update_acc lexbuf; LESSER_EQUAL @@ -284,12 +329,27 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | '>' -> L.update_acc lexbuf; GREATER + | '+' -> + L.update_acc lexbuf; + PLUS + | '-' -> + L.update_acc lexbuf; + MINUS + | '*' -> + L.update_acc lexbuf; + MULT + | '/' -> + L.update_acc lexbuf; + DIV | "!=" -> L.update_acc lexbuf; NOT_EQUAL | '=' -> L.update_acc lexbuf; EQUAL + | '%' -> + L.update_acc lexbuf; + PERCENT | '(' -> L.update_acc lexbuf; LPAREN @@ -302,21 +362,6 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | '}' -> L.update_acc lexbuf; RBRACKET - | '+' -> - L.update_acc lexbuf; - PLUS - | '-' -> - L.update_acc lexbuf; - MINUS - | '*' -> - L.update_acc lexbuf; - MULT - | '%' -> - L.update_acc lexbuf; - PERCENT - | '/' -> - L.update_acc lexbuf; - DIV | '|' -> L.update_acc lexbuf; VERTICAL @@ -326,6 +371,9 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "--" -> L.update_acc lexbuf; ALT + | '.' -> + L.update_acc lexbuf; + DOT | uppercase, Star (uppercase | lowercase | '0' .. '9' | '_' | '\'') -> (* Name of constructor *) L.update_acc lexbuf; diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 7b9c2f62..bb32ccbc 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -278,9 +278,54 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "->" -> L.update_acc lexbuf; ARROW - | '.' -> + | "<=", 0x20AC -> L.update_acc lexbuf; - DOT + LESSER_EQUAL_MONEY + | '<', 0x20AC -> + L.update_acc lexbuf; + LESSER_MONEY + | ">=", 0x20AC -> + L.update_acc lexbuf; + GREATER_EQUAL_MONEY + | '>', 0x20AC -> + L.update_acc lexbuf; + GREATER_MONEY + | '+', 0x20AC -> + L.update_acc lexbuf; + PLUSMONEY + | '-', 0x20AC -> + L.update_acc lexbuf; + MINUSMONEY + | '*', 0x20AC -> + L.update_acc lexbuf; + MULTMONEY + | '/', 0x20AC -> + L.update_acc lexbuf; + DIVMONEY + | "<=." -> + L.update_acc lexbuf; + LESSER_EQUAL_DEC + | "<." -> + L.update_acc lexbuf; + LESSER_DEC + | ">=." -> + L.update_acc lexbuf; + GREATER_EQUAL_DEC + | ">." -> + L.update_acc lexbuf; + GREATER_DEC + | "+." -> + L.update_acc lexbuf; + PLUSDEC + | "-." -> + L.update_acc lexbuf; + MINUSDEC + | "*." -> + L.update_acc lexbuf; + MULTDEC + | "/." -> + L.update_acc lexbuf; + DIVDEC | "<=" -> L.update_acc lexbuf; LESSER_EQUAL @@ -293,12 +338,27 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | '>' -> L.update_acc lexbuf; GREATER + | '+' -> + L.update_acc lexbuf; + PLUS + | '-' -> + L.update_acc lexbuf; + MINUS + | '*' -> + L.update_acc lexbuf; + MULT + | '/' -> + L.update_acc lexbuf; + DIV | "!=" -> L.update_acc lexbuf; NOT_EQUAL | '=' -> L.update_acc lexbuf; EQUAL + | '%' -> + L.update_acc lexbuf; + PERCENT | '(' -> L.update_acc lexbuf; LPAREN @@ -311,21 +371,6 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | '}' -> L.update_acc lexbuf; RBRACKET - | '+' -> - L.update_acc lexbuf; - PLUS - | '-' -> - L.update_acc lexbuf; - MINUS - | '*' -> - L.update_acc lexbuf; - MULT - | '%' -> - L.update_acc lexbuf; - PERCENT - | '/' -> - L.update_acc lexbuf; - DIV | '|' -> L.update_acc lexbuf; VERTICAL @@ -335,6 +380,9 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "--" -> L.update_acc lexbuf; ALT + | '.' -> + L.update_acc lexbuf; + DOT | uppercase, Star (uppercase | lowercase | '0' .. '9' | '_' | '\'') -> (* Name of constructor *) L.update_acc lexbuf; diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 5daf1316..319d2c48 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -96,15 +96,16 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : Scopelang.Ast.typ Pos.marked = match typ with - | Ast.Condition -> (Scopelang.Ast.TBool, typ_pos) + | Ast.Condition -> (Scopelang.Ast.TLit TBool, typ_pos) | Ast.Data (Ast.Collection _) -> raise_unsupported_feature "collection type" typ_pos | Ast.Data (Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos | Ast.Data (Ast.Primitive prim) -> ( match prim with - | Ast.Integer -> (Scopelang.Ast.TInt, typ_pos) - | Ast.Decimal -> (Scopelang.Ast.TRat, typ_pos) - | Ast.Money | Ast.Date -> raise_unsupported_feature "value type" typ_pos - | Ast.Boolean -> (Scopelang.Ast.TBool, typ_pos) + | Ast.Integer -> (Scopelang.Ast.TLit TInt, typ_pos) + | Ast.Decimal -> (Scopelang.Ast.TLit TRat, typ_pos) + | Ast.Money -> (Scopelang.Ast.TLit TMoney, typ_pos) + | Ast.Date -> raise_unsupported_feature "date type" typ_pos + | Ast.Boolean -> (Scopelang.Ast.TLit TBool, typ_pos) | Ast.Text -> raise_unsupported_feature "text type" typ_pos | Ast.Named ident -> ( match Desugared.Ast.IdentMap.find_opt ident ctxt.struct_idmap with @@ -297,7 +298,7 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = (fun cases -> let typ = match cdecl.Ast.enum_decl_case_typ with - | None -> (Scopelang.Ast.TUnit, cdecl_pos) + | None -> (Scopelang.Ast.TLit TUnit, cdecl_pos) | Some typ -> process_type ctxt typ in match cases with diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 68c30541..a3fa6504 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 279. +## Ends in an error in state: 297. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -36,7 +36,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 291. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -49,7 +49,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 268. +## Ends in an error in state: 286. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -61,7 +61,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 267. +## Ends in an error in state: 285. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -73,7 +73,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 266. +## Ends in an error in state: 284. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -85,7 +85,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 265. +## Ends in an error in state: 283. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -97,7 +97,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 264. +## Ends in an error in state: 282. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -109,7 +109,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 263. +## Ends in an error in state: 281. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -121,7 +121,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 258. +## Ends in an error in state: 276. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -133,7 +133,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 256. +## Ends in an error in state: 274. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -145,7 +145,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 255. +## Ends in an error in state: 273. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -157,7 +157,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 260. +## Ends in an error in state: 278. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -170,7 +170,7 @@ expected the next context item, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 271. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -182,7 +182,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 252. +## Ends in an error in state: 270. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -196,7 +196,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 251. +## Ends in an error in state: 269. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -210,7 +210,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 268. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -222,7 +222,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 249. +## Ends in an error in state: 267. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -234,7 +234,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 248. +## Ends in an error in state: 266. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -246,7 +246,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 235. +## Ends in an error in state: 253. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -258,7 +258,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR ## -## Ends in an error in state: 232. +## Ends in an error in state: 250. ## ## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -270,7 +270,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 243. +## Ends in an error in state: 261. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 239. +## Ends in an error in state: 257. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -294,7 +294,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 238. +## Ends in an error in state: 256. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -306,7 +306,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 245. +## Ends in an error in state: 263. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -318,7 +318,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 221. +## Ends in an error in state: 239. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -330,7 +330,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 220. +## Ends in an error in state: 238. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -342,7 +342,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 237. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +354,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 218. +## Ends in an error in state: 236. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -366,7 +366,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 217. +## Ends in an error in state: 235. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -378,7 +378,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 216. +## Ends in an error in state: 234. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -390,7 +390,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 233. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -404,7 +404,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 212. +## Ends in an error in state: 230. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -416,23 +416,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 49, spurious reduction of production primitive_expression -> CARDINAL -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression -## In state 209, spurious reduction of production assertion_base -> expression -## In state 210, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 211, spurious reduction of production scope_item -> ASSERTION assertion +## In state 51, spurious reduction of production primitive_expression -> CARDINAL +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression +## In state 227, spurious reduction of production assertion_base -> expression +## In state 228, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 229, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 206. +## Ends in an error in state: 224. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -444,7 +444,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 205. +## Ends in an error in state: 223. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -455,15 +455,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 204. +## Ends in an error in state: 222. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -475,7 +475,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 208. +## Ends in an error in state: 226. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -487,9 +487,9 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 177. +## Ends in an error in state: 195. ## -## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## condition @@ -498,21 +498,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 49, spurious reduction of production primitive_expression -> CARDINAL -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression -## In state 170, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 51, spurious reduction of production primitive_expression -> CARDINAL +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression +## In state 188, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 187. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -524,7 +524,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 197. +## Ends in an error in state: 215. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -535,15 +535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 199. +## Ends in an error in state: 217. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -554,15 +554,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 198. +## Ends in an error in state: 216. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -574,7 +574,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 196. +## Ends in an error in state: 214. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -586,7 +586,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 195. +## Ends in an error in state: 213. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -598,7 +598,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 192. +## Ends in an error in state: 210. ## ## definition -> qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -610,7 +610,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 190. +## Ends in an error in state: 208. ## ## definition -> qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -622,7 +622,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 191. +## Ends in an error in state: 209. ## ## definition -> qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -634,7 +634,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 189. +## Ends in an error in state: 207. ## ## definition -> qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -645,15 +645,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 188. +## Ends in an error in state: 206. ## ## scope_item -> DEFINITION . definition [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -665,7 +665,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 186. +## Ends in an error in state: 204. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -677,7 +677,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 174. +## Ends in an error in state: 192. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -689,7 +689,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 168. +## Ends in an error in state: 186. ## ## rule -> rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -701,7 +701,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 181. +## Ends in an error in state: 199. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -713,7 +713,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 171. +## Ends in an error in state: 189. ## ## rule -> rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -725,7 +725,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 180. +## Ends in an error in state: 198. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -736,15 +736,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 185, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 167, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 185. +## Ends in an error in state: 203. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -757,7 +757,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 166. +## Ends in an error in state: 184. ## ## scope_item -> RULE . rule [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -769,7 +769,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 165. +## Ends in an error in state: 183. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -781,10 +781,10 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 49. +## Ends in an error in state: 51. ## ## aggregate_func -> CARDINAL . [ FOR ] -## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CARDINAL @@ -794,11 +794,11 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 117. +## Ends in an error in state: 135. ## -## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT small_expression @@ -808,9 +808,9 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 116. +## Ends in an error in state: 134. ## -## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT @@ -820,9 +820,9 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 69. +## Ends in an error in state: 71. ## -## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## constructor @@ -832,7 +832,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 132. +## Ends in an error in state: 150. ## ## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -844,9 +844,9 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 138. +## Ends in an error in state: 156. ## -## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression SUCH @@ -856,9 +856,9 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 137. +## Ends in an error in state: 155. ## -## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression @@ -867,16 +867,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 136. +## Ends in an error in state: 154. ## -## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN @@ -886,9 +886,9 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 135. +## Ends in an error in state: 153. ## -## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident @@ -898,9 +898,9 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 134. +## Ends in an error in state: 152. ## -## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked @@ -910,7 +910,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 125. +## Ends in an error in state: 143. ## ## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -922,9 +922,9 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 129. +## Ends in an error in state: 147. ## -## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN primitive_expression @@ -933,16 +933,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 128. +## Ends in an error in state: 146. ## -## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN @@ -952,9 +952,9 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 127. +## Ends in an error in state: 145. ## -## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident @@ -964,9 +964,9 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 126. +## Ends in an error in state: 144. ## -## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked @@ -976,7 +976,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 44. +## Ends in an error in state: 46. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -988,7 +988,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 140. +## Ends in an error in state: 158. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -999,20 +999,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 143. +## Ends in an error in state: 161. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1024,7 +1024,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 142. +## Ends in an error in state: 160. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1035,20 +1035,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 141. +## Ends in an error in state: 159. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1060,7 +1060,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 42. +## Ends in an error in state: 44. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1072,9 +1072,9 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 62. +## Ends in an error in state: 64. ## -## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## num_literal @@ -1084,9 +1084,9 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 145. +## Ends in an error in state: 163. ## -## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN expression @@ -1095,22 +1095,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 40. +## Ends in an error in state: 42. ## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN @@ -1120,7 +1120,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 147. +## Ends in an error in state: 165. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1131,14 +1131,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 150. +## Ends in an error in state: 168. ## ## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1149,20 +1149,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 107, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 154, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 125, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 172, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 153. +## Ends in an error in state: 171. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1174,7 +1174,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 158. +## Ends in an error in state: 176. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1186,7 +1186,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 152. +## Ends in an error in state: 170. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1198,7 +1198,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 156. +## Ends in an error in state: 174. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1211,7 +1211,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 155. +## Ends in an error in state: 173. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1223,7 +1223,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 149. +## Ends in an error in state: 167. ## ## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1235,7 +1235,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 148. +## Ends in an error in state: 166. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1247,7 +1247,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 39. +## Ends in an error in state: 41. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1259,9 +1259,9 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 50. +## Ends in an error in state: 52. ## -## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_unop @@ -1271,7 +1271,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 106. +## Ends in an error in state: 124. ## ## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1283,9 +1283,9 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 102. +## Ends in an error in state: 120. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression OF @@ -1295,9 +1295,9 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 101. +## Ends in an error in state: 119. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression @@ -1306,16 +1306,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 99. +## Ends in an error in state: 117. ## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN @@ -1325,9 +1325,9 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 98. +## Ends in an error in state: 116. ## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident @@ -1337,9 +1337,9 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 97. +## Ends in an error in state: 115. ## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR @@ -1349,9 +1349,9 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 96. +## Ends in an error in state: 114. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func @@ -1361,9 +1361,9 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 56. +## Ends in an error in state: 58. ## -## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression ARROW @@ -1373,7 +1373,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 164. +## Ends in an error in state: 182. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1384,24 +1384,24 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression -## In state 90, spurious reduction of production mult_expression -> base_expression -## In state 85, spurious reduction of production sum_expression -> mult_expression -## In state 77, spurious reduction of production compare_expression -> sum_expression -## In state 109, spurious reduction of production logical_expression -> compare_expression -## In state 124, spurious reduction of production expression -> logical_expression -## In state 162, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 163, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 104, spurious reduction of production mult_expression -> base_expression +## In state 95, spurious reduction of production sum_expression -> mult_expression +## In state 79, spurious reduction of production compare_expression -> sum_expression +## In state 127, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production expression -> logical_expression +## In state 180, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 181, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 54. +## Ends in an error in state: 56. ## -## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression DOT @@ -1411,9 +1411,9 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 122. +## Ends in an error in state: 140. ## -## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression IN @@ -1423,10 +1423,10 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 90. +## Ends in an error in state: 104. ## -## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression @@ -1435,17 +1435,17 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression -## In state 58, spurious reduction of production base_expression -> primitive_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 60, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 93. +## Ends in an error in state: 111. ## -## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MINUS LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression mult_op @@ -1455,7 +1455,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 84. +## Ends in an error in state: 94. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1467,9 +1467,9 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 61. +## Ends in an error in state: 63. ## -## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression OF @@ -1479,7 +1479,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 112. +## Ends in an error in state: 130. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1491,9 +1491,9 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 88. +## Ends in an error in state: 102. ## -## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_EQUAL LESSER GREATER_EQUAL GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## mult_expression sum_op @@ -1503,12 +1503,12 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 58. +## Ends in an error in state: 60. ## -## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression @@ -1517,16 +1517,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> small_expression +## In state 55, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 59. +## Ends in an error in state: 61. ## -## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUS OR NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression WITH @@ -1536,11 +1536,11 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 53. +## Ends in an error in state: 55. ## -## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression @@ -1552,7 +1552,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 31. ## -## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV date_int @@ -1564,7 +1564,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 30. ## -## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV @@ -1576,7 +1576,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 29. ## -## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int @@ -1588,7 +1588,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 28. ## -## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV @@ -1600,7 +1600,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 27. ## -## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int @@ -1612,7 +1612,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 25. ## -## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUS OR OF NOT_EQUAL MULT MINUS LESSER_EQUAL LESSER INCREASING IN GREATER_EQUAL GREATER EQUAL END_CODE ELSE DOT DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL @@ -1658,7 +1658,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 290. +## Ends in an error in state: 308. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1670,7 +1670,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 295. +## Ends in an error in state: 313. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1682,7 +1682,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 288. +## Ends in an error in state: 306. ## ## source_file_article -> law_article . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1694,7 +1694,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 283. +## Ends in an error in state: 301. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index f0a6ddc1..ebd7a489 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -42,11 +42,16 @@ %token COLON ALT DATA VERTICAL %token OF INTEGER COLLECTION %token RULE CONDITION DEFINED_AS -%token EXISTS IN SUCH THAT NOW LESSER GREATER +%token LESSER GREATER LESSER_EQUAL GREATER_EQUAL +%token LESSER_DEC GREATER_DEC LESSER_EQUAL_DEC GREATER_EQUAL_DEC +%token LESSER_MONEY GREATER_MONEY LESSER_EQUAL_MONEY GREATER_EQUAL_MONEY +%token EXISTS IN SUCH THAT NOW %token DOT AND OR LPAREN RPAREN OPTIONAL EQUAL -%token CARDINAL LESSER_EQUAL GREATER_EQUAL -%token ASSERTION FIXED BY YEAR -%token PLUS MINUS MULT DIV MATCH WITH VARIES WITH_V +%token CARDINAL ASSERTION FIXED BY YEAR +%token PLUS MINUS MULT DIV +%token PLUSDEC MINUSDEC MULTDEC DIVDEC +%token PLUSMONEY MINUSMONEY MULTMONEY DIVMONEY +%token MATCH WITH VARIES WITH_V %token FOR ALL WE_HAVE INCREASING DECREASING %token NOT BOOLEAN PERCENT ARROW %token SCOPE FILLED NOT_EQUAL DEFINITION @@ -177,10 +182,18 @@ literal: | FALSE { (Bool false, $sloc) } compare_op: -| LESSER { (Lt, $sloc) } -| LESSER_EQUAL { (Lte, $sloc) } -| GREATER { (Gt, $sloc) } -| GREATER_EQUAL { (Gte, $sloc) } +| LESSER { (Lt KInt, $sloc) } +| LESSER_EQUAL { (Lte KInt, $sloc) } +| GREATER { (Gt KInt, $sloc) } +| GREATER_EQUAL { (Gte KInt, $sloc) } +| LESSER_DEC { (Lt KDec, $sloc) } +| LESSER_EQUAL_DEC { (Lte KDec, $sloc) } +| GREATER_DEC { (Gt KDec, $sloc) } +| GREATER_EQUAL_DEC { (Gte KDec, $sloc) } +| LESSER_MONEY { (Lt KMoney, $sloc) } +| LESSER_EQUAL_MONEY { (Lte KMoney, $sloc) } +| GREATER_MONEY { (Gt KMoney, $sloc) } +| GREATER_EQUAL_MONEY { (Gte KMoney, $sloc) } | EQUAL { (Eq, $sloc) } | NOT_EQUAL { (Neq, $sloc) } @@ -208,8 +221,12 @@ base_expression: } mult_op: -| MULT { (Mult, $sloc) } -| DIV { (Div, $sloc) } +| MULT { (Mult KInt, $sloc) } +| DIV { (Div KInt, $sloc) } +| MULTDEC { (Mult KDec, $sloc) } +| DIVDEC { (Div KDec, $sloc) } +| MULTMONEY { (Mult KMoney, $sloc) } +| DIVMONEY { (Div KMoney, $sloc) } mult_expression: | e = base_expression { e } @@ -218,11 +235,17 @@ mult_expression: } sum_op: -| PLUS { (Add, $sloc) } -| MINUS { (Sub, $sloc) } +| PLUSMONEY { (Add KMoney, $sloc) } +| MINUSMONEY { (Sub KMoney, $sloc) } +| PLUSDEC { (Add KDec, $sloc) } +| MINUSDEC { (Sub KDec, $sloc) } +| PLUS { (Add KInt, $sloc) } +| MINUS { (Sub KInt, $sloc) } sum_unop: -| MINUS { (Minus, $sloc) } +| MINUS { (Minus KInt, $sloc) } +| MINUSDEC { (Minus KDec, $sloc) } +| MINUSMONEY { (Minus KMoney, $sloc) } sum_expression: | e = mult_expression { e } diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 7427baca..c630f3af 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -11,10 +11,10 @@ let message s = | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 283 -> "expected some text, another heading or a law article\n" - | 288 -> "expected a code block, a metadata block, more law text or a heading\n" - | 295 -> "expected a code block, a metadata block, more law text or a heading\n" - | 290 -> "expected a declaration or a scope use\n" + | 301 -> "expected some text, another heading or a law article\n" + | 306 -> "expected a code block, a metadata block, more law text or a heading\n" + | 313 -> "expected a code block, a metadata block, more law text or a heading\n" + | 308 -> "expected a declaration or a scope use\n" | 21 -> "expected the name of the scope you want to use\n" | 23 -> "expected a scope use precondition or a colon\n" | 24 -> "expected an expression which will act as the condition\n" @@ -24,133 +24,133 @@ let message s = | 29 -> "expected a \"/\"\n" | 30 -> "expected the third component of the date literal\n" | 31 -> "expected a delimiter to finish the date literal\n" - | 53 -> "expected an operator to compose the expression on the left with\n" - | 59 -> "expected an enum constructor to test if the expression on the left\n" - | 58 -> "expected an operator to compose the expression on the left with\n" - | 88 -> "expected an expression on the right side of the sum or minus operator\n" - | 112 -> "expected an expression on the right side of the logical operator\n" - | 61 -> "expected an expression for the argument of this function call\n" - | 84 -> "expected an expression on the right side of the comparison operator\n" - | 93 -> "expected an expression on the right side of the multiplication or division operator\n" - | 90 -> "expected an operator to compose the expression on the left\n" - | 122 -> "expected an expression standing for the set you want to test for membership\n" - | 54 -> "expected an identifier standing for a struct field or a subscope name\n" - | 164 -> "expected a colon after the scope use precondition\n" - | 56 -> "expected a constructor, to get the payload of this enum case\n" - | 96 -> "expected the \"for\" keyword to spell the aggregation\n" - | 97 -> "expected an identifier for the aggregation bound variable\n" - | 98 -> "expected the \"in\" keyword\n" - | 99 -> + | 55 -> "expected an operator to compose the expression on the left with\n" + | 61 -> "expected an enum constructor to test if the expression on the left\n" + | 60 -> "expected an operator to compose the expression on the left with\n" + | 102 -> "expected an expression on the right side of the sum or minus operator\n" + | 130 -> "expected an expression on the right side of the logical operator\n" + | 63 -> "expected an expression for the argument of this function call\n" + | 94 -> "expected an expression on the right side of the comparison operator\n" + | 111 -> "expected an expression on the right side of the multiplication or division operator\n" + | 104 -> "expected an operator to compose the expression on the left\n" + | 140 -> "expected an expression standing for the set you want to test for membership\n" + | 56 -> "expected an identifier standing for a struct field or a subscope name\n" + | 182 -> "expected a colon after the scope use precondition\n" + | 58 -> "expected a constructor, to get the payload of this enum case\n" + | 114 -> "expected the \"for\" keyword to spell the aggregation\n" + | 115 -> "expected an identifier for the aggregation bound variable\n" + | 116 -> "expected the \"in\" keyword\n" + | 117 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 101 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 102 -> "expected an expression to compute its aggregation over the set\n" - | 106 -> "expected an expression to take the negation of\n" - | 50 -> "expected an expression to take the opposite of\n" - | 39 -> "expected an expression to match with\n" - | 148 -> "expected a pattern matching case\n" - | 149 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 155 -> + | 119 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 120 -> "expected an expression to compute its aggregation over the set\n" + | 124 -> "expected an expression to take the negation of\n" + | 52 -> "expected an expression to take the opposite of\n" + | 41 -> "expected an expression to match with\n" + | 166 -> "expected a pattern matching case\n" + | 167 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 173 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 156 -> "expected an identifier for this enum case binding\n" - | 152 -> "expected a colon and then the expression for this matching case\n" - | 158 -> "expected a colon or a binding for the enum constructor payload\n" - | 153 -> "expected an expression for this pattern matching case\n" - | 150 -> + | 174 -> "expected an identifier for this enum case binding\n" + | 170 -> "expected a colon and then the expression for this matching case\n" + | 176 -> "expected a colon or a binding for the enum constructor payload\n" + | 171 -> "expected an expression for this pattern matching case\n" + | 168 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 147 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 40 -> "expected an expression inside the parenthesis\n" - | 145 -> "unmatched parenthesis that should have been closed by here\n" - | 62 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 42 -> "expected an expression for the test of the conditional\n" - | 141 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 142 -> + | 165 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 42 -> "expected an expression inside the parenthesis\n" + | 163 -> "unmatched parenthesis that should have been closed by here\n" + | 64 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 44 -> "expected an expression for the test of the conditional\n" + | 159 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 160 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 143 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 140 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 44 -> + | 161 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 158 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 46 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 126 -> "expected an identifier for the bound variable of the universal test\n" - | 127 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 128 -> "expected the expression designating the set on which to perform the universal test\n" - | 129 -> "expected the \"we have\" keyword for this universal test\n" - | 125 -> "expected an expression for the universal test\n" - | 134 -> "expected an identifier that will designate the existential witness for the test\n" - | 135 -> "expected the \"in\" keyword to continue this existential test\n" - | 136 -> "expected an expression that designates the set subject to the existential test\n" - | 137 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 138 -> "expected a keyword to complete the \"such that\" construction\n" - | 132 -> "expected an expression for the existential test\n" - | 69 -> + | 144 -> "expected an identifier for the bound variable of the universal test\n" + | 145 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 146 -> "expected the expression designating the set on which to perform the universal test\n" + | 147 -> "expected the \"we have\" keyword for this universal test\n" + | 143 -> "expected an expression for the universal test\n" + | 152 -> "expected an identifier that will designate the existential witness for the test\n" + | 153 -> "expected the \"in\" keyword to continue this existential test\n" + | 154 -> "expected an expression that designates the set subject to the existential test\n" + | 155 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 156 -> "expected a keyword to complete the \"such that\" construction\n" + | 150 -> "expected an expression for the existential test\n" + | 71 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 116 -> "expected an expression for the content of this enum case\n" - | 117 -> + | 134 -> "expected an expression for the content of this enum case\n" + | 135 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 49 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 165 -> "expected a scope use item: a rule, definition or assertion\n" - | 166 -> "expected the name of the variable subject to the rule\n" - | 185 -> + | 51 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 183 -> "expected a scope use item: a rule, definition or assertion\n" + | 184 -> "expected the name of the variable subject to the rule\n" + | 203 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 180 -> "expected a condition or a consequence for this rule\n" - | 171 -> "expected filled or not filled for a rule consequence\n" - | 181 -> "expected the name of the parameter for this dependent variable \n" - | 168 -> "expected the expression of the rule\n" - | 174 -> "expected the filled keyword the this rule \n" - | 186 -> "expected a struct field or a sub-scope context item after the dot\n" - | 188 -> "expected the name of the variable you want to define\n" - | 189 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 191 -> "expected an expression for the consequence of this definition under condition\n" - | 190 -> + | 198 -> "expected a condition or a consequence for this rule\n" + | 189 -> "expected filled or not filled for a rule consequence\n" + | 199 -> "expected the name of the parameter for this dependent variable \n" + | 186 -> "expected the expression of the rule\n" + | 192 -> "expected the filled keyword the this rule \n" + | 204 -> "expected a struct field or a sub-scope context item after the dot\n" + | 206 -> "expected the name of the variable you want to define\n" + | 207 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 209 -> "expected an expression for the consequence of this definition under condition\n" + | 208 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 192 -> "expected an expression for the definition\n" - | 195 -> "expected an expression that shoud be asserted during execution\n" - | 196 -> "expecting the name of the varying variable\n" - | 198 -> "the variable varies with an expression that was expected here\n" - | 199 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 197 -> "expected an indication about what this variable varies with\n" - | 169 -> "expected an expression for this condition\n" - | 177 -> "expected a consequence for this definition under condition\n" - | 208 -> "expected an expression for this definition under condition\n" - | 204 -> "expected the name of the variable that should be fixed\n" - | 205 -> "expected the legislative text by which the value of the variable is fixed\n" - | 206 -> "expected the legislative text by which the value of the variable is fixed\n" - | 212 -> "expected a new scope use item \n" - | 215 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 216 -> "expected the struct name\n" - | 217 -> "expected a colon\n" - | 218 -> "expected struct data or condition\n" - | 219 -> "expected the name of this struct data \n" - | 220 -> "expected the type of this struct data, introduced by the content keyword\n" - | 221 -> "expected the type of this struct data\n" - | 245 -> "expected the name of this struct condition\n" - | 238 -> "expected a new struct data, or another declaration or scope use\n" - | 239 -> "expected the type of the parameter of this struct data function\n" - | 243 -> "expected a new struct data, or another declaration or scope use\n" - | 232 -> "expected a new struct data, or another declaration or scope use\n" - | 235 -> "expected a new struct data, or another declaration or scope use\n" - | 248 -> "expected the name of the scope you are declaring\n" - | 249 -> "expected a colon followed by the list of context items of this scope\n" - | 250 -> "expected a context item introduced by \"context\"\n" - | 251 -> "expected the name of this new context item\n" - | 252 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 253 -> "expected the name of the subscope for this context item\n" - | 260 -> "expected the next context item, or another declaration or scope use\n" - | 255 -> "expected the type of this context item\n" - | 256 -> "expected the next context item or a dependency declaration for this item\n" - | 258 -> "expected the next context item or a dependency declaration for this item\n" - | 263 -> "expected the name of your enum\n" - | 264 -> "expected a colon\n" - | 265 -> "expected an enum case\n" - | 266 -> "expected the name of an enum case \n" - | 267 -> "expected a payload for your enum case, or another case or declaration \n" - | 268 -> "expected a content type\n" - | 273 -> "expected another enum case, or a new declaration or scope use\n" + | 210 -> "expected an expression for the definition\n" + | 213 -> "expected an expression that shoud be asserted during execution\n" + | 214 -> "expecting the name of the varying variable\n" + | 216 -> "the variable varies with an expression that was expected here\n" + | 217 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 215 -> "expected an indication about what this variable varies with\n" + | 187 -> "expected an expression for this condition\n" + | 195 -> "expected a consequence for this definition under condition\n" + | 226 -> "expected an expression for this definition under condition\n" + | 222 -> "expected the name of the variable that should be fixed\n" + | 223 -> "expected the legislative text by which the value of the variable is fixed\n" + | 224 -> "expected the legislative text by which the value of the variable is fixed\n" + | 230 -> "expected a new scope use item \n" + | 233 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 234 -> "expected the struct name\n" + | 235 -> "expected a colon\n" + | 236 -> "expected struct data or condition\n" + | 237 -> "expected the name of this struct data \n" + | 238 -> "expected the type of this struct data, introduced by the content keyword\n" + | 239 -> "expected the type of this struct data\n" + | 263 -> "expected the name of this struct condition\n" + | 256 -> "expected a new struct data, or another declaration or scope use\n" + | 257 -> "expected the type of the parameter of this struct data function\n" + | 261 -> "expected a new struct data, or another declaration or scope use\n" + | 250 -> "expected a new struct data, or another declaration or scope use\n" + | 253 -> "expected a new struct data, or another declaration or scope use\n" + | 266 -> "expected the name of the scope you are declaring\n" + | 267 -> "expected a colon followed by the list of context items of this scope\n" + | 268 -> "expected a context item introduced by \"context\"\n" + | 269 -> "expected the name of this new context item\n" + | 270 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 271 -> "expected the name of the subscope for this context item\n" + | 278 -> "expected the next context item, or another declaration or scope use\n" + | 273 -> "expected the type of this context item\n" + | 274 -> "expected the next context item or a dependency declaration for this item\n" + | 276 -> "expected the next context item or a dependency declaration for this item\n" + | 281 -> "expected the name of your enum\n" + | 282 -> "expected a colon\n" + | 283 -> "expected an enum case\n" + | 284 -> "expected the name of an enum case \n" + | 285 -> "expected a payload for your enum case, or another case or declaration \n" + | 286 -> "expected a content type\n" + | 291 -> "expected another enum case, or a new declaration or scope use\n" | 17 -> "expected a declaration or a scope use\n" | 19 -> "expected a declaration or a scope use\n" - | 279 -> + | 297 -> "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" | _ -> raise Not_found diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index b1b6105e..e7545959 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -15,20 +15,33 @@ module Pos = Utils.Pos module Uid = Utils.Uid +type typ_lit = TBool | TUnit | TInt | TRat | TMoney + type typ = - | TBool - | TUnit - | TInt - | TRat + | TLit of typ_lit | TTuple of typ Pos.marked list | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LBool of bool | LEmptyError | LInt of Int64.t | LRat of Q.t | LUnit +type lit = LBool of bool | LEmptyError | LInt of Int64.t | LRat of Q.t | LMoney of Z.t | LUnit -type binop = And | Or | Add | Sub | Mult | Div | Lt | Lte | Gt | Gte | Eq | Neq +type op_kind = KInt | KRat | KMoney -type unop = Not | Minus | ErrorOnEmpty +type binop = + | And + | Or + | 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 + | Eq + | Neq + +type unop = Not | Minus of op_kind | ErrorOnEmpty type operator = Binop of binop | Unop of unop diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 1a656642..fb5cdbb3 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -26,10 +26,10 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis ( match (Pos.unmark op, List.map Pos.unmark args) with | A.Binop A.And, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 && b2)) | A.Binop A.Or, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 || b2)) - | A.Binop A.Add, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.add i1 i2)) - | A.Binop A.Sub, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.sub i1 i2)) - | A.Binop A.Mult, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.mul i1 i2)) - | A.Binop A.Div, [ ELit (LInt i1); ELit (LInt i2) ] -> + | A.Binop (A.Add KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.add i1 i2)) + | A.Binop (A.Sub KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.sub i1 i2)) + | A.Binop (A.Mult KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.mul i1 i2)) + | A.Binop (A.Div KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> if i2 <> Int64.zero then A.ELit (LInt (Int64.div i1 i2)) else Errors.raise_multispanned_error "division by zero at runtime" @@ -37,10 +37,10 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The division operator:", Pos.get_position op); (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] - | A.Binop A.Add, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.add i1 i2)) - | A.Binop A.Sub, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.sub i1 i2)) - | A.Binop A.Mult, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.mul i1 i2)) - | A.Binop A.Div, [ ELit (LRat i1); ELit (LRat i2) ] -> + | A.Binop (A.Add KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.add i1 i2)) + | A.Binop (A.Sub KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.sub i1 i2)) + | A.Binop (A.Mult KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LRat (Q.mul i1 i2)) + | A.Binop (A.Div KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> if i2 <> Q.zero then A.ELit (LRat (Q.div i1 i2)) else Errors.raise_multispanned_error "division by zero at runtime" @@ -48,24 +48,25 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The division operator:", Pos.get_position op); (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] - | A.Binop A.Lt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) - | A.Binop A.Lte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) - | A.Binop A.Gt, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) - | A.Binop A.Gte, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 >= i2)) - | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) - | A.Binop A.Lt, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 < i2)) - | A.Binop A.Lte, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <= i2)) - | A.Binop A.Gt, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) - | A.Binop A.Gte, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) + | A.Binop (A.Lt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) + | A.Binop (A.Lte KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) + | A.Binop (A.Gt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) + | A.Binop (A.Gte KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 >= i2)) + | A.Binop (A.Lt KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 < i2)) + | A.Binop (A.Lte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <= i2)) + | A.Binop (A.Gt KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) + | A.Binop (A.Gte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) + | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) | A.Binop _, ([ ELit LEmptyError; _ ] | [ _; ELit LEmptyError ]) -> A.ELit LEmptyError + | A.Unop (A.Minus KInt), [ ELit (LInt i) ] -> A.ELit (LInt (Int64.sub Int64.zero i)) + | A.Unop (A.Minus KRat), [ ELit (LRat i) ] -> A.ELit (LRat (Q.sub Q.zero i)) | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) - | A.Unop A.Minus, [ ELit (LInt i) ] -> A.ELit (LInt (Int64.sub Int64.zero i)) | A.Unop A.ErrorOnEmpty, [ e' ] -> if e' = A.ELit LEmptyError then Errors.raise_spanned_error @@ -206,7 +207,9 @@ let empty_thunked_term : Ast.expr Pos.marked = (Ast.make_abs (Array.of_list [ silent ]) (Bindlib.box (Ast.ELit Ast.LEmptyError, Pos.no_pos)) - Pos.no_pos [ (Ast.TUnit, Pos.no_pos) ] Pos.no_pos) + Pos.no_pos + [ (Ast.TLit Ast.TUnit, Pos.no_pos) ] + Pos.no_pos) let interpret_program (e : Ast.expr Pos.marked) : (Ast.Var.t * Ast.expr Pos.marked) list = match Pos.unmark (evaluate_expr e) with diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 67642cb9..b7788e39 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -24,10 +24,11 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = else Format.fprintf fmt "%a" format_typ t in match Pos.unmark typ with - | TUnit -> Format.fprintf fmt "unit" - | TBool -> Format.fprintf fmt "bool" - | TInt -> Format.fprintf fmt "int" - | TRat -> Format.fprintf fmt "dec" + | TLit TUnit -> Format.fprintf fmt "unit" + | TLit TBool -> Format.fprintf fmt "bool" + | TLit TInt -> Format.fprintf fmt "int" + | TLit TRat -> Format.fprintf fmt "dec" + | TLit TMoney -> Format.fprintf fmt "money" | TTuple ts -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) @@ -46,26 +47,27 @@ let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = | LEmptyError -> Format.fprintf fmt "∅" | LUnit -> Format.fprintf fmt "()" | LRat i -> Format.fprintf fmt "%f" (Q.to_float i) + | LMoney e -> Format.fprintf fmt "$%.2f" Q.(to_float (of_bigint e / of_int 100)) let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = Format.fprintf fmt "%s" ( match Pos.unmark op with - | Add -> "+" - | Sub -> "-" - | Mult -> "*" - | Div -> "/" + | Add _ -> "+" + | Sub _ -> "-" + | Mult _ -> "*" + | Div _ -> "/" | And -> "&&" | Or -> "||" | Eq -> "==" | Neq -> "!=" - | Lt -> "<" - | Lte -> "<=" - | Gt -> ">" - | Gte -> ">=" ) + | Lt _ -> "<" + | Lte _ -> "<=" + | Gt _ -> ">" + | Gte _ -> ">=" ) let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" - (match Pos.unmark op with Minus -> "-" | Not -> "~" | ErrorOnEmpty -> "error_on_empty") + (match Pos.unmark op with Minus _ -> "-" | Not -> "~" | ErrorOnEmpty -> "error_on_empty") let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ -> true | _ -> false diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index ff83db5e..6663dd50 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -21,10 +21,7 @@ module A = Ast module Cli = Utils.Cli type typ = - | TUnit - | TInt - | TBool - | TRat + | TLit of A.typ_lit | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem | TTuple of typ Pos.marked UnionFind.elem list | TEnum of typ Pos.marked UnionFind.elem list @@ -33,10 +30,11 @@ type typ = let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = let ty_repr = UnionFind.get (UnionFind.find ty) in match Pos.unmark ty_repr with - | TUnit -> Format.fprintf fmt "unit" - | TBool -> Format.fprintf fmt "bool" - | TInt -> Format.fprintf fmt "int" - | TRat -> Format.fprintf fmt "dec" + | TLit TUnit -> Format.fprintf fmt "unit" + | TLit TBool -> Format.fprintf fmt "bool" + | TLit TInt -> Format.fprintf fmt "int" + | TLit TRat -> Format.fprintf fmt "dec" + | TLit TMoney -> Format.fprintf fmt "money" | TAny -> Format.fprintf fmt "any type" | TTuple ts -> Format.fprintf fmt "(%a)" @@ -53,8 +51,7 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with - | (TUnit, _), (TUnit, _) | (TBool, _), (TBool, _) | (TInt, _), (TInt, _) | (TRat, _), (TRat, _) -> - () + | (TLit tl1, _), (TLit tl2, _) when tl1 = tl2 -> () | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> unify t11 t21; unify t12 t22 @@ -68,8 +65,8 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin (* TODO: if we get weird error messages, then it means that we should use the persistent version of the union-find data structure. *) Errors.raise_multispanned_error - (Format.asprintf "Error during typechecking, type mismatch: cannot unify %a and %a" - format_typ t1 format_typ t2) + (Format.asprintf "Error during typechecking, types %a and %a are incompatible" format_typ t1 + format_typ t2) [ (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); @@ -77,24 +74,30 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = let pos = Pos.get_position op in - let bt = UnionFind.make (TBool, pos) in + let bt = UnionFind.make (TLit TBool, pos) in + let it = UnionFind.make (TLit TInt, pos) in + let rt = UnionFind.make (TLit TRat, pos) in + let mt = UnionFind.make (TLit TMoney, pos) in let any = UnionFind.make (TAny, pos) in let arr x y = UnionFind.make (TArrow (x, y), pos) in match Pos.unmark op with | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) - | A.Binop (A.Add | A.Sub | A.Mult | A.Div) -> arr any (arr any any) - | A.Binop (A.Lt | A.Lte | A.Gt | A.Gte) -> arr any (arr any bt) + | A.Binop (A.Add KInt | A.Sub KInt | A.Mult KInt | A.Div KInt) -> arr it (arr it it) + | A.Binop (A.Add KRat | A.Sub KRat | A.Mult KRat | A.Div KRat) -> arr rt (arr rt rt) + | A.Binop (A.Add KMoney | A.Sub KMoney | A.Mult KMoney | A.Div KMoney) -> arr mt (arr mt mt) + | A.Binop (A.Lt KInt | A.Lte KInt | A.Gt KInt | A.Gte KInt) -> arr it (arr it bt) + | A.Binop (A.Lt KRat | A.Lte KRat | A.Gt KRat | A.Gte KRat) -> arr rt (arr rt bt) + | A.Binop (A.Lt KMoney | A.Lte KMoney | A.Gt KMoney | A.Gte KMoney) -> arr mt (arr mt bt) | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) - | A.Unop A.Minus -> arr any any + | A.Unop (A.Minus KInt) -> arr it it + | A.Unop (A.Minus KRat) -> arr rt rt + | A.Unop (A.Minus KMoney) -> arr mt mt | A.Unop A.Not -> arr bt bt | A.Unop A.ErrorOnEmpty -> arr any any let rec ast_to_typ (ty : A.typ) : typ = match ty with - | A.TUnit -> TUnit - | A.TBool -> TBool - | A.TRat -> TRat - | A.TInt -> TInt + | A.TLit l -> TLit l | A.TArrow (t1, t2) -> TArrow ( UnionFind.make (Pos.map_under_mark ast_to_typ t1), @@ -106,14 +109,11 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = Pos.map_under_mark (fun ty -> match ty with - | TUnit -> A.TUnit - | TBool -> A.TBool - | TInt -> A.TInt - | TRat -> A.TRat + | TLit l -> A.TLit l | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TEnum ts -> A.TEnum (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) - | TAny -> A.TUnit) + | TAny -> A.TLit A.TUnit) (UnionFind.get (UnionFind.find ty)) type env = typ Pos.marked A.VarMap.t @@ -127,10 +127,11 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) - | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as TBool e) - | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as TInt e) - | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as TRat e) - | ELit LUnit -> UnionFind.make (Pos.same_pos_as TUnit e) + | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as (TLit TBool) e) + | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as (TLit TInt) e) + | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as (TLit TRat) e) + | ELit (LMoney _) -> UnionFind.make (Pos.same_pos_as (TLit TMoney) e) + | ELit LUnit -> UnionFind.make (Pos.same_pos_as (TLit TUnit) e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> let ts = List.map (fun (e, _) -> typecheck_expr_bottom_up env e) es in @@ -209,12 +210,12 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m t_ret | EOp op -> op_type (Pos.same_pos_as op e) | EDefault (just, cons, subs) -> - typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); let tcons = typecheck_expr_bottom_up env cons in List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; tcons | EIfThenElse (cond, et, ef) -> - typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); let tt = typecheck_expr_bottom_up env et in typecheck_expr_top_down env ef tt; tt @@ -228,10 +229,11 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) - | ELit (LBool _) -> unify tau (UnionFind.make (Pos.same_pos_as TBool e)) - | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as TInt e)) - | ELit (LRat _) -> unify tau (UnionFind.make (Pos.same_pos_as TRat e)) - | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as TUnit e)) + | ELit (LBool _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TBool) e)) + | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TInt) e)) + | ELit (LRat _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TRat) e)) + | ELit (LMoney _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TMoney) e)) + | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | ETuple es -> ( let tau' = UnionFind.get (UnionFind.find tau) in @@ -333,11 +335,11 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) let op_typ = op_type (Pos.same_pos_as op e) in unify op_typ tau | EDefault (just, cons, subs) -> - typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as TBool just)); + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); typecheck_expr_top_down env cons tau; List.iter (fun sub -> typecheck_expr_top_down env sub tau) subs | EIfThenElse (cond, et, ef) -> - typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as TBool cond)); + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); typecheck_expr_top_down env et tau; typecheck_expr_top_down env ef tau diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index e7b9530e..23dba6bf 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -65,10 +65,7 @@ module LocationSet = Set.Make (struct end) type typ = - | TBool - | TUnit - | TInt - | TRat + | TLit of Dcalc.Ast.typ_lit | TStruct of StructName.t | TEnum of EnumName.t | TArrow of typ Pos.marked * typ Pos.marked diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 2bf425d2..d6e69f4c 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -149,7 +149,7 @@ let rec get_structs_or_enums_in_type (t : Ast.typ Pos.marked) : TVertexSet.t = | Ast.TEnum e -> TVertexSet.singleton (TVertex.Enum e) | Ast.TArrow (t1, t2) -> TVertexSet.union (get_structs_or_enums_in_type t1) (get_structs_or_enums_in_type t2) - | Ast.TBool | Ast.TUnit | Ast.TInt | Ast.TRat -> TVertexSet.empty + | Ast.TLit _ -> TVertexSet.empty let build_type_graph (structs : Ast.struct_ctx) (enums : Ast.enum_ctx) : TDependencies.t = let g = TDependencies.empty in diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index af036ac1..af240081 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -37,10 +37,11 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = else Format.fprintf fmt "%a" format_typ t in match Pos.unmark typ with - | TUnit -> Format.fprintf fmt "unit" - | TBool -> Format.fprintf fmt "bool" - | TInt -> Format.fprintf fmt "int" - | TRat -> Format.fprintf fmt "dec" + | TLit TUnit -> Format.fprintf fmt "unit" + | TLit TBool -> Format.fprintf fmt "bool" + | TLit TInt -> Format.fprintf fmt "int" + | TLit TRat -> Format.fprintf fmt "dec" + | TLit TMoney -> Format.fprintf fmt "money" | TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e | TArrow (t1, t2) -> diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 764f8762..58e77c24 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -45,10 +45,7 @@ let hole_var : Dcalc.Ast.Var.t = Dcalc.Ast.Var.make ("·", Pos.no_pos) let rec translate_typ (ctx : ctx) (t : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.marked = Pos.same_pos_as ( match Pos.unmark t with - | Ast.TUnit -> Dcalc.Ast.TUnit - | Ast.TBool -> Dcalc.Ast.TBool - | Ast.TInt -> Dcalc.Ast.TInt - | Ast.TRat -> Dcalc.Ast.TRat + | Ast.TLit l -> Dcalc.Ast.TLit l | Ast.TArrow (t1, t2) -> Dcalc.Ast.TArrow (translate_typ ctx t1, translate_typ ctx t2) | Ast.TStruct s_uid -> let s_fields = Ast.StructMap.find s_uid ctx.structs in @@ -299,7 +296,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos Dcalc.Ast.make_abs (Array.of_list [ Pos.unmark a_var ]) next_e var_def_pos - [ (Dcalc.Ast.TArrow ((TUnit, var_def_pos), tau), var_def_pos) ] + [ (Dcalc.Ast.TArrow ((TLit TUnit, var_def_pos), tau), var_def_pos) ] (Pos.get_position e) in let new_e = translate_expr ctx e in @@ -308,7 +305,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos Dcalc.Ast.make_abs (Array.of_list [ silent_var ]) new_e var_def_pos - [ (Dcalc.Ast.TUnit, var_def_pos) ] + [ (Dcalc.Ast.TLit TUnit, var_def_pos) ] var_def_pos in let out_e = Dcalc.Ast.make_app intermediate_e [ thunked_new_e ] (Pos.get_position e) in @@ -416,7 +413,7 @@ let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) rules pos_sigma (List.map (fun (_, tau, _) -> - (Dcalc.Ast.TArrow ((Dcalc.Ast.TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) + (Dcalc.Ast.TArrow ((Dcalc.Ast.TLit TUnit, pos_sigma), (tau, pos_sigma)), pos_sigma)) scope_variables) pos_sigma @@ -425,7 +422,7 @@ let build_scope_typ_from_sig (scope_sig : (Ast.ScopeVar.t * Dcalc.Ast.typ) list) let result_typ = (Dcalc.Ast.TTuple (List.map (fun (_, tau) -> (tau, pos)) scope_sig), pos) in List.fold_right (fun (_, arg_t) acc -> - (Dcalc.Ast.TArrow ((Dcalc.Ast.TArrow ((TUnit, pos), (arg_t, pos)), pos), acc), pos)) + (Dcalc.Ast.TArrow ((Dcalc.Ast.TArrow ((TLit TUnit, pos), (arg_t, pos)), pos), acc), pos)) scope_sig result_typ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName.t) : diff --git a/tests/test_dec/simple.catala b/tests/test_dec/simple.catala index e7a907a8..382c7bd3 100644 --- a/tests/test_dec/simple.catala +++ b/tests/test_dec/simple.catala @@ -9,5 +9,5 @@ new scope A: scope A: def x := 84.648665 def y := 4.368297 - def z := x / y + def z := x /. y */ \ No newline at end of file From b0b231b38a6da4c6df6603c153138e4a8230ee92 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 16:45:23 +0100 Subject: [PATCH 064/142] Handles infinite precision --- src/catala/catala_surface/ast.ml | 4 +- src/catala/catala_surface/desugaring.ml | 3 +- src/catala/catala_surface/lexer.ml | 8 ++-- src/catala/catala_surface/lexer_en.ml | 8 ++-- src/catala/catala_surface/lexer_fr.ml | 8 ++-- src/catala/catala_surface/parser.mly | 8 ++-- src/catala/default_calculus/ast.ml | 2 +- src/catala/default_calculus/interpreter.ml | 10 ++--- src/catala/default_calculus/print.ml | 38 ++++++++++++++++++- src/catala/driver.ml | 3 +- src/catala/utils/cli.ml | 14 ++++++- tests/test_dec/infinite_precision.catala | 15 ++++++++ .../test_dec/infinite_precision.catala.A.out | 4 ++ 13 files changed, 95 insertions(+), 30 deletions(-) create mode 100644 tests/test_dec/infinite_precision.catala create mode 100644 tests/test_dec/infinite_precision.catala.A.out diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 4df599f8..13344a56 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -83,13 +83,13 @@ type literal_date = { literal_date_year : int Pos.marked; } -type literal_number = Int of Int64.t | Dec of Int64.t * Int64.t +type literal_number = Int of Z.t | Dec of Z.t * Z.t type literal_unit = Percent | Year | Month | Day type collection_op = Exists | Forall | Aggregate of aggregate_func -type money_amount = { money_amount_units : Int64.t; money_amount_cents : Int64.t } +type money_amount = { money_amount_units : Z.t; money_amount_cents : Z.t } type literal = | Number of literal_number Pos.marked * literal_unit Pos.marked option diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index bdff831b..6726b647 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -70,9 +70,10 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) match l with | Number ((Int i, _), _) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) | Number ((Dec (i, f), _), _) -> + let digits_f = int_of_float (ceil (float_of_int (Z.log2up f) *. log 2.0 /. log 10.0)) in Scopelang.Ast.ELit (Dcalc.Ast.LRat - Q.(of_int64 i + (of_int64 f / of_float (10.0 ** ceil (log10 (Int64.to_float f)))))) + Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) | _ -> Name_resolution.raise_unsupported_feature "literal" pos in diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 266a66cf..0b4143c7 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -288,8 +288,8 @@ let rec lex_code (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_commas = R.regexp "," in - let units = Int64.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in - let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in + let units = Z.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in + let cents = try Z.of_string (parts 4) with Not_found -> Z.zero in update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', '.', Star '0' .. '9' -> @@ -297,7 +297,7 @@ let rec lex_code (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) update_acc lexbuf; - DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) + DECIMAL_LITERAL (Z.of_string (dec_parts 1), Z.of_string (dec_parts 2)) | "->" -> update_acc lexbuf; ARROW @@ -417,7 +417,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) update_acc lexbuf; - INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> raise_lexer_error prev_pos prev_lexeme let lex_law (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index c3f57700..76373cdf 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -256,8 +256,8 @@ let rec lex_code_en (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_commas = R.regexp "," in - let units = Int64.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in - let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in + let units = Z.of_string (R.substitute ~rex:remove_commas ~subst:(fun _ -> "") units) in + let cents = try Z.of_string (parts 4) with Not_found -> Z.zero in L.update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', '.', Star '0' .. '9' -> @@ -265,7 +265,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) L.update_acc lexbuf; - DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) + DECIMAL_LITERAL (Z.of_string (dec_parts 1), Z.of_string (dec_parts 2)) | "->" -> L.update_acc lexbuf; ARROW @@ -385,7 +385,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) L.update_acc lexbuf; - INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error prev_pos prev_lexeme let lex_law_en (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index bb32ccbc..fa867c5b 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -265,8 +265,8 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = (* Integer literal*) let units = parts 1 in let remove_spaces = R.regexp " " in - let units = Int64.of_string (R.substitute ~rex:remove_spaces ~subst:(fun _ -> "") units) in - let cents = try Int64.of_string (parts 4) with Not_found -> Int64.zero in + let units = Z.of_string (R.substitute ~rex:remove_spaces ~subst:(fun _ -> "") units) in + let cents = try Z.of_string (parts 4) with Not_found -> Z.zero in L.update_acc lexbuf; MONEY_AMOUNT (units, cents) | Plus '0' .. '9', ',', Star '0' .. '9' -> @@ -274,7 +274,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = let dec_parts = R.get_substring (R.exec ~rex:extract_code_title (Utf8.lexeme lexbuf)) in (* Integer literal*) L.update_acc lexbuf; - DECIMAL_LITERAL (Int64.of_string (dec_parts 1), Int64.of_string (dec_parts 2)) + DECIMAL_LITERAL (Z.of_string (dec_parts 1), Z.of_string (dec_parts 2)) | "->" -> L.update_acc lexbuf; ARROW @@ -394,7 +394,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | Plus '0' .. '9' -> (* Integer literal*) L.update_acc lexbuf; - INT_LITERAL (Int64.of_string (Utf8.lexeme lexbuf)) + INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error prev_pos prev_lexeme let lex_law_fr (lexbuf : lexbuf) : token = diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index ebd7a489..605b0449 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -34,10 +34,10 @@ %token LAW_TEXT %token CONSTRUCTOR IDENT %token END_CODE -%token INT_LITERAL +%token INT_LITERAL %token TRUE FALSE -%token DECIMAL_LITERAL -%token MONEY_AMOUNT +%token DECIMAL_LITERAL +%token MONEY_AMOUNT %token BEGIN_CODE TEXT MASTER_FILE %token COLON ALT DATA VERTICAL %token OF INTEGER COLLECTION @@ -158,7 +158,7 @@ unit_literal: | YEAR { (Year, $sloc)} date_int: -| d = INT_LITERAL { (Int64.to_int d, $sloc) } +| d = INT_LITERAL { (Z.to_int d, $sloc) } literal: | l = num_literal u = option(unit_literal) { diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index e7545959..6e151810 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -23,7 +23,7 @@ type typ = | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LBool of bool | LEmptyError | LInt of Int64.t | LRat of Q.t | LMoney of Z.t | LUnit +type lit = LBool of bool | LEmptyError | LInt of Z.t | LRat of Q.t | LMoney of Z.t | LUnit type op_kind = KInt | KRat | KMoney diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index fb5cdbb3..19dfdbd0 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -26,11 +26,11 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis ( match (Pos.unmark op, List.map Pos.unmark args) with | A.Binop A.And, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 && b2)) | A.Binop A.Or, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 || b2)) - | A.Binop (A.Add KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.add i1 i2)) - | A.Binop (A.Sub KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.sub i1 i2)) - | A.Binop (A.Mult KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Int64.mul i1 i2)) + | A.Binop (A.Add KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Z.add i1 i2)) + | A.Binop (A.Sub KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Z.sub i1 i2)) + | A.Binop (A.Mult KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Z.mul i1 i2)) | A.Binop (A.Div KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> - if i2 <> Int64.zero then A.ELit (LInt (Int64.div i1 i2)) + if i2 <> Z.zero then A.ELit (LInt (Z.div i1 i2)) else Errors.raise_multispanned_error "division by zero at runtime" [ @@ -64,7 +64,7 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) | A.Binop _, ([ ELit LEmptyError; _ ] | [ _; ELit LEmptyError ]) -> A.ELit LEmptyError - | A.Unop (A.Minus KInt), [ ELit (LInt i) ] -> A.ELit (LInt (Int64.sub Int64.zero i)) + | A.Unop (A.Minus KInt), [ ELit (LInt i) ] -> A.ELit (LInt (Z.sub Z.zero i)) | A.Unop (A.Minus KRat), [ ELit (LRat i) ] -> A.ELit (LRat (Q.sub Q.zero i)) | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) | A.Unop A.ErrorOnEmpty, [ e' ] -> diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index b7788e39..6f07eb30 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -43,10 +43,44 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with | LBool b -> Format.fprintf fmt "%b" b - | LInt i -> Format.fprintf fmt "%s" (Int64.to_string i) + | LInt i -> Format.fprintf fmt "%s" (Z.to_string i) | LEmptyError -> Format.fprintf fmt "∅" | LUnit -> Format.fprintf fmt "()" - | LRat i -> Format.fprintf fmt "%f" (Q.to_float i) + | LRat i -> + let sign = Q.sign i in + let n = Z.abs (Q.num i) in + let d = Z.abs (Q.den i) in + let int_part = Z.ediv n d in + let n = ref (Z.erem n d) in + let digits = ref [] in + let leading_zeroes (digits : Z.t list) : int = + match + List.fold_right + (fun digit num_leading_zeroes -> + match num_leading_zeroes with + | `End _ -> num_leading_zeroes + | `Begin i -> if Z.(digit = zero) then `Begin (i + 1) else `End i) + digits (`Begin 0) + with + | `End i -> i + | `Begin i -> i + in + while + !n <> Z.zero && List.length !digits - leading_zeroes !digits < !Utils.Cli.max_prec_digits + do + n := Z.mul !n (Z.of_int 10); + digits := Z.ediv !n d :: !digits; + n := Z.erem !n d + done; + Format.fprintf fmt "%s%a.%a%s" + (if sign < 0 then "-" else "") + Z.pp_print int_part + (Format.pp_print_list + ~pp_sep:(fun _fmt () -> ()) + (fun fmt digit -> Format.fprintf fmt "%a" Z.pp_print digit)) + (List.rev !digits) + ( if List.length !digits - leading_zeroes !digits = !Utils.Cli.max_prec_digits then "…" + else "" ) | LMoney e -> Format.fprintf fmt "$%.2f" Q.(to_float (of_bigint e / of_int 100)) let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = diff --git a/src/catala/driver.ml b/src/catala/driver.ml index da54148a..eb923361 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -18,11 +18,12 @@ module Errors = Utils.Errors (** Entry function for the executable. Returns a negative number in case of error. *) let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_output : bool) (pygmentize_loc : string option) (backend : string) (language : string option) - (ex_scope : string option) (output_file : string option) : int = + (max_prec_digits : int option) (ex_scope : string option) (output_file : string option) : int = try Cli.debug_flag := debug; Cli.style_flag := not unstyled; Cli.debug_print "Reading files..."; + (match max_prec_digits with None -> () | Some i -> Cli.max_prec_digits := i); let language = match language with | Some l -> diff --git a/src/catala/utils/cli.ml b/src/catala/utils/cli.ml index b3591efc..14c63624 100644 --- a/src/catala/utils/cli.ml +++ b/src/catala/utils/cli.ml @@ -21,6 +21,9 @@ let debug_flag = ref false (* Styles the terminal output *) let style_flag = ref true +(* Max number of digits to show for decimal results *) +let max_prec_digits = ref 20 + open Cmdliner let file = @@ -53,6 +56,13 @@ let language = & info [ "l"; "language" ] ~docv:"LANG" ~doc:"Input language among: en, fr, non-verbose (default non-verbose)") +let max_prec_digits_opt = + Arg.( + value + & opt (some int) None + & info [ "p"; "max_digits_printed" ] ~docv:"LANG" + ~doc:"Maximum number of significant digits printed for decimal results (default 20)") + let ex_scope = Arg.( value & opt (some string) None & info [ "s"; "scope" ] ~docv:"SCOPE" ~doc:"Scope to be executed") @@ -76,13 +86,13 @@ let pygmentize_loc = Arg.( value & opt (some string) None - & info [ "pygmentize"; "p" ] ~docv:"PYGMENTIZE" + & info [ "pygmentize" ] ~docv:"PYGMENTIZE" ~doc:"Location of a custom pygmentize executable for LaTeX source code highlighting") let catala_t f = Term.( const f $ file $ debug $ unstyled $ wrap_weaved_output $ pygmentize_loc $ backend $ language - $ ex_scope $ output) + $ max_prec_digits_opt $ ex_scope $ output) let info = let doc = diff --git a/tests/test_dec/infinite_precision.catala b/tests/test_dec/infinite_precision.catala new file mode 100644 index 00000000..9ad6df20 --- /dev/null +++ b/tests/test_dec/infinite_precision.catala @@ -0,0 +1,15 @@ +@Article@ + +/* +new scope A: + param x content dec + param y content dec + param z content dec + param a content dec + +scope A: + def x := 84.64866565265689623 + def y := -. 4.36829778705320654980 + def z := 654265429805103220650980650.5705405106540 + def a := x /. y *. (x +. y) *. (x *. x *. z *. z) +*/ \ No newline at end of file diff --git a/tests/test_dec/infinite_precision.catala.A.out b/tests/test_dec/infinite_precision.catala.A.out new file mode 100644 index 00000000..2f4468d4 --- /dev/null +++ b/tests/test_dec/infinite_precision.catala.A.out @@ -0,0 +1,4 @@ +[RESULT] a -> -0.000000000000000000000000000000000000000000000000000000000078695580959228473468… +[RESULT] x -> 84.64866565265689623 +[RESULT] y -> -4.3682977870532065498 +[RESULT] z -> 654265429805103220650980650.570540510654 From fe130f90c7c4f65fb4c6f4d8f3139106c7f011c4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 16:51:03 +0100 Subject: [PATCH 065/142] Update simple test --- tests/test_dec/simple.catala.A.out | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_dec/simple.catala.A.out b/tests/test_dec/simple.catala.A.out index c759f2a4..67b7a267 100644 --- a/tests/test_dec/simple.catala.A.out +++ b/tests/test_dec/simple.catala.A.out @@ -1,3 +1,3 @@ -[RESULT] x -> 84.648665 +[RESULT] x -> 84.0648665 [RESULT] y -> 4.368297 -[RESULT] z -> 19.377956 +[RESULT] z -> 19.24431111254569000230… From 5deee89562363fa0eccc8335ee7895eedf36ecb2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 17:09:43 +0100 Subject: [PATCH 066/142] Run tests in paralell --- tests/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Makefile b/tests/Makefile index 96b3920f..7a90b663 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -4,7 +4,7 @@ CATALA_OPTS?= -CATALA=dune exec --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) +CATALA=dune exec --no-buffer --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) tests: $(wildcard */*.out) From 45684e124c9a65bb85efab6106473241fc39ee59 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 17:31:42 +0100 Subject: [PATCH 067/142] Better test harness and doc --- tests/Makefile | 12 ++++++++---- tests/README.md | 28 +++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/tests/Makefile b/tests/Makefile index 7a90b663..fb22540c 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -11,19 +11,23 @@ tests: $(wildcard */*.out) # Forces all the tests to be redone .FORCE: +%.run: .FORCE + $(CATALA) $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) + # Usage: make /.catala..out # This rule runs the test and compares against the expected output. If the # Catala program is /.catala and the scope to run is # , then the expected output should be in the file # /.catala..out %.out: .FORCE - $(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) 2>&1 | \ - colordiff -u -b $@ - + @$(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) 2>&1 | \ + colordiff -u -b $@ - || { echo "[FAIL $*]"; exit 1; } + @echo "[PASS $*]" # Usage: make /.catala..in # This rule runs the test /.catala, prints its output and # writes this output to the /.catala..out file %.in: .FORCE - -$(CATALA) $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) - -$(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) \ + @-$(CATALA) $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) + @-$(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) \ > $*.out 2>&1 \ No newline at end of file diff --git a/tests/README.md b/tests/README.md index 7551b408..67ab2839 100644 --- a/tests/README.md +++ b/tests/README.md @@ -2,7 +2,33 @@ This folder contains Catala source files designed to test the features of the language. - It uses `make` to launch tests and compare the test terminal output with an expected output. When you create a new test, please register it in the `Makefile` following the other examples. Expected outputs are stored using the convention `.catala..out` in the corresponding test folder. + + +## Workflow for adding new tests + +1. Create a new test file in `foo/bar.catala` (pick the right directory and + an informative name for your test) +2. Write your test, and pick a toplevel scope `A` to run. +3. From this directory, launch `make foo/bar.catala.A.run` to get the output of + your test. +4. When you're happy with the output, launch `make foo/bar.catala.A.in`. This + will record the content of the output of your test into a file. +5. Check that your test pass with `make foo/bar.catala.A.out`. +6. That's it, you've added a new test for the Catala language! + + +## Workflow for fixing regressions + +1. Run `make`, if a test fails you should see something like + `[FAIL foo/bar.catala.A]`. +2. Compare the computed and expected output with `make foo/bar.catala.A.out`. +3. Debug the compiler and/or the test, running `make foo/bar.catala.A.run` + periodically to check the output of Catala on the test case. +4. When you're finished debugging, record the new test output with + `make foo/bar.catala.A.in`. +5. Re-reun `make` to check that everything passes. +6. That's it, you've fixed the Catala test suite to adapt for changes in the + language. \ No newline at end of file From 159901b993ea49c237ae4ad3ec9d8fe2c8d18a3f Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 9 Dec 2020 18:14:52 +0100 Subject: [PATCH 068/142] Performing nearest rounding for money multiplication --- src/catala/catala_surface/desugaring.ml | 17 ++++++++++-- src/catala/default_calculus/interpreter.ml | 20 +++++++++++++++ src/catala/default_calculus/print.ml | 30 ++++++++++++---------- src/catala/default_calculus/typing.ml | 7 +++-- tests/README.md | 2 ++ tests/test_money/simple.catala | 13 ++++++++++ tests/test_money/simple.catala.A.out | 3 +++ 7 files changed, 74 insertions(+), 18 deletions(-) create mode 100644 tests/test_money/simple.catala create mode 100644 tests/test_money/simple.catala.A.out diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 6726b647..24f99569 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -68,13 +68,26 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | Literal l -> let untyped_term = match l with - | Number ((Int i, _), _) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) - | Number ((Dec (i, f), _), _) -> + | Number ((Int i, _), None) -> Scopelang.Ast.ELit (Dcalc.Ast.LInt i) + | Number ((Int i, _), Some (Percent, _)) -> + Scopelang.Ast.ELit (Dcalc.Ast.LRat (Q.div (Q.of_bigint i) (Q.of_int 100))) + | Number ((Dec (i, f), _), None) -> let digits_f = int_of_float (ceil (float_of_int (Z.log2up f) *. log 2.0 /. log 10.0)) in Scopelang.Ast.ELit (Dcalc.Ast.LRat Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) + | Number ((Dec (i, f), _), Some (Percent, _)) -> + let digits_f = + int_of_float (ceil (float_of_int (Z.log2up f) *. log 2.0 /. log 10.0)) + 2 + (* because of % *) + in + Scopelang.Ast.ELit + (Dcalc.Ast.LRat + Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) + | MoneyAmount i -> + Scopelang.Ast.ELit + (Dcalc.Ast.LMoney Z.((i.money_amount_units * of_int 100) + i.money_amount_cents)) | _ -> Name_resolution.raise_unsupported_feature "literal" pos in Bindlib.box (untyped_term, pos) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 19dfdbd0..d3eabab1 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -48,6 +48,26 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The division operator:", Pos.get_position op); (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] + | A.Binop (A.Add KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> + A.ELit (LMoney (Z.add i1 i2)) + | A.Binop (A.Sub KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> + A.ELit (LMoney (Z.sub i1 i2)) + | A.Binop (A.Mult KMoney), [ ELit (LMoney i1); ELit (LRat i2) ] -> + let rat_result = Q.mul (Q.of_bigint i1) i2 in + let res, remainder = Z.div_rem (Q.num rat_result) (Q.den rat_result) in + (* we perform nearest rounding when multiplying an amount of money by a decimal !*) + let out = + if Z.(of_int 2 * remainder >= Q.den rat_result) then Z.add res (Z.of_int 1) else res + in + A.ELit (LMoney out) + | A.Binop (A.Div KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> + if i2 <> Z.zero then A.ELit (LRat (Q.div (Q.of_bigint i1) (Q.of_bigint i2))) + else + Errors.raise_multispanned_error "division by zero at runtime" + [ + (Some "The division operator:", Pos.get_position op); + (Some "The null denominator:", Pos.get_position (List.nth args 2)); + ] | A.Binop (A.Lt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) | A.Binop (A.Lte KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) | A.Binop (A.Gt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 6f07eb30..2212df76 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -83,21 +83,23 @@ let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = else "" ) | LMoney e -> Format.fprintf fmt "$%.2f" Q.(to_float (of_bigint e / of_int 100)) +let format_op_kind (fmt : Format.formatter) (k : op_kind) = + Format.fprintf fmt "%s" (match k with KInt -> "" | KRat -> "." | KMoney -> "$") + let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = - Format.fprintf fmt "%s" - ( match Pos.unmark op with - | Add _ -> "+" - | Sub _ -> "-" - | Mult _ -> "*" - | Div _ -> "/" - | And -> "&&" - | Or -> "||" - | Eq -> "==" - | Neq -> "!=" - | Lt _ -> "<" - | Lte _ -> "<=" - | Gt _ -> ">" - | Gte _ -> ">=" ) + match Pos.unmark op with + | Add k -> Format.fprintf fmt "+%a" format_op_kind k + | Sub k -> Format.fprintf fmt "-%a" format_op_kind k + | Mult k -> Format.fprintf fmt "*%a" format_op_kind k + | Div k -> Format.fprintf fmt "/%a" format_op_kind k + | And -> Format.fprintf fmt "%s" "&&" + | Or -> Format.fprintf fmt "%s" "||" + | Eq -> Format.fprintf fmt "%s" "==" + | Neq -> Format.fprintf fmt "%s" "!=" + | Lt _ -> Format.fprintf fmt "%s" "<" + | Lte _ -> Format.fprintf fmt "%s" "<=" + | Gt _ -> Format.fprintf fmt "%s" ">" + | Gte _ -> Format.fprintf fmt "%s" ">=" let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 6663dd50..a51ecdfc 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -84,7 +84,9 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) | A.Binop (A.Add KInt | A.Sub KInt | A.Mult KInt | A.Div KInt) -> arr it (arr it it) | A.Binop (A.Add KRat | A.Sub KRat | A.Mult KRat | A.Div KRat) -> arr rt (arr rt rt) - | A.Binop (A.Add KMoney | A.Sub KMoney | A.Mult KMoney | A.Div KMoney) -> arr mt (arr mt mt) + | A.Binop (A.Add KMoney | A.Sub KMoney) -> arr mt (arr mt mt) + | A.Binop (A.Div KMoney) -> arr mt (arr mt rt) + | A.Binop (A.Mult KMoney) -> arr mt (arr rt mt) | A.Binop (A.Lt KInt | A.Lte KInt | A.Gt KInt | A.Gte KInt) -> arr it (arr it bt) | A.Binop (A.Lt KRat | A.Lte KRat | A.Gt KRat | A.Gte KRat) -> arr rt (arr rt bt) | A.Binop (A.Lt KMoney | A.Lte KMoney | A.Gt KMoney | A.Gte KMoney) -> arr mt (arr mt bt) @@ -184,7 +186,8 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in let env = List.fold_left - (fun env (x, tau) -> A.VarMap.add x (ast_to_typ (Pos.unmark tau), pos_binder) env) + (fun env (x, tau) -> + A.VarMap.add x (ast_to_typ (Pos.unmark tau), Pos.get_position tau) env) env xstaus in List.fold_right diff --git a/tests/README.md b/tests/README.md index 67ab2839..ffdf81b4 100644 --- a/tests/README.md +++ b/tests/README.md @@ -6,6 +6,8 @@ It uses `make` to launch tests and compare the test terminal output with an expe When you create a new test, please register it in the `Makefile` following the other examples. Expected outputs are stored using the convention `.catala..out` in the corresponding test folder. +For both workflows: use `CATALA_OPTS="..." make ...` to pass in Catala compiler +options when debugging. ## Workflow for adding new tests diff --git a/tests/test_money/simple.catala b/tests/test_money/simple.catala new file mode 100644 index 00000000..7d5653a4 --- /dev/null +++ b/tests/test_money/simple.catala @@ -0,0 +1,13 @@ +@Article@ + +/* +new scope A: + param x content amount + param y content amount + param z content amount + +scope A: + def x := $123.54 + def y := $8548,650.96 + def z := $250,000,000 *$ ((x /$ y) *. 0.2 %) +*/ \ No newline at end of file diff --git a/tests/test_money/simple.catala.A.out b/tests/test_money/simple.catala.A.out new file mode 100644 index 00000000..26094971 --- /dev/null +++ b/tests/test_money/simple.catala.A.out @@ -0,0 +1,3 @@ +[RESULT] x -> $123.54 +[RESULT] y -> $8548650.96 +[RESULT] z -> $7.23 From a4916208ba5ec4d143ff935cf799258f26567cb4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 09:27:51 +0100 Subject: [PATCH 069/142] amount -> money --- CONTRIBUTING.md | 2 +- doc/enlish_token_list.md | 2 +- .../allocations_familiales/metadata.catala_fr | 48 +++++++++---------- ...Section_I_Dispositions_generales.catala_fr | 18 +++---- examples/tutorial/tutorial_en.catala_en | 8 ++-- examples/us_tax_code/section_1015.catala_en | 18 +++---- examples/us_tax_code/section_121.catala_en | 6 +-- examples/us_tax_code/section_132.catala_en | 10 ++-- src/catala/catala_surface/lexer.ml | 4 +- src/catala/catala_surface/lexer_en.ml | 4 +- src/catala/catala_surface/lexer_fr.ml | 4 +- src/catala/default_calculus/print.ml | 6 +-- src/catala/scope_language/print.ml | 6 +-- .../en/atom/grammars/catala_en.cson | 4 +- syntax_highlighting/en/catala_en.iro | 4 +- syntax_highlighting/en/pygments/catala_en.py | 20 ++++---- .../en/vscode/syntaxes/catalavs.xml | 4 +- .../fr/atom/grammars/catala_fr.cson | 2 +- syntax_highlighting/fr/catala_fr.iro | 2 +- syntax_highlighting/fr/pygments/catala_fr.py | 20 ++++---- .../fr/vscode/syntaxes/catalavs.xml | 2 +- .../nv/atom/grammars/catala_nv.cson | 4 +- syntax_highlighting/nv/catala_nv.iro | 4 +- syntax_highlighting/nv/pygments/catala_nv.py | 4 +- .../nv/vscode/syntaxes/catalavs.xml | 4 +- tests/Makefile | 4 +- tests/test_money/no_mingle.catala | 13 +++++ tests/test_money/no_mingle.catala.A.out | 13 +++++ tests/test_money/simple.catala | 6 +-- tests/test_scope/cycle_in_scope.catala.A.out | 4 +- tests/test_scope/sub_scope.catala.B.out | 4 +- tests/test_scope/sub_sub_scope.catala.C.out | 2 +- tests/test_struct/nested.catala.A.out | 2 +- tests/test_struct/nested2.catala.A.out | 2 +- 34 files changed, 148 insertions(+), 112 deletions(-) create mode 100644 tests/test_money/no_mingle.catala create mode 100644 tests/test_money/no_mingle.catala.A.out diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a0d08361..ff6c3ac2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -87,7 +87,7 @@ While all the code sections are equivalent in terms of execution, you can mark s /* declaration structure FooBar: data foo content boolean - data bar content amount + data bar content money */ diff --git a/doc/enlish_token_list.md b/doc/enlish_token_list.md index 16866b95..66b336a0 100644 --- a/doc/enlish_token_list.md +++ b/doc/enlish_token_list.md @@ -157,7 +157,7 @@ Current proposal : "amount". The base data type for representing amounts of money. ``` -data foo content amount +data foo content money ``` ## TEXT diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index db66c4bc..1f901074 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -17,7 +17,7 @@ déclaration énumération PriseEnCharge : déclaration structure Enfant : donnée fin_obligation_scolaire contenu date donnée âge contenu entier - donnée rémuneration_mensuelle contenu montant + donnée rémuneration_mensuelle contenu argent donnée prise_en_charge contenu PriseEnCharge condition confié_service_social @@ -99,8 +99,8 @@ déclaration énumération Prestation: déclaration structure PrestationsFamiliales : condition conditions_hors_âge dépend de Enfant condition droits_ouverts dépend de Enfant - donnée base_mensuelle contenu montant - donnée base_mensuelle_dom contenu montant + donnée base_mensuelle contenu argent + donnée base_mensuelle_dom contenu argent déclaration énumération ChargeAllocation : -- Complète @@ -110,21 +110,21 @@ déclaration structure AllocationsFamiliales : condition droits_ouverts donnée date_ouverture_droits contenu date condition conditions_hors_âge dépend de Enfant - donnée base contenu montant - donnée avec_garde_alternée contenu montant - donnée montant_versé contenu montant + donnée base contenu argent + donnée avec_garde_alternée contenu argent + donnée montant_versé contenu argent donnée récipiendaire_par_enfant contenu Personne dépend de Enfant donnée charge_par_enfant contenu ChargeAllocation dépend de Enfant donnée rapport_enfants_total_moyen contenu décimal donnée nombre_total_enfants contenu entier donnée nombre_moyen_enfants contenu décimal - donnée montant_premier_enfant contenu montant - donnée montant_deuxieme_enfant contenu montant - donnée montant_troisième_enfant_et_plus contenu montant + donnée montant_premier_enfant contenu argent + donnée montant_deuxieme_enfant contenu argent + donnée montant_troisième_enfant_et_plus contenu argent déclaration structure AllocationForfaitaire : condition droits_ouverts dépend de Enfant - donnée montant_versé contenu montant + donnée montant_versé contenu argent déclaration énumération ChoixParentAllocataire : -- UnParent contenu Personne @@ -140,16 +140,16 @@ déclaration structure AllocationsGardeAlternée : déclaration structure MajorationsAllocationsFamiliales : condition droits_ouverts dépend de Enfant - donnée base_par_enfant contenu montant dépend de Enfant - donnée avec_garde_alternée contenu montant dépend de Enfant - donnée montant_versé contenu montant + donnée base_par_enfant contenu argent dépend de Enfant + donnée avec_garde_alternée contenu argent dépend de Enfant + donnée montant_versé contenu argent déclaration structure ComplémentDégressif : condition droits_ouverts dépend de montant - donnée dépassement contenu montant dépend de montant - donnée pour_allocation_forfaitaire contenu montant - donnée pour_allocations_familiales_et_majorations contenu montant - donnée montant_versé contenu montant + donnée dépassement contenu argent dépend de montant + donnée pour_allocation_forfaitaire contenu argent + donnée pour_allocations_familiales_et_majorations contenu argent + donnée montant_versé contenu argent déclaration structure TitreI: condition droits_ouverts_allocations_familiales dépend de Personne @@ -161,25 +161,25 @@ déclaration structure L512_3 : donnée âge_limite_alinéa_2 contenu entier donnée âge_limite_alinéa_2_alternatif contenu entier condition âge_limite_alinéa_2_alternatif_utilisé - donnée plafond_rémunération_mensuelle_alinéa_2 contenu montant + donnée plafond_rémunération_mensuelle_alinéa_2 contenu argent déclaration structure L521_1 : - donnée nombre_minimum_enfants contenu montant - donnée ressources_ménage contenu montant + donnée nombre_minimum_enfants contenu argent + donnée ressources_ménage contenu argent déclaration structure L521_3 : donnée âge_limite_alinéa_1 contenu entier dépend de Enfant - donnée minimum_alinéa_2 contenu montant + donnée minimum_alinéa_2 contenu argent déclaration structure L751_1 : condition régime_outre_mer déclaration structure D521_3 : - donnée plafond_I contenu montant - donnée plafond_II contenu montant + donnée plafond_I contenu argent + donnée plafond_II contenu argent déclaration structure SMIC : - donnée brut_horaire contenu montant dépend de Collectivité + donnée brut_horaire contenu argent dépend de Collectivité déclaration champ d'application CalculPrestationsFamiliales : # Les règles déclarées dans PrestationsFamiliales pourront utiliser diff --git a/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr b/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr index 7e70a0d8..99e27733 100644 --- a/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr +++ b/examples/code_general_impots/Section_I_Dispositions_generales.catala_fr @@ -36,15 +36,15 @@ total dont sont retranchées les charges énumérées à l'article 156. /* déclaration structure RevenuNetGlobal: -donnée revenus_fonciers contenu montant -donnée bénéfices_industriels_commerciaux contenu montant -donnée rémunérations_dirigeants contenu montant -donnée bénéfices_agricoles contenu montant -donnée traitements_salaires contenu montant -donnée bénéfices_non_commerciaux contenu montant -donnée revenus_capitaux_mobiliers contenu montant -donnée plus_values contenu montant -donnée total contenu montant +donnée revenus_fonciers contenu argent +donnée bénéfices_industriels_commerciaux contenu argent +donnée rémunérations_dirigeants contenu argent +donnée bénéfices_agricoles contenu argent +donnée traitements_salaires contenu argent +donnée bénéfices_non_commerciaux contenu argent +donnée revenus_capitaux_mobiliers contenu argent +donnée plus_values contenu argent +donnée total contenu argent déclaration champ d'application CalculImpotSurLeRevenu : contexte revenu_net_global contenu RevenuNetGlobal diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index 94fd31f1..af24c70a 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -46,11 +46,11 @@ individual and the income tax computation: @@Begin metadata@@ /* declaration structure Individual: - data income content amount + data income content money declaration structure Article1: data fixed_percentage content decimal - data income_tax content amount + data income_tax content money */ @@End metadata@@ @@ -158,13 +158,13 @@ computation: @@Begin metadata@@ /* declaration structure TwoBrackets: - data breakpoint content amount + data breakpoint content money data rate1 content decimal data rate2 content decimal declaration scope TwoBracketsTaxComputation : context brackets content TwoBrackets - context tax_formula content amount depends on amount + context tax_formula content money depends on amount */ @@End metadata@@ diff --git a/examples/us_tax_code/section_1015.catala_en b/examples/us_tax_code/section_1015.catala_en index 16770ee3..4161ce45 100644 --- a/examples/us_tax_code/section_1015.catala_en +++ b/examples/us_tax_code/section_1015.catala_en @@ -13,23 +13,23 @@ declaration structure Acquisition: data no_sale_or_exchange_before content boolean declaration structure Value: - data fair_market content amount depends on date - data last_acquisition content amount - data net_appreciation content amount + data fair_market content money depends on date + data last_acquisition content money + data net_appreciation content money declaration structure Transferor: - data basis content amount + data basis content money data basis_known content optional amount data acquisition content Acquisition - data gain_or_loss content amount depends on date + data gain_or_loss content money depends on date declaration scope BasisOfGift: context acquisition content Acquisition - context basis_subsection_a content amount - context basis content amount - context basis_bonus_after_1976 content amount + context basis_subsection_a content money + context basis content money + context basis_bonus_after_1976 content money context transferor content Transferor - context gift_tax_paid content amount + context gift_tax_paid content money */ @@End metadata@@ diff --git a/examples/us_tax_code/section_121.catala_en b/examples/us_tax_code/section_121.catala_en index 878a694b..5e2084f1 100644 --- a/examples/us_tax_code/section_121.catala_en +++ b/examples/us_tax_code/section_121.catala_en @@ -13,14 +13,14 @@ declaration structure Property: declaration structure SaleOrExchange: data property content Property - data gain content amount + data gain content money data date_of_sale_or_exchange content date declaration scope Section121: context taxpayer content Person context applicable condition - context maximum_gain_excluded content amount - context gain_considered_for_exclusion content amount + context maximum_gain_excluded content money + context gain_considered_for_exclusion content money context sale_or_exchange content SaleOrExchange context included_in_gross_income condition context ownage_considered_for_gain_inclusion condition diff --git a/examples/us_tax_code/section_132.catala_en b/examples/us_tax_code/section_132.catala_en index 41a8058b..cd47db87 100644 --- a/examples/us_tax_code/section_132.catala_en +++ b/examples/us_tax_code/section_132.catala_en @@ -8,12 +8,12 @@ declaration enumeration DiscountType: -- Services declaration scope QualifiedEmployeeDiscount: - context customer_price content amount - context employee_price content amount + context customer_price content money + context employee_price content money context gross_profit_percentage content decimal - context qualified_employee_discount content amount - context employee_discount content amount - context aggregate_cost content amount + context qualified_employee_discount content money + context employee_discount content money + context aggregate_cost content money context discount_type content DiscountType */ @@End metadata@@ diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 0b4143c7..d2924021 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -65,7 +65,7 @@ let token_list : (string * token) list = ("set", COLLECTION); ("enum", ENUM); ("int", INTEGER); - ("amount", MONEY); + ("money", MONEY); ("text", TEXT); ("decimal", DECIMAL); ("date", DATE); @@ -155,7 +155,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "int" -> update_acc lexbuf; INTEGER - | "amount" -> + | "money" -> update_acc lexbuf; MONEY | "text" -> diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 76373cdf..37d29876 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -33,7 +33,7 @@ let token_list_en : (string * token) list = ("collection", COLLECTION); ("enumeration", ENUM); ("integer", INTEGER); - ("amount", MONEY); + ("money", MONEY); ("text", TEXT); ("decimal", DECIMAL); ("date", DATE); @@ -123,7 +123,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "integer" -> L.update_acc lexbuf; INTEGER - | "amount" -> + | "money" -> L.update_acc lexbuf; MONEY | "text" -> diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index fa867c5b..a41b5ea5 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -33,7 +33,7 @@ let token_list_fr : (string * token) list = ("collection", COLLECTION); ("énumération", ENUM); ("entier", INTEGER); - ("montant", MONEY); + ("argent", MONEY); ("texte", TEXT); ("decimal", DECIMAL); ("date", DATE); @@ -124,7 +124,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "entier" -> L.update_acc lexbuf; INTEGER - | "montant" -> + | "argent" -> L.update_acc lexbuf; MONEY | "texte" -> diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 2212df76..30b7c20f 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -25,9 +25,9 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = in match Pos.unmark typ with | TLit TUnit -> Format.fprintf fmt "unit" - | TLit TBool -> Format.fprintf fmt "bool" - | TLit TInt -> Format.fprintf fmt "int" - | TLit TRat -> Format.fprintf fmt "dec" + | TLit TBool -> Format.fprintf fmt "boolean" + | TLit TInt -> Format.fprintf fmt "integer" + | TLit TRat -> Format.fprintf fmt "decimal" | TLit TMoney -> Format.fprintf fmt "money" | TTuple ts -> Format.fprintf fmt "(%a)" diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index af240081..393cfe4b 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -38,9 +38,9 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = in match Pos.unmark typ with | TLit TUnit -> Format.fprintf fmt "unit" - | TLit TBool -> Format.fprintf fmt "bool" - | TLit TInt -> Format.fprintf fmt "int" - | TLit TRat -> Format.fprintf fmt "dec" + | TLit TBool -> Format.fprintf fmt "boolean" + | TLit TInt -> Format.fprintf fmt "integer" + | TLit TRat -> Format.fprintf fmt "decimal" | TLit TMoney -> Format.fprintf fmt "money" | TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e diff --git a/syntax_highlighting/en/atom/grammars/catala_en.cson b/syntax_highlighting/en/atom/grammars/catala_en.cson index 4c404679..603d61cc 100644 --- a/syntax_highlighting/en/atom/grammars/catala_en.cson +++ b/syntax_highlighting/en/atom/grammars/catala_en.cson @@ -120,11 +120,11 @@ 'name' : 'punctuation.catala_en' } { - 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)' + 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)' 'name' : 'keyword.operator.catala_en' } { - 'match' : '\\b(integer|boolean|date|amount|text|decimal|number|sum|now)\\b' + 'match' : '\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b' 'name' : 'support.type.catala_en' } { diff --git a/syntax_highlighting/en/catala_en.iro b/syntax_highlighting/en/catala_en.iro index 958b2031..243c083d 100644 --- a/syntax_highlighting/en/catala_en.iro +++ b/syntax_highlighting/en/catala_en.iro @@ -240,12 +240,12 @@ code : context { } : pattern { - regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\\$|%|year|month|day) + regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) styles [] = .operator; } : pattern { - regex \= \b(integer|boolean|date|amount|text|decimal|number|sum|now)\b + regex \= \b(integer|boolean|date|money|text|decimal|number|sum|now)\b styles [] = .primitive; } diff --git a/syntax_highlighting/en/pygments/catala_en.py b/syntax_highlighting/en/pygments/catala_en.py index fbf30a55..6a4e537e 100644 --- a/syntax_highlighting/en/pygments/catala_en.py +++ b/syntax_highlighting/en/pygments/catala_en.py @@ -3,7 +3,8 @@ from pygments.token import * import re -__all__=['CatalaEnLexer'] +__all__ = ['CatalaEnLexer'] + class CatalaEnLexer(RegexLexer): name = 'CatalaEn' @@ -12,7 +13,7 @@ class CatalaEnLexer(RegexLexer): flags = re.MULTILINE | re.UNICODE tokens = { - 'root' : [ + 'root': [ (u'(@@)', bygroups(Generic.Heading), 'main__1'), (u'(@)', bygroups(Generic.Heading), 'main__2'), (u'([^\\/\\n\\r])', bygroups(Text)), @@ -20,18 +21,21 @@ class CatalaEnLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'code' : [ + 'code': [ (u'(\\*\\/)', bygroups(Text), 'root'), (u'(\\s*\\#.*$)', bygroups(Comment.Single)), - (u'(context)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), + (u'(context)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', + bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(match|with\\s+pattern|fixed|by|decreasing|increasing|varies|with|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b', bygroups(Keyword.Reserved)), (u'\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))', bygroups(Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)', bygroups(Operator)), - (u'\\b(integer|boolean|date|amount|text|decimal|number|sum|now)\\b', bygroups(Keyword.Type)), + (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)', + bygroups(Operator)), + (u'\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b', + bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Variable)), @@ -39,13 +43,13 @@ class CatalaEnLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__1' : [ + 'main__1': [ (u'(@@)', bygroups(Generic.Heading), 'root'), (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__2' : [ + 'main__2': [ (u'(@)', bygroups(Generic.Heading), 'root'), (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), diff --git a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml index 319404f9..d6a8d374 100644 --- a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml @@ -191,13 +191,13 @@ match - (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\\$|%|year|month|day) + (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) name keyword.operator.catala_en match - \b(integer|boolean|date|amount|text|decimal|number|sum|now)\b + \b(integer|boolean|date|money|text|decimal|number|sum|now)\b name support.type.catala_en diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index 0f26ff7b..d23bf6c1 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -124,7 +124,7 @@ 'name' : 'keyword.operator.catala_fr' } { - 'match' : '\\b(entier|booléen|date|montant|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\\b' + 'match' : '\\b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\\b' 'name' : 'support.type.catala_fr' } { diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index 86c6a6e3..546910c1 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -245,7 +245,7 @@ code : context { } : pattern { - regex \= \b(entier|booléen|date|montant|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b + regex \= \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b styles [] = .primitive; } diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 0ce38e70..21047bf2 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -3,7 +3,8 @@ from pygments.token import * import re -__all__=['CatalaFrLexer'] +__all__ = ['CatalaFrLexer'] + class CatalaFrLexer(RegexLexer): name = 'CatalaFr' @@ -12,7 +13,7 @@ class CatalaFrLexer(RegexLexer): flags = re.MULTILINE | re.UNICODE tokens = { - 'root' : [ + 'root': [ (u'(@@)', bygroups(Generic.Heading), 'main__1'), (u'(@)', bygroups(Generic.Heading), 'main__2'), (u'([^\\/\\n\\r])', bygroups(Text)), @@ -20,18 +21,21 @@ class CatalaFrLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'code' : [ + 'code': [ (u'(\\*\\/)', bygroups(Text), 'root'), (u'(\\s*\\#.*$)', bygroups(Comment.Single)), - (u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), + (u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', + bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(selon|sous\\s+forme|fix\xe9|par|d\xe9croissante|croissante|varie|avec|on\\s+a|dans|tel\\s+que|existe|pour|tout|de|si|alors|sinon)\\b', bygroups(Keyword.Reserved)), (u'\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|d\xe9pend\\s+de|d\xe9claration|inclus|collection|contenu|optionnel|structure|\xe9num\xe9ration|contexte|r\xe8gle|sous\\s+condition|condition|donn\xe9e|cons\xe9quence|rempli|\xe9gal\\s+\xe0|assertion|d\xe9finition)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(vrai|faux)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))', bygroups(Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour)', bygroups(Operator)), - (u'\\b(entier|bool\xe9en|date|montant|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme|date_aujourd_hui)\\b', bygroups(Keyword.Type)), + (u'(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour)', + bygroups(Operator)), + (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme|date_aujourd_hui)\\b', + bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Variable)), @@ -39,13 +43,13 @@ class CatalaFrLexer(RegexLexer): ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__1' : [ + 'main__1': [ (u'(@@)', bygroups(Generic.Heading), 'root'), (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), ('.', Text), ], - 'main__2' : [ + 'main__2': [ (u'(@)', bygroups(Generic.Heading), 'root'), (u'(.)', bygroups(Generic.Heading)), ('(\n|\r|\r\n)', Text), diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index a3fff0c2..b9af454c 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -197,7 +197,7 @@ match - \b(entier|booléen|date|montant|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b + \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b name support.type.catala_fr diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index a069501c..943a3a30 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -120,11 +120,11 @@ 'name' : 'punctuation.catala_nv' } { - 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\\\$|%|year|month|day)' + 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)' 'name' : 'keyword.operator.catala_nv' } { - 'match' : '\\b(int|bool|date|amount|text|decimal|number|sum|now)\\b' + 'match' : '\\b(int|bool|date|money|text|decimal|number|sum|now)\\b' 'name' : 'support.type.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index 029ee140..2dd58f73 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -240,12 +240,12 @@ code : context { } : pattern { - regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\\$|%|year|month|day) + regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) styles [] = .operator; } : pattern { - regex \= \b(int|bool|date|amount|text|decimal|number|sum|now)\b + regex \= \b(int|bool|date|money|text|decimal|number|sum|now)\b styles [] = .primitive; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index 192c3c04..9f322053 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -33,9 +33,9 @@ class CatalaNvLexer(RegexLexer): (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[|\\])', bygroups(Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\\\$|%|year|month|day)', + (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)', bygroups(Operator)), - (u'\\b(int|bool|date|amount|text|decimal|number|sum|now)\\b', + (u'\\b(int|bool|date|money|text|decimal|number|sum|now)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index a3c13c45..84a1ed97 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -191,13 +191,13 @@ match - (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\\$|%|year|month|day) + (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) name keyword.operator.catala_nv match - \b(int|bool|date|amount|text|decimal|number|sum|now)\b + \b(int|bool|date|money|text|decimal|number|sum|now)\b name support.type.catala_nv diff --git a/tests/Makefile b/tests/Makefile index fb22540c..2b58b826 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -6,7 +6,9 @@ CATALA_OPTS?= CATALA=dune exec --no-buffer --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) -tests: $(wildcard */*.out) +pass_tests: $(wildcard */*.out) + +reset_tests: $(subst .out,.in,$(wildcard */*.out)) # Forces all the tests to be redone .FORCE: diff --git a/tests/test_money/no_mingle.catala b/tests/test_money/no_mingle.catala new file mode 100644 index 00000000..72fae441 --- /dev/null +++ b/tests/test_money/no_mingle.catala @@ -0,0 +1,13 @@ +@Article@ + +/* +new scope A: + param x content money + param y content money + param z content money + +scope A: + def x := $123.54 + def y := $8548,650.96 + def z := (x *$ y) +*/ \ No newline at end of file diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out new file mode 100644 index 00000000..b4e19443 --- /dev/null +++ b/tests/test_money/no_mingle.catala.A.out @@ -0,0 +1,13 @@ +[ERROR] Error during typechecking, types dec and money are incompatible +[ERROR] +[ERROR] Type dec coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 12 | def z := (x *$ y) +[ERROR] | ^^ +[ERROR] +[ERROR] Type money coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 4 | new scope A: +[ERROR] | ^ diff --git a/tests/test_money/simple.catala b/tests/test_money/simple.catala index 7d5653a4..dec82db8 100644 --- a/tests/test_money/simple.catala +++ b/tests/test_money/simple.catala @@ -2,9 +2,9 @@ /* new scope A: - param x content amount - param y content amount - param z content amount + param x content money + param y content money + param z content money scope A: def x := $123.54 diff --git a/tests/test_scope/cycle_in_scope.catala.A.out b/tests/test_scope/cycle_in_scope.catala.A.out index 56338bb3..8514de34 100644 --- a/tests/test_scope/cycle_in_scope.catala.A.out +++ b/tests/test_scope/cycle_in_scope.catala.A.out @@ -22,7 +22,7 @@ [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | [ERROR] 13 | def z [y < 1] := y -[ERROR] | ^ +[ERROR] | ^ [ERROR] [ERROR] Cycle variable x, declared: [ERROR] --> test_scope/cycle_in_scope.catala @@ -34,4 +34,4 @@ [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | [ERROR] 11 | def y [x >= 0] := x -[ERROR] | ^ +[ERROR] | ^ diff --git a/tests/test_scope/sub_scope.catala.B.out b/tests/test_scope/sub_scope.catala.B.out index db60adbc..cc4ef583 100644 --- a/tests/test_scope/sub_scope.catala.B.out +++ b/tests/test_scope/sub_scope.catala.B.out @@ -1,2 +1,2 @@ -[RESULT] a -> 42 -[RESULT] b -> true \ No newline at end of file +[RESULT] a -> 42 +[RESULT] b -> true diff --git a/tests/test_scope/sub_sub_scope.catala.C.out b/tests/test_scope/sub_sub_scope.catala.C.out index 59553b02..70b6389a 100644 --- a/tests/test_scope/sub_sub_scope.catala.C.out +++ b/tests/test_scope/sub_sub_scope.catala.C.out @@ -1 +1 @@ -[RESULT] z -> 2 \ No newline at end of file +[RESULT] z -> 2 diff --git a/tests/test_struct/nested.catala.A.out b/tests/test_struct/nested.catala.A.out index 9161e374..7dc817d4 100644 --- a/tests/test_struct/nested.catala.A.out +++ b/tests/test_struct/nested.catala.A.out @@ -3,4 +3,4 @@ [ERROR] --> test_struct/nested.catala [ERROR] | [ERROR] 5 | data x content S -[ERROR] | ^ +[ERROR] | ^ diff --git a/tests/test_struct/nested2.catala.A.out b/tests/test_struct/nested2.catala.A.out index 22ce0bdc..56204f5d 100644 --- a/tests/test_struct/nested2.catala.A.out +++ b/tests/test_struct/nested2.catala.A.out @@ -3,4 +3,4 @@ [ERROR] --> test_struct/nested2.catala [ERROR] | [ERROR] 5 | data x content E -[ERROR] | ^ +[ERROR] | ^ From 0038a1ea2d6e4cb8d7c415253b58f9ab4c919b54 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 09:42:32 +0100 Subject: [PATCH 070/142] Updated example --- examples/allocations_familiales/metadata.catala_fr | 4 ++-- examples/tutorial/tutorial_en.catala_en | 2 +- examples/us_tax_code/section_1015.catala_en | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index 1f901074..1f78de53 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -145,8 +145,8 @@ déclaration structure MajorationsAllocationsFamiliales : donnée montant_versé contenu argent déclaration structure ComplémentDégressif : - condition droits_ouverts dépend de montant - donnée dépassement contenu argent dépend de montant + condition droits_ouverts dépend de argent + donnée dépassement contenu argent dépend de argent donnée pour_allocation_forfaitaire contenu argent donnée pour_allocations_familiales_et_majorations contenu argent donnée montant_versé contenu argent diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index af24c70a..0f075d90 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -164,7 +164,7 @@ declaration structure TwoBrackets: declaration scope TwoBracketsTaxComputation : context brackets content TwoBrackets - context tax_formula content money depends on amount + context tax_formula content money depends on money */ @@End metadata@@ diff --git a/examples/us_tax_code/section_1015.catala_en b/examples/us_tax_code/section_1015.catala_en index 4161ce45..8ff4bbfa 100644 --- a/examples/us_tax_code/section_1015.catala_en +++ b/examples/us_tax_code/section_1015.catala_en @@ -19,7 +19,7 @@ declaration structure Value: declaration structure Transferor: data basis content money - data basis_known content optional amount + data basis_known content optional money data acquisition content Acquisition data gain_or_loss content money depends on date From 902c3f8d7d7f4140ef3bf10e2e466f7be3961f75 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 11:35:56 +0100 Subject: [PATCH 071/142] Added date and durations handling --- Makefile | 3 +- src/catala/catala_surface/ast.ml | 12 ++++- src/catala/catala_surface/desugaring.ml | 26 ++++++++++- src/catala/catala_surface/dune | 2 +- src/catala/catala_surface/lexer.ml | 40 +++++++++++++++++ src/catala/catala_surface/lexer_en.ml | 40 +++++++++++++++++ src/catala/catala_surface/lexer_fr.ml | 40 +++++++++++++++++ src/catala/catala_surface/name_resolution.ml | 3 +- src/catala/catala_surface/parser.mly | 19 +++++++- src/catala/default_calculus/ast.ml | 23 ++++++++-- src/catala/default_calculus/dune | 2 +- src/catala/default_calculus/interpreter.ml | 47 ++++++++++++++++++-- src/catala/default_calculus/print.ml | 27 ++++++++--- src/catala/default_calculus/typing.ml | 35 +++++++++++---- src/catala/scope_language/print.ml | 6 +-- tests/test_date/simple.catala | 13 ++++++ 16 files changed, 304 insertions(+), 34 deletions(-) create mode 100644 tests/test_date/simple.catala diff --git a/Makefile b/Makefile index 9e784a0a..1065c56d 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,8 @@ install-dependencies-ocaml: unionfind \ bindlib \ zarith \ - ocamlgraph + ocamlgraph \ + odate init-submodules: git submodule update --init diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 13344a56..17e09c36 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -20,7 +20,15 @@ type ident = string type qident = ident Pos.marked list -type primitive_typ = Integer | Decimal | Boolean | Money | Text | Date | Named of constructor +type primitive_typ = + | Integer + | Decimal + | Boolean + | Money + | Duration + | Text + | Date + | Named of constructor type base_typ_data = | Primitive of primitive_typ @@ -55,7 +63,7 @@ type enum_decl = { type match_case_pattern = constructor Pos.marked list * ident Pos.marked option -type op_kind = KInt | KDec | KMoney +type op_kind = KInt | KDec | KMoney | KDate | KDuration type binop = | And diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 24f99569..9a587ea3 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -20,7 +20,12 @@ module Cli = Utils.Cli a redefinition of a subvariable *) let translate_op_kind (k : Ast.op_kind) : Dcalc.Ast.op_kind = - match k with KInt -> KInt | KDec -> KRat | KMoney -> KMoney + match k with + | KInt -> KInt + | KDec -> KRat + | KMoney -> KMoney + | KDate -> KDate + | KDuration -> KDuration let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = match op with @@ -88,7 +93,24 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | MoneyAmount i -> Scopelang.Ast.ELit (Dcalc.Ast.LMoney Z.((i.money_amount_units * of_int 100) + i.money_amount_cents)) - | _ -> Name_resolution.raise_unsupported_feature "literal" pos + | Number ((Int _, _), Some ((Year | Month | Day), _)) + | Number ((Dec (_, _), _), Some ((Year | Month | Day), _)) -> + Name_resolution.raise_unsupported_feature "literal" pos + | Date date -> ( + let date = + ODate.Unix.make + ~year:(Pos.unmark date.literal_date_year) + ~day:(Pos.unmark date.literal_date_day) + ~month: + ( try ODate.Month.of_int (Pos.unmark date.literal_date_month) + with Failure _ -> + Errors.raise_spanned_error "Invalid month (should be between 1 and 12)" + (Pos.get_position date.literal_date_month) ) + () + in + match ODate.Unix.some_if_valid date with + | Some date -> Scopelang.Ast.ELit (Dcalc.Ast.LDate date) + | None -> Errors.raise_spanned_error "Invalid date" pos ) in Bindlib.box (untyped_term, pos) | Ident x -> ( diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index 08ae8ac0..ac5827ac 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -1,6 +1,6 @@ (library (name surface) - (libraries utils menhirLib sedlex re desugared scopelang zarith) + (libraries utils menhirLib sedlex re desugared scopelang zarith odate) (public_name catala.surface) (preprocess (pps sedlex.ppx))) diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index d2924021..fb90b30b 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -69,6 +69,7 @@ let token_list : (string * token) list = ("text", TEXT); ("decimal", DECIMAL); ("date", DATE); + ("duration", DURATION); ("boolean", BOOLEAN); ("sum", SUM); ("ok", FILLED); @@ -167,6 +168,9 @@ let rec lex_code (lexbuf : lexbuf) : token = | "date" -> update_acc lexbuf; DATE + | "duration" -> + update_acc lexbuf; + DURATION | "bool" -> update_acc lexbuf; BOOLEAN @@ -301,6 +305,42 @@ let rec lex_code (lexbuf : lexbuf) : token = | "->" -> update_acc lexbuf; ARROW + | "<=@" -> + update_acc lexbuf; + LESSER_EQUAL_DATE + | "<@" -> + update_acc lexbuf; + LESSER_DATE + | ">=@" -> + update_acc lexbuf; + GREATER_EQUAL_DATE + | ">@" -> + update_acc lexbuf; + GREATER_DATE + | "-@" -> + update_acc lexbuf; + MINUSDATE + | "+@" -> + update_acc lexbuf; + PLUSDATE + | "<=^" -> + update_acc lexbuf; + LESSER_EQUAL_DURATION + | "<^" -> + update_acc lexbuf; + LESSER_DURATION + | ">=^" -> + update_acc lexbuf; + GREATER_EQUAL_DURATION + | ">^" -> + update_acc lexbuf; + GREATER_DURATION + | "+^" -> + update_acc lexbuf; + PLUSDURATION + | "-^" -> + update_acc lexbuf; + MINUSDURATION | "<=", 0x24 -> update_acc lexbuf; LESSER_EQUAL_MONEY diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 37d29876..bbd03c79 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -37,6 +37,7 @@ let token_list_en : (string * token) list = ("text", TEXT); ("decimal", DECIMAL); ("date", DATE); + ("duration", DURATION); ("boolean", BOOLEAN); ("sum", SUM); ("fulfilled", FILLED); @@ -135,6 +136,9 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "date" -> L.update_acc lexbuf; DATE + | "duration" -> + L.update_acc lexbuf; + DURATION | "boolean" -> L.update_acc lexbuf; BOOLEAN @@ -269,6 +273,42 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "->" -> L.update_acc lexbuf; ARROW + | "<=@" -> + L.update_acc lexbuf; + LESSER_EQUAL_DATE + | "<@" -> + L.update_acc lexbuf; + LESSER_DATE + | ">=@" -> + L.update_acc lexbuf; + GREATER_EQUAL_DATE + | ">@" -> + L.update_acc lexbuf; + GREATER_DATE + | "-@" -> + L.update_acc lexbuf; + MINUSDATE + | "+@" -> + L.update_acc lexbuf; + PLUSDATE + | "<=^" -> + L.update_acc lexbuf; + LESSER_EQUAL_DURATION + | "<^" -> + L.update_acc lexbuf; + LESSER_DURATION + | ">=^" -> + L.update_acc lexbuf; + GREATER_EQUAL_DURATION + | ">^" -> + L.update_acc lexbuf; + GREATER_DURATION + | "+^" -> + L.update_acc lexbuf; + PLUSDURATION + | "-^" -> + L.update_acc lexbuf; + MINUSDURATION | "<=", 0x24 -> L.update_acc lexbuf; LESSER_EQUAL_MONEY diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index a41b5ea5..5bd2ab84 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -37,6 +37,7 @@ let token_list_fr : (string * token) list = ("texte", TEXT); ("decimal", DECIMAL); ("date", DATE); + ("durée", DURATION); ("booléen", BOOLEAN); ("somme", SUM); ("rempli", FILLED); @@ -136,6 +137,9 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "date" -> L.update_acc lexbuf; DATE + | "dur", 0xE9, "e" -> + L.update_acc lexbuf; + DURATION | "bool", 0xE9, "en" -> L.update_acc lexbuf; BOOLEAN @@ -278,6 +282,42 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "->" -> L.update_acc lexbuf; ARROW + | "<=@" -> + L.update_acc lexbuf; + LESSER_EQUAL_DATE + | "<@" -> + L.update_acc lexbuf; + LESSER_DATE + | ">=@" -> + L.update_acc lexbuf; + GREATER_EQUAL_DATE + | ">@" -> + L.update_acc lexbuf; + GREATER_DATE + | "-@" -> + L.update_acc lexbuf; + MINUSDATE + | "+@" -> + L.update_acc lexbuf; + PLUSDATE + | "<=^" -> + L.update_acc lexbuf; + LESSER_EQUAL_DURATION + | "<^" -> + L.update_acc lexbuf; + LESSER_DURATION + | ">=^" -> + L.update_acc lexbuf; + GREATER_EQUAL_DURATION + | ">^" -> + L.update_acc lexbuf; + GREATER_DURATION + | "+^" -> + L.update_acc lexbuf; + PLUSDURATION + | "-^" -> + L.update_acc lexbuf; + MINUSDURATION | "<=", 0x20AC -> L.update_acc lexbuf; LESSER_EQUAL_MONEY diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 319d2c48..9bd78d63 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -104,7 +104,8 @@ let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) | Ast.Integer -> (Scopelang.Ast.TLit TInt, typ_pos) | Ast.Decimal -> (Scopelang.Ast.TLit TRat, typ_pos) | Ast.Money -> (Scopelang.Ast.TLit TMoney, typ_pos) - | Ast.Date -> raise_unsupported_feature "date type" typ_pos + | Ast.Duration -> (Scopelang.Ast.TLit TDuration, typ_pos) + | Ast.Date -> (Scopelang.Ast.TLit TDate, typ_pos) | Ast.Boolean -> (Scopelang.Ast.TLit TBool, typ_pos) | Ast.Text -> raise_unsupported_feature "text type" typ_pos | Ast.Named ident -> ( diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 605b0449..f9abd4c9 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -45,15 +45,18 @@ %token LESSER GREATER LESSER_EQUAL GREATER_EQUAL %token LESSER_DEC GREATER_DEC LESSER_EQUAL_DEC GREATER_EQUAL_DEC %token LESSER_MONEY GREATER_MONEY LESSER_EQUAL_MONEY GREATER_EQUAL_MONEY +%token LESSER_DATE GREATER_DATE LESSER_EQUAL_DATE GREATER_EQUAL_DATE +%token LESSER_DURATION GREATER_DURATION LESSER_EQUAL_DURATION GREATER_EQUAL_DURATION %token EXISTS IN SUCH THAT NOW %token DOT AND OR LPAREN RPAREN OPTIONAL EQUAL %token CARDINAL ASSERTION FIXED BY YEAR %token PLUS MINUS MULT DIV %token PLUSDEC MINUSDEC MULTDEC DIVDEC %token PLUSMONEY MINUSMONEY MULTMONEY DIVMONEY +%token MINUSDATE PLUSDATE PLUSDURATION MINUSDURATION %token MATCH WITH VARIES WITH_V %token FOR ALL WE_HAVE INCREASING DECREASING -%token NOT BOOLEAN PERCENT ARROW +%token NOT BOOLEAN PERCENT ARROW DURATION %token SCOPE FILLED NOT_EQUAL DEFINITION %token STRUCT CONTENT IF THEN DEPENDS DECLARATION %token CONTEXT ENUM ELSE DATE SUM @@ -70,6 +73,7 @@ typ_base: | INTEGER { (Integer, $sloc) } | BOOLEAN { (Boolean, $sloc) } | MONEY { (Money, $sloc) } +| DURATION { (Duration, $sloc) } | TEXT { (Text, $sloc) } | DECIMAL { (Decimal, $sloc) } | DATE { (Date, $sloc) } @@ -194,6 +198,14 @@ compare_op: | LESSER_EQUAL_MONEY { (Lte KMoney, $sloc) } | GREATER_MONEY { (Gt KMoney, $sloc) } | GREATER_EQUAL_MONEY { (Gte KMoney, $sloc) } +| LESSER_DATE { (Lt KDate, $sloc) } +| LESSER_EQUAL_DATE { (Lte KDate, $sloc) } +| GREATER_DATE { (Gt KDate, $sloc) } +| GREATER_EQUAL_DATE { (Gte KDate, $sloc) } +| LESSER_DURATION { (Lt KDuration, $sloc) } +| LESSER_EQUAL_DURATION { (Lte KDuration, $sloc) } +| GREATER_DURATION { (Gt KDuration, $sloc) } +| GREATER_EQUAL_DURATION { (Gte KDuration, $sloc) } | EQUAL { (Eq, $sloc) } | NOT_EQUAL { (Neq, $sloc) } @@ -235,6 +247,10 @@ mult_expression: } sum_op: +| PLUSDURATION { (Add KDuration, $sloc) } +| MINUSDURATION { (Sub KDuration, $sloc) } +| PLUSDATE { (Add KDate, $sloc) } +| MINUSDATE { (Sub KDate, $sloc) } | PLUSMONEY { (Add KMoney, $sloc) } | MINUSMONEY { (Sub KMoney, $sloc) } | PLUSDEC { (Add KDec, $sloc) } @@ -246,6 +262,7 @@ sum_unop: | MINUS { (Minus KInt, $sloc) } | MINUSDEC { (Minus KDec, $sloc) } | MINUSMONEY { (Minus KMoney, $sloc) } +| MINUSDURATION { (Minus KDuration, $sloc) } sum_expression: | e = mult_expression { e } diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 6e151810..293903a2 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -15,7 +15,7 @@ module Pos = Utils.Pos module Uid = Utils.Uid -type typ_lit = TBool | TUnit | TInt | TRat | TMoney +type typ_lit = TBool | TUnit | TInt | TRat | TMoney | TDate | TDuration type typ = | TLit of typ_lit @@ -23,9 +23,26 @@ type typ = | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked -type lit = LBool of bool | LEmptyError | LInt of Z.t | LRat of Q.t | LMoney of Z.t | LUnit +type date = ODate.Unix.t -type op_kind = KInt | KRat | KMoney +type duration = ODate.Unix.d + +type lit = + | LBool of bool + | LEmptyError + | LInt of Z.t + | LRat of Q.t + | LMoney of Z.t + | LUnit + | LDate of date + | LDuration of duration + +type op_kind = + | KInt + | KRat + | KMoney + | KDate + | KDuration (** All ops don't have a Kdate and KDuration *) type binop = | And diff --git a/src/catala/default_calculus/dune b/src/catala/default_calculus/dune index 2ec7c591..ff9f00da 100644 --- a/src/catala/default_calculus/dune +++ b/src/catala/default_calculus/dune @@ -1,7 +1,7 @@ (library (name dcalc) (public_name catala.dcalc) - (libraries bindlib unionFind utils zarith)) + (libraries bindlib unionFind utils zarith odate)) (documentation (package catala)) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index d3eabab1..48be0686 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -68,6 +68,14 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The division operator:", Pos.get_position op); (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] + | A.Binop (A.Add KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + A.ELit (LDuration (ODuration.( + ) i1 i2)) + | A.Binop (A.Sub KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + A.ELit (LDuration (ODuration.( - ) i1 i2)) + | A.Binop (A.Sub KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LDuration (ODate.Unix.between i1 i2)) + | A.Binop (A.Add KDate), [ ELit (LDate i1); ELit (LDuration i2) ] -> + A.ELit (LDate (ODate.Unix.move i1 i2)) | A.Binop (A.Lt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) | A.Binop (A.Lte KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) | A.Binop (A.Gt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) @@ -76,10 +84,41 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop (A.Lte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <= i2)) | A.Binop (A.Gt KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) | A.Binop (A.Gte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) + | A.Binop (A.Lt KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (ODuration.is_positive diff)) + | A.Binop (A.Lte KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (ODuration.is_positive diff || ODuration.is_instantenous diff)) + | A.Binop (A.Gt KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (ODuration.is_negative diff)) + | A.Binop (A.Gte KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (ODuration.is_negative diff || ODuration.is_instantenous diff)) + | A.Binop (A.Lt KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 < 0)) + | A.Binop (A.Lte KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 <= 0)) + | A.Binop (A.Gt KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 > 0)) + | A.Binop (A.Gte KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 >= 0)) + | A.Binop A.Eq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (ODuration.is_instantenous diff)) + | A.Binop A.Eq, [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 = 0)) | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) + | A.Binop A.Neq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> + let diff = ODuration.( - ) i2 i1 in + A.ELit (LBool (not (ODuration.is_instantenous diff))) + | A.Binop A.Neq, [ ELit (LDate i1); ELit (LDate i2) ] -> + A.ELit (LBool (ODate.Unix.compare i1 i2 <> 0)) + | A.Binop A.Neq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <> i2)) | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) @@ -97,9 +136,11 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Unop _, [ ELit LEmptyError ] -> A.ELit LEmptyError | _ -> Errors.raise_multispanned_error - "operator applied to the wrong arguments (should not happen if the term was well-typed)" - [ (Some "Operator:", Pos.get_position op) ] - @@ List.mapi (fun i arg -> Some ("Argument n°" ^ string_of_int i, Pos.get_position arg)) ) + "Operator applied to the wrong arguments\n(should nothappen if the term was well-typed)" + ( [ (Some "Operator:", Pos.get_position op) ] + @ List.mapi + (fun i arg -> (Some ("Argument n°" ^ string_of_int (i + 1)), Pos.get_position arg)) + args ) ) op let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 30b7c20f..a9448eeb 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -18,17 +18,23 @@ open Ast let typ_needs_parens (e : typ Pos.marked) : bool = match Pos.unmark e with TArrow _ -> true | _ -> false +let format_tlit (fmt : Format.formatter) (l : typ_lit) : unit = + match l with + | TUnit -> Format.fprintf fmt "unit" + | TBool -> Format.fprintf fmt "boolean" + | TInt -> Format.fprintf fmt "integer" + | TRat -> Format.fprintf fmt "decimal" + | TMoney -> Format.fprintf fmt "money" + | TDuration -> Format.fprintf fmt "duration" + | TDate -> Format.fprintf fmt "date" + let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = let format_typ_with_parens (fmt : Format.formatter) (t : typ Pos.marked) = if typ_needs_parens t then Format.fprintf fmt "(%a)" format_typ t else Format.fprintf fmt "%a" format_typ t in match Pos.unmark typ with - | TLit TUnit -> Format.fprintf fmt "unit" - | TLit TBool -> Format.fprintf fmt "boolean" - | TLit TInt -> Format.fprintf fmt "integer" - | TLit TRat -> Format.fprintf fmt "decimal" - | TLit TMoney -> Format.fprintf fmt "money" + | TLit l -> Format.fprintf fmt "%a" format_tlit l | TTuple ts -> Format.fprintf fmt "(%a)" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) @@ -82,9 +88,18 @@ let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = ( if List.length !digits - leading_zeroes !digits = !Utils.Cli.max_prec_digits then "…" else "" ) | LMoney e -> Format.fprintf fmt "$%.2f" Q.(to_float (of_bigint e / of_int 100)) + | LDate d -> + Format.fprintf fmt "%s" + (ODate.Unix.To.string (Option.get (ODate.Unix.To.generate_printer "%Y-%m-%d")) d) + | LDuration d -> + Format.fprintf fmt "%s" + (ODuration.To.string + (Option.get (ODuration.To.generate_printer "[%Y] years or [%M] months of [%D] days")) + d) let format_op_kind (fmt : Format.formatter) (k : op_kind) = - Format.fprintf fmt "%s" (match k with KInt -> "" | KRat -> "." | KMoney -> "$") + Format.fprintf fmt "%s" + (match k with KInt -> "" | KRat -> "." | KMoney -> "$" | KDate -> "@" | KDuration -> "^") let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = match Pos.unmark op with diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index a51ecdfc..a83ff31e 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -30,11 +30,7 @@ type typ = let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = let ty_repr = UnionFind.get (UnionFind.find ty) in match Pos.unmark ty_repr with - | TLit TUnit -> Format.fprintf fmt "unit" - | TLit TBool -> Format.fprintf fmt "bool" - | TLit TInt -> Format.fprintf fmt "int" - | TLit TRat -> Format.fprintf fmt "dec" - | TLit TMoney -> Format.fprintf fmt "money" + | TLit l -> Format.fprintf fmt "%a" Print.format_tlit l | TAny -> Format.fprintf fmt "any type" | TTuple ts -> Format.fprintf fmt "(%a)" @@ -52,9 +48,17 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with | (TLit tl1, _), (TLit tl2, _) when tl1 = tl2 -> () - | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> - unify t11 t21; - unify t12 t22 + | (TArrow (t11, t12), t1_pos), (TArrow (t21, t22), t2_pos) -> ( + try + unify t11 t21; + unify t12 t22 + with Errors.StructuredError (msg, err_pos) -> + Errors.raise_multispanned_error msg + ( err_pos + @ [ + (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); + (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); + ] ) ) | (TTuple ts1, _), (TTuple ts2, _) -> List.iter2 unify ts1 ts2 | (TEnum ts1, _), (TEnum ts2, _) -> List.iter2 unify ts1 ts2 | (TAny, _), (TAny, _) -> ignore (UnionFind.union t1 t2) @@ -78,6 +82,8 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = let it = UnionFind.make (TLit TInt, pos) in let rt = UnionFind.make (TLit TRat, pos) in let mt = UnionFind.make (TLit TMoney, pos) in + let dut = UnionFind.make (TLit TDuration, pos) in + let dat = UnionFind.make (TLit TDate, pos) in let any = UnionFind.make (TAny, pos) in let arr x y = UnionFind.make (TArrow (x, y), pos) in match Pos.unmark op with @@ -85,17 +91,26 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Binop (A.Add KInt | A.Sub KInt | A.Mult KInt | A.Div KInt) -> arr it (arr it it) | A.Binop (A.Add KRat | A.Sub KRat | A.Mult KRat | A.Div KRat) -> arr rt (arr rt rt) | A.Binop (A.Add KMoney | A.Sub KMoney) -> arr mt (arr mt mt) + | A.Binop (A.Add KDuration | A.Sub KDuration) -> arr dut (arr dut dut) + | A.Binop (A.Sub KDate) -> arr dat (arr dat dut) + | A.Binop (A.Add KDate) -> arr dat (arr dut dat) | A.Binop (A.Div KMoney) -> arr mt (arr mt rt) | A.Binop (A.Mult KMoney) -> arr mt (arr rt mt) | A.Binop (A.Lt KInt | A.Lte KInt | A.Gt KInt | A.Gte KInt) -> arr it (arr it bt) | A.Binop (A.Lt KRat | A.Lte KRat | A.Gt KRat | A.Gte KRat) -> arr rt (arr rt bt) | A.Binop (A.Lt KMoney | A.Lte KMoney | A.Gt KMoney | A.Gte KMoney) -> arr mt (arr mt bt) + | A.Binop (A.Lt KDate | A.Lte KDate | A.Gt KDate | A.Gte KDate) -> arr dat (arr dat bt) + | A.Binop (A.Lt KDuration | A.Lte KDuration | A.Gt KDuration | A.Gte KDuration) -> + arr dut (arr dut bt) | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) | A.Unop (A.Minus KInt) -> arr it it | A.Unop (A.Minus KRat) -> arr rt rt | A.Unop (A.Minus KMoney) -> arr mt mt + | A.Unop (A.Minus KDuration) -> arr dut dut | A.Unop A.Not -> arr bt bt | A.Unop A.ErrorOnEmpty -> arr any any + | Binop (Mult (KDate | KDuration)) | Binop (Div (KDate | KDuration)) | Unop (Minus KDate) -> + Errors.raise_spanned_error "This operator is not available!" pos let rec ast_to_typ (ty : A.typ) : typ = match ty with @@ -133,6 +148,8 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as (TLit TInt) e) | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as (TLit TRat) e) | ELit (LMoney _) -> UnionFind.make (Pos.same_pos_as (TLit TMoney) e) + | ELit (LDate _) -> UnionFind.make (Pos.same_pos_as (TLit TDate) e) + | ELit (LDuration _) -> UnionFind.make (Pos.same_pos_as (TLit TDuration) e) | ELit LUnit -> UnionFind.make (Pos.same_pos_as (TLit TUnit) e) | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) | ETuple es -> @@ -236,6 +253,8 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | ELit (LInt _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TInt) e)) | ELit (LRat _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TRat) e)) | ELit (LMoney _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TMoney) e)) + | ELit (LDate _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TDate) e)) + | ELit (LDuration _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TDuration) e)) | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e)) | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) | ETuple es -> ( diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 393cfe4b..02a863ec 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -37,11 +37,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = else Format.fprintf fmt "%a" format_typ t in match Pos.unmark typ with - | TLit TUnit -> Format.fprintf fmt "unit" - | TLit TBool -> Format.fprintf fmt "boolean" - | TLit TInt -> Format.fprintf fmt "integer" - | TLit TRat -> Format.fprintf fmt "decimal" - | TLit TMoney -> Format.fprintf fmt "money" + | TLit l -> Dcalc.Print.format_tlit fmt l | TStruct s -> Format.fprintf fmt "%a" Ast.StructName.format_t s | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e | TArrow (t1, t2) -> diff --git a/tests/test_date/simple.catala b/tests/test_date/simple.catala new file mode 100644 index 00000000..24ddec34 --- /dev/null +++ b/tests/test_date/simple.catala @@ -0,0 +1,13 @@ +@Article@ + +/* +new scope A: + param x content date + param y content date + param z content duration + +scope A: + def x := |01/01/2019| + def y := |30/09/2002| + def z := x -@ y +*/ \ No newline at end of file From 5004ee12d237233473ea8a137064a6501009492b Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 11:51:50 +0100 Subject: [PATCH 072/142] Added duration literals but comparison buggy --- src/catala/catala_surface/desugaring.ml | 40 +++++++++++++++++++++++-- src/catala/catala_surface/lexer.ml | 8 +++++ src/catala/catala_surface/lexer_en.ml | 8 +++++ src/catala/catala_surface/lexer_fr.ml | 8 +++++ src/catala/catala_surface/parser.mly | 4 ++- src/catala/default_calculus/print.ml | 8 ++--- tests/test_date/durations.catala | 15 ++++++++++ tests/test_date/durations.catala.A.out | 4 +++ tests/test_date/simple.catala.A.out | 3 ++ 9 files changed, 91 insertions(+), 7 deletions(-) create mode 100644 tests/test_date/durations.catala create mode 100644 tests/test_date/durations.catala.A.out create mode 100644 tests/test_date/simple.catala.A.out diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 9a587ea3..9a17f350 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -93,9 +93,45 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | MoneyAmount i -> Scopelang.Ast.ELit (Dcalc.Ast.LMoney Z.((i.money_amount_units * of_int 100) + i.money_amount_cents)) - | Number ((Int _, _), Some ((Year | Month | Day), _)) + | Number ((Int i, i_pos), Some (Year, _)) -> + Scopelang.Ast.ELit + (Dcalc.Ast.LDuration + (ODuration.make ~forward:true + ~year: + ( try Z.to_int i + with Failure _ -> + Errors.raise_spanned_error + "This duration is too big to fit in Catala's duration computation \ + engine" + i_pos ) + ())) + | Number ((Int i, i_pos), Some (Month, _)) -> + Scopelang.Ast.ELit + (Dcalc.Ast.LDuration + (ODuration.make ~forward:true + ~month: + ( try Z.to_int i + with Failure _ -> + Errors.raise_spanned_error + "This duration is too big to fit in Catala's duration computation \ + engine" + i_pos ) + ())) + | Number ((Int i, i_pos), Some (Day, _)) -> + Scopelang.Ast.ELit + (Dcalc.Ast.LDuration + (ODuration.make ~forward:true + ~day: + ( try Z.to_int i + with Failure _ -> + Errors.raise_spanned_error + "This duration is too big to fit in Catala's duration computation \ + engine" + i_pos ) + ())) | Number ((Dec (_, _), _), Some ((Year | Month | Day), _)) -> - Name_resolution.raise_unsupported_feature "literal" pos + Errors.raise_spanned_error + "Impossible to specify decimal amounts of days, months or years" pos | Date date -> ( let date = ODate.Unix.make diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index fb90b30b..7e6fe031 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -102,6 +102,8 @@ let token_list : (string * token) list = ("not", NOT); ("number", CARDINAL); ("year", YEAR); + ("month", MONTH); + ("day", DAY); ("true", TRUE); ("false", FALSE); ] @@ -283,6 +285,12 @@ let rec lex_code (lexbuf : lexbuf) : token = | "year" -> update_acc lexbuf; YEAR + | "month" -> + update_acc lexbuf; + MONTH + | "day" -> + update_acc lexbuf; + DAY | 0x24, Star white_space, '0' .. '9', Star ('0' .. '9' | ','), Opt ('.', Rep ('0' .. '9', 0 .. 2)) -> let extract_parts = R.regexp "([0-9]([0-9,]*[0-9]|))(.([0-9]{0,2})|)" in diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index bbd03c79..7c57cb5e 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -70,6 +70,8 @@ let token_list_en : (string * token) list = ("not", NOT); ("number", CARDINAL); ("year", YEAR); + ("month", MONTH); + ("day", DAY); ("true", TRUE); ("false", FALSE); ] @@ -251,6 +253,12 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "year" -> L.update_acc lexbuf; YEAR + | "month" -> + L.update_acc lexbuf; + MONTH + | "day" -> + L.update_acc lexbuf; + DAY | 0x24, Star white_space, '0' .. '9', Star ('0' .. '9' | ','), Opt ('.', Rep ('0' .. '9', 0 .. 2)) -> let extract_parts = R.regexp "([0-9]([0-9,]*[0-9]|))(.([0-9]{0,2})|)" in diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 5bd2ab84..0d018440 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -70,6 +70,8 @@ let token_list_fr : (string * token) list = ("non", NOT); ("nombre", CARDINAL); ("an", YEAR); + ("mois", MONTH); + ("jour", DAY); ("vrai", TRUE); ("faux", FALSE); ] @@ -257,6 +259,12 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "an" -> L.update_acc lexbuf; YEAR + | "mois" -> + L.update_acc lexbuf; + MONTH + | "jour" -> + L.update_acc lexbuf; + DAY | ( '0' .. '9', Star ('0' .. '9' | white_space), Opt (',', Rep ('0' .. '9', 0 .. 2)), diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index f9abd4c9..b4b96838 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -49,7 +49,7 @@ %token LESSER_DURATION GREATER_DURATION LESSER_EQUAL_DURATION GREATER_EQUAL_DURATION %token EXISTS IN SUCH THAT NOW %token DOT AND OR LPAREN RPAREN OPTIONAL EQUAL -%token CARDINAL ASSERTION FIXED BY YEAR +%token CARDINAL ASSERTION FIXED BY YEAR MONTH DAY %token PLUS MINUS MULT DIV %token PLUSDEC MINUSDEC MULTDEC DIVDEC %token PLUSMONEY MINUSMONEY MULTMONEY DIVMONEY @@ -160,6 +160,8 @@ num_literal: unit_literal: | PERCENT { (Percent, $sloc) } | YEAR { (Year, $sloc)} +| MONTH { (Month, $sloc) } +| DAY { (Day, $sloc) } date_int: | d = INT_LITERAL { (Z.to_int d, $sloc) } diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index a9448eeb..14487340 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -111,10 +111,10 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = | Or -> Format.fprintf fmt "%s" "||" | Eq -> Format.fprintf fmt "%s" "==" | Neq -> Format.fprintf fmt "%s" "!=" - | Lt _ -> Format.fprintf fmt "%s" "<" - | Lte _ -> Format.fprintf fmt "%s" "<=" - | Gt _ -> Format.fprintf fmt "%s" ">" - | Gte _ -> Format.fprintf fmt "%s" ">=" + | Lt k -> Format.fprintf fmt "%s%a" "<" format_op_kind k + | Lte k -> Format.fprintf fmt "%s%a" "<=" format_op_kind k + | Gt k -> Format.fprintf fmt "%s%a" ">" format_op_kind k + | Gte k -> Format.fprintf fmt "%s%a" ">=" format_op_kind k let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" diff --git a/tests/test_date/durations.catala b/tests/test_date/durations.catala new file mode 100644 index 00000000..8ad0787d --- /dev/null +++ b/tests/test_date/durations.catala @@ -0,0 +1,15 @@ +@Article@ + +/* +new scope A: + param x content date + param y content date + param z content bool + param z2 content bool + +scope A: + def x := |01/01/2019| + def y := |30/09/2002| + def z := x -@ y >=^ 16 year + def z2 := x -@ y <^ 20 year +*/ \ No newline at end of file diff --git a/tests/test_date/durations.catala.A.out b/tests/test_date/durations.catala.A.out new file mode 100644 index 00000000..0d683c24 --- /dev/null +++ b/tests/test_date/durations.catala.A.out @@ -0,0 +1,4 @@ +[RESULT] x -> 2019-01-01 +[RESULT] y -> 2002-09-30 +[RESULT] z -> true +[RESULT] z2 -> false diff --git a/tests/test_date/simple.catala.A.out b/tests/test_date/simple.catala.A.out new file mode 100644 index 00000000..865056ea --- /dev/null +++ b/tests/test_date/simple.catala.A.out @@ -0,0 +1,3 @@ +[RESULT] x -> 2019-01-01 +[RESULT] y -> 2002-09-30 +[RESULT] z -> 16 years or 195 months of 5937 days From 540057fe27ddcc4934ae453b09935665593d9253 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 11:53:55 +0100 Subject: [PATCH 073/142] Updated parser error and some test --- src/catala/catala_surface/parser.messages | 472 ++++++++++----------- src/catala/catala_surface/parser_errors.ml | 232 +++++----- tests/test_money/no_mingle.catala.A.out | 28 +- 3 files changed, 378 insertions(+), 354 deletions(-) diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index a3fa6504..f29f5b1d 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 297. +## Ends in an error in state: 313. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -36,7 +36,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 291. +## Ends in an error in state: 307. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -49,7 +49,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 302. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -61,7 +61,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 301. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -73,7 +73,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 284. +## Ends in an error in state: 300. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -85,7 +85,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 283. +## Ends in an error in state: 299. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -97,7 +97,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 298. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -109,7 +109,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 281. +## Ends in an error in state: 297. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -121,7 +121,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 276. +## Ends in an error in state: 292. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -133,7 +133,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 274. +## Ends in an error in state: 290. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -145,7 +145,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 289. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -157,7 +157,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 278. +## Ends in an error in state: 294. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -170,7 +170,7 @@ expected the next context item, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 271. +## Ends in an error in state: 287. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -182,7 +182,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 270. +## Ends in an error in state: 286. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -196,7 +196,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 269. +## Ends in an error in state: 285. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -210,7 +210,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 268. +## Ends in an error in state: 284. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -222,7 +222,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 267. +## Ends in an error in state: 283. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -234,7 +234,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 266. +## Ends in an error in state: 282. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -246,7 +246,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 269. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -258,7 +258,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 266. ## ## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -270,7 +270,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 261. +## Ends in an error in state: 277. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 257. +## Ends in an error in state: 273. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -294,7 +294,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 256. +## Ends in an error in state: 272. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -306,7 +306,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 263. +## Ends in an error in state: 279. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -318,7 +318,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 239. +## Ends in an error in state: 254. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -330,7 +330,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 238. +## Ends in an error in state: 253. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -342,7 +342,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 237. +## Ends in an error in state: 252. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +354,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 236. +## Ends in an error in state: 251. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -366,7 +366,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 235. +## Ends in an error in state: 250. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -378,7 +378,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 234. +## Ends in an error in state: 249. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -390,7 +390,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 233. +## Ends in an error in state: 248. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -404,7 +404,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 230. +## Ends in an error in state: 245. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -416,23 +416,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 51, spurious reduction of production primitive_expression -> CARDINAL -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression -## In state 227, spurious reduction of production assertion_base -> expression -## In state 228, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 229, spurious reduction of production scope_item -> ASSERTION assertion +## In state 52, spurious reduction of production primitive_expression -> CARDINAL +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression +## In state 242, spurious reduction of production assertion_base -> expression +## In state 243, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 244, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 224. +## Ends in an error in state: 239. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -444,7 +444,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 223. +## Ends in an error in state: 238. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -455,15 +455,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 222. +## Ends in an error in state: 237. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -475,7 +475,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 226. +## Ends in an error in state: 241. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -487,9 +487,9 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 195. +## Ends in an error in state: 210. ## -## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## condition @@ -498,21 +498,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 51, spurious reduction of production primitive_expression -> CARDINAL -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression -## In state 188, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 52, spurious reduction of production primitive_expression -> CARDINAL +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression +## In state 203, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 187. +## Ends in an error in state: 202. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -524,7 +524,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 215. +## Ends in an error in state: 230. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -535,15 +535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 217. +## Ends in an error in state: 232. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -554,15 +554,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 216. +## Ends in an error in state: 231. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -574,7 +574,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 214. +## Ends in an error in state: 229. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -586,7 +586,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 213. +## Ends in an error in state: 228. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -598,7 +598,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 210. +## Ends in an error in state: 225. ## ## definition -> qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -610,7 +610,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 208. +## Ends in an error in state: 223. ## ## definition -> qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -622,7 +622,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 209. +## Ends in an error in state: 224. ## ## definition -> qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -634,7 +634,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 207. +## Ends in an error in state: 222. ## ## definition -> qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -645,15 +645,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 206. +## Ends in an error in state: 221. ## ## scope_item -> DEFINITION . definition [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -665,7 +665,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 204. +## Ends in an error in state: 219. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -677,7 +677,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 192. +## Ends in an error in state: 207. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -689,7 +689,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 186. +## Ends in an error in state: 201. ## ## rule -> rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -701,7 +701,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 214. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -713,7 +713,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 189. +## Ends in an error in state: 204. ## ## rule -> rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -725,7 +725,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 198. +## Ends in an error in state: 213. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -736,15 +736,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 203, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 185, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 203. +## Ends in an error in state: 218. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -757,7 +757,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 184. +## Ends in an error in state: 199. ## ## scope_item -> RULE . rule [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -769,7 +769,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 183. +## Ends in an error in state: 198. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -781,10 +781,10 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 51. +## Ends in an error in state: 52. ## ## aggregate_func -> CARDINAL . [ FOR ] -## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CARDINAL @@ -794,11 +794,11 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 135. +## Ends in an error in state: 150. ## -## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT small_expression @@ -808,9 +808,9 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 134. +## Ends in an error in state: 149. ## -## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT @@ -820,9 +820,9 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 71. +## Ends in an error in state: 74. ## -## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## constructor @@ -832,7 +832,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 150. +## Ends in an error in state: 165. ## ## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -844,9 +844,9 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 156. +## Ends in an error in state: 171. ## -## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression SUCH @@ -856,9 +856,9 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 155. +## Ends in an error in state: 170. ## -## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression @@ -867,16 +867,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 154. +## Ends in an error in state: 169. ## -## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN @@ -886,9 +886,9 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 153. +## Ends in an error in state: 168. ## -## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident @@ -898,9 +898,9 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 152. +## Ends in an error in state: 167. ## -## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked @@ -910,7 +910,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 143. +## Ends in an error in state: 158. ## ## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -922,9 +922,9 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 147. +## Ends in an error in state: 162. ## -## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN primitive_expression @@ -933,16 +933,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 146. +## Ends in an error in state: 161. ## -## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN @@ -952,9 +952,9 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 145. +## Ends in an error in state: 160. ## -## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident @@ -964,9 +964,9 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 144. +## Ends in an error in state: 159. ## -## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked @@ -976,7 +976,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 46. +## Ends in an error in state: 47. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -988,7 +988,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 158. +## Ends in an error in state: 173. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -999,20 +999,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 176. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1024,7 +1024,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 160. +## Ends in an error in state: 175. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1035,20 +1035,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 159. +## Ends in an error in state: 174. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1060,7 +1060,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 44. +## Ends in an error in state: 45. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1072,9 +1072,9 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 64. +## Ends in an error in state: 65. ## -## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## num_literal @@ -1084,9 +1084,9 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 163. +## Ends in an error in state: 178. ## -## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN expression @@ -1095,22 +1095,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 42. +## Ends in an error in state: 43. ## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN @@ -1120,7 +1120,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 165. +## Ends in an error in state: 180. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1131,14 +1131,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 168. +## Ends in an error in state: 183. ## ## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1149,20 +1149,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 125, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 172, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 140, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 187, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 171. +## Ends in an error in state: 186. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1174,7 +1174,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 176. +## Ends in an error in state: 191. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1186,7 +1186,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 170. +## Ends in an error in state: 185. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1198,7 +1198,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 174. +## Ends in an error in state: 189. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1211,7 +1211,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 173. +## Ends in an error in state: 188. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1223,7 +1223,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 167. +## Ends in an error in state: 182. ## ## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1235,7 +1235,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 166. +## Ends in an error in state: 181. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1247,7 +1247,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 41. +## Ends in an error in state: 42. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1259,9 +1259,9 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 52. +## Ends in an error in state: 53. ## -## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_unop @@ -1271,7 +1271,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 124. +## Ends in an error in state: 139. ## ## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1283,9 +1283,9 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 120. +## Ends in an error in state: 135. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression OF @@ -1295,9 +1295,9 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 119. +## Ends in an error in state: 134. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression @@ -1306,16 +1306,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 117. +## Ends in an error in state: 132. ## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN @@ -1325,9 +1325,9 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 116. +## Ends in an error in state: 131. ## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident @@ -1337,9 +1337,9 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 115. +## Ends in an error in state: 130. ## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR @@ -1349,9 +1349,9 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 114. +## Ends in an error in state: 129. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func @@ -1361,9 +1361,9 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 58. +## Ends in an error in state: 59. ## -## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression ARROW @@ -1373,7 +1373,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 182. +## Ends in an error in state: 197. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1384,24 +1384,24 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression -## In state 104, spurious reduction of production mult_expression -> base_expression -## In state 95, spurious reduction of production sum_expression -> mult_expression -## In state 79, spurious reduction of production compare_expression -> sum_expression -## In state 127, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production expression -> logical_expression -## In state 180, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 181, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 119, spurious reduction of production mult_expression -> base_expression +## In state 106, spurious reduction of production sum_expression -> mult_expression +## In state 82, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> compare_expression +## In state 157, spurious reduction of production expression -> logical_expression +## In state 195, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 196, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 56. +## Ends in an error in state: 57. ## -## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression DOT @@ -1411,9 +1411,9 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 140. +## Ends in an error in state: 155. ## -## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression IN @@ -1423,10 +1423,10 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 104. +## Ends in an error in state: 119. ## -## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression @@ -1435,17 +1435,17 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression -## In state 60, spurious reduction of production base_expression -> primitive_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 61, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 111. +## Ends in an error in state: 126. ## -## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression mult_op @@ -1455,7 +1455,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 94. +## Ends in an error in state: 105. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1467,9 +1467,9 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 63. +## Ends in an error in state: 64. ## -## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression OF @@ -1479,7 +1479,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 130. +## Ends in an error in state: 145. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1491,9 +1491,9 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 102. +## Ends in an error in state: 117. ## -## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## mult_expression sum_op @@ -1503,12 +1503,12 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 60. +## Ends in an error in state: 61. ## -## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression @@ -1517,16 +1517,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 55, spurious reduction of production primitive_expression -> small_expression +## In state 56, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 61. +## Ends in an error in state: 62. ## -## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression WITH @@ -1536,11 +1536,11 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 55. +## Ends in an error in state: 56. ## -## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression @@ -1552,7 +1552,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 31. ## -## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV date_int @@ -1564,7 +1564,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 30. ## -## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV @@ -1576,7 +1576,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 29. ## -## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int @@ -1588,7 +1588,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 28. ## -## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV @@ -1600,7 +1600,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 27. ## -## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int @@ -1612,7 +1612,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 25. ## -## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDEC PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDEC MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DEC LESSER_EQUAL LESSER_DEC LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DEC GREATER_EQUAL GREATER_DEC GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL @@ -1658,7 +1658,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 308. +## Ends in an error in state: 324. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1670,7 +1670,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 313. +## Ends in an error in state: 329. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1682,7 +1682,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 306. +## Ends in an error in state: 322. ## ## source_file_article -> law_article . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1694,7 +1694,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 301. +## Ends in an error in state: 317. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index c630f3af..89197bb1 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -11,10 +11,10 @@ let message s = | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 301 -> "expected some text, another heading or a law article\n" - | 306 -> "expected a code block, a metadata block, more law text or a heading\n" - | 313 -> "expected a code block, a metadata block, more law text or a heading\n" - | 308 -> "expected a declaration or a scope use\n" + | 317 -> "expected some text, another heading or a law article\n" + | 322 -> "expected a code block, a metadata block, more law text or a heading\n" + | 329 -> "expected a code block, a metadata block, more law text or a heading\n" + | 324 -> "expected a declaration or a scope use\n" | 21 -> "expected the name of the scope you want to use\n" | 23 -> "expected a scope use precondition or a colon\n" | 24 -> "expected an expression which will act as the condition\n" @@ -24,133 +24,133 @@ let message s = | 29 -> "expected a \"/\"\n" | 30 -> "expected the third component of the date literal\n" | 31 -> "expected a delimiter to finish the date literal\n" - | 55 -> "expected an operator to compose the expression on the left with\n" - | 61 -> "expected an enum constructor to test if the expression on the left\n" - | 60 -> "expected an operator to compose the expression on the left with\n" - | 102 -> "expected an expression on the right side of the sum or minus operator\n" - | 130 -> "expected an expression on the right side of the logical operator\n" - | 63 -> "expected an expression for the argument of this function call\n" - | 94 -> "expected an expression on the right side of the comparison operator\n" - | 111 -> "expected an expression on the right side of the multiplication or division operator\n" - | 104 -> "expected an operator to compose the expression on the left\n" - | 140 -> "expected an expression standing for the set you want to test for membership\n" - | 56 -> "expected an identifier standing for a struct field or a subscope name\n" - | 182 -> "expected a colon after the scope use precondition\n" - | 58 -> "expected a constructor, to get the payload of this enum case\n" - | 114 -> "expected the \"for\" keyword to spell the aggregation\n" - | 115 -> "expected an identifier for the aggregation bound variable\n" - | 116 -> "expected the \"in\" keyword\n" - | 117 -> + | 56 -> "expected an operator to compose the expression on the left with\n" + | 62 -> "expected an enum constructor to test if the expression on the left\n" + | 61 -> "expected an operator to compose the expression on the left with\n" + | 117 -> "expected an expression on the right side of the sum or minus operator\n" + | 145 -> "expected an expression on the right side of the logical operator\n" + | 64 -> "expected an expression for the argument of this function call\n" + | 105 -> "expected an expression on the right side of the comparison operator\n" + | 126 -> "expected an expression on the right side of the multiplication or division operator\n" + | 119 -> "expected an operator to compose the expression on the left\n" + | 155 -> "expected an expression standing for the set you want to test for membership\n" + | 57 -> "expected an identifier standing for a struct field or a subscope name\n" + | 197 -> "expected a colon after the scope use precondition\n" + | 59 -> "expected a constructor, to get the payload of this enum case\n" + | 129 -> "expected the \"for\" keyword to spell the aggregation\n" + | 130 -> "expected an identifier for the aggregation bound variable\n" + | 131 -> "expected the \"in\" keyword\n" + | 132 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 119 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 120 -> "expected an expression to compute its aggregation over the set\n" - | 124 -> "expected an expression to take the negation of\n" - | 52 -> "expected an expression to take the opposite of\n" - | 41 -> "expected an expression to match with\n" - | 166 -> "expected a pattern matching case\n" - | 167 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 173 -> + | 134 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 135 -> "expected an expression to compute its aggregation over the set\n" + | 139 -> "expected an expression to take the negation of\n" + | 53 -> "expected an expression to take the opposite of\n" + | 42 -> "expected an expression to match with\n" + | 181 -> "expected a pattern matching case\n" + | 182 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 188 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 174 -> "expected an identifier for this enum case binding\n" - | 170 -> "expected a colon and then the expression for this matching case\n" - | 176 -> "expected a colon or a binding for the enum constructor payload\n" - | 171 -> "expected an expression for this pattern matching case\n" - | 168 -> + | 189 -> "expected an identifier for this enum case binding\n" + | 185 -> "expected a colon and then the expression for this matching case\n" + | 191 -> "expected a colon or a binding for the enum constructor payload\n" + | 186 -> "expected an expression for this pattern matching case\n" + | 183 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 165 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 42 -> "expected an expression inside the parenthesis\n" - | 163 -> "unmatched parenthesis that should have been closed by here\n" - | 64 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 44 -> "expected an expression for the test of the conditional\n" - | 159 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 160 -> + | 180 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 43 -> "expected an expression inside the parenthesis\n" + | 178 -> "unmatched parenthesis that should have been closed by here\n" + | 65 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 45 -> "expected an expression for the test of the conditional\n" + | 174 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 175 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 161 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 158 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 46 -> + | 176 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 173 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 47 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 144 -> "expected an identifier for the bound variable of the universal test\n" - | 145 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 146 -> "expected the expression designating the set on which to perform the universal test\n" - | 147 -> "expected the \"we have\" keyword for this universal test\n" - | 143 -> "expected an expression for the universal test\n" - | 152 -> "expected an identifier that will designate the existential witness for the test\n" - | 153 -> "expected the \"in\" keyword to continue this existential test\n" - | 154 -> "expected an expression that designates the set subject to the existential test\n" - | 155 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 156 -> "expected a keyword to complete the \"such that\" construction\n" - | 150 -> "expected an expression for the existential test\n" - | 71 -> + | 159 -> "expected an identifier for the bound variable of the universal test\n" + | 160 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 161 -> "expected the expression designating the set on which to perform the universal test\n" + | 162 -> "expected the \"we have\" keyword for this universal test\n" + | 158 -> "expected an expression for the universal test\n" + | 167 -> "expected an identifier that will designate the existential witness for the test\n" + | 168 -> "expected the \"in\" keyword to continue this existential test\n" + | 169 -> "expected an expression that designates the set subject to the existential test\n" + | 170 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 171 -> "expected a keyword to complete the \"such that\" construction\n" + | 165 -> "expected an expression for the existential test\n" + | 74 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 134 -> "expected an expression for the content of this enum case\n" - | 135 -> + | 149 -> "expected an expression for the content of this enum case\n" + | 150 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 51 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 183 -> "expected a scope use item: a rule, definition or assertion\n" - | 184 -> "expected the name of the variable subject to the rule\n" - | 203 -> + | 52 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 198 -> "expected a scope use item: a rule, definition or assertion\n" + | 199 -> "expected the name of the variable subject to the rule\n" + | 218 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 198 -> "expected a condition or a consequence for this rule\n" - | 189 -> "expected filled or not filled for a rule consequence\n" - | 199 -> "expected the name of the parameter for this dependent variable \n" - | 186 -> "expected the expression of the rule\n" - | 192 -> "expected the filled keyword the this rule \n" - | 204 -> "expected a struct field or a sub-scope context item after the dot\n" - | 206 -> "expected the name of the variable you want to define\n" - | 207 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 209 -> "expected an expression for the consequence of this definition under condition\n" - | 208 -> + | 213 -> "expected a condition or a consequence for this rule\n" + | 204 -> "expected filled or not filled for a rule consequence\n" + | 214 -> "expected the name of the parameter for this dependent variable \n" + | 201 -> "expected the expression of the rule\n" + | 207 -> "expected the filled keyword the this rule \n" + | 219 -> "expected a struct field or a sub-scope context item after the dot\n" + | 221 -> "expected the name of the variable you want to define\n" + | 222 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 224 -> "expected an expression for the consequence of this definition under condition\n" + | 223 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 210 -> "expected an expression for the definition\n" - | 213 -> "expected an expression that shoud be asserted during execution\n" - | 214 -> "expecting the name of the varying variable\n" - | 216 -> "the variable varies with an expression that was expected here\n" - | 217 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 215 -> "expected an indication about what this variable varies with\n" - | 187 -> "expected an expression for this condition\n" - | 195 -> "expected a consequence for this definition under condition\n" - | 226 -> "expected an expression for this definition under condition\n" - | 222 -> "expected the name of the variable that should be fixed\n" - | 223 -> "expected the legislative text by which the value of the variable is fixed\n" - | 224 -> "expected the legislative text by which the value of the variable is fixed\n" - | 230 -> "expected a new scope use item \n" - | 233 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 234 -> "expected the struct name\n" - | 235 -> "expected a colon\n" - | 236 -> "expected struct data or condition\n" - | 237 -> "expected the name of this struct data \n" - | 238 -> "expected the type of this struct data, introduced by the content keyword\n" - | 239 -> "expected the type of this struct data\n" - | 263 -> "expected the name of this struct condition\n" - | 256 -> "expected a new struct data, or another declaration or scope use\n" - | 257 -> "expected the type of the parameter of this struct data function\n" - | 261 -> "expected a new struct data, or another declaration or scope use\n" - | 250 -> "expected a new struct data, or another declaration or scope use\n" - | 253 -> "expected a new struct data, or another declaration or scope use\n" - | 266 -> "expected the name of the scope you are declaring\n" - | 267 -> "expected a colon followed by the list of context items of this scope\n" - | 268 -> "expected a context item introduced by \"context\"\n" - | 269 -> "expected the name of this new context item\n" - | 270 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 271 -> "expected the name of the subscope for this context item\n" - | 278 -> "expected the next context item, or another declaration or scope use\n" - | 273 -> "expected the type of this context item\n" - | 274 -> "expected the next context item or a dependency declaration for this item\n" - | 276 -> "expected the next context item or a dependency declaration for this item\n" - | 281 -> "expected the name of your enum\n" - | 282 -> "expected a colon\n" - | 283 -> "expected an enum case\n" - | 284 -> "expected the name of an enum case \n" - | 285 -> "expected a payload for your enum case, or another case or declaration \n" - | 286 -> "expected a content type\n" - | 291 -> "expected another enum case, or a new declaration or scope use\n" + | 225 -> "expected an expression for the definition\n" + | 228 -> "expected an expression that shoud be asserted during execution\n" + | 229 -> "expecting the name of the varying variable\n" + | 231 -> "the variable varies with an expression that was expected here\n" + | 232 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 230 -> "expected an indication about what this variable varies with\n" + | 202 -> "expected an expression for this condition\n" + | 210 -> "expected a consequence for this definition under condition\n" + | 241 -> "expected an expression for this definition under condition\n" + | 237 -> "expected the name of the variable that should be fixed\n" + | 238 -> "expected the legislative text by which the value of the variable is fixed\n" + | 239 -> "expected the legislative text by which the value of the variable is fixed\n" + | 245 -> "expected a new scope use item \n" + | 248 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 249 -> "expected the struct name\n" + | 250 -> "expected a colon\n" + | 251 -> "expected struct data or condition\n" + | 252 -> "expected the name of this struct data \n" + | 253 -> "expected the type of this struct data, introduced by the content keyword\n" + | 254 -> "expected the type of this struct data\n" + | 279 -> "expected the name of this struct condition\n" + | 272 -> "expected a new struct data, or another declaration or scope use\n" + | 273 -> "expected the type of the parameter of this struct data function\n" + | 277 -> "expected a new struct data, or another declaration or scope use\n" + | 266 -> "expected a new struct data, or another declaration or scope use\n" + | 269 -> "expected a new struct data, or another declaration or scope use\n" + | 282 -> "expected the name of the scope you are declaring\n" + | 283 -> "expected a colon followed by the list of context items of this scope\n" + | 284 -> "expected a context item introduced by \"context\"\n" + | 285 -> "expected the name of this new context item\n" + | 286 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 287 -> "expected the name of the subscope for this context item\n" + | 294 -> "expected the next context item, or another declaration or scope use\n" + | 289 -> "expected the type of this context item\n" + | 290 -> "expected the next context item or a dependency declaration for this item\n" + | 292 -> "expected the next context item or a dependency declaration for this item\n" + | 297 -> "expected the name of your enum\n" + | 298 -> "expected a colon\n" + | 299 -> "expected an enum case\n" + | 300 -> "expected the name of an enum case \n" + | 301 -> "expected a payload for your enum case, or another case or declaration \n" + | 302 -> "expected a content type\n" + | 307 -> "expected another enum case, or a new declaration or scope use\n" | 17 -> "expected a declaration or a scope use\n" | 19 -> "expected a declaration or a scope use\n" - | 297 -> + | 313 -> "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" | _ -> raise Not_found diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out index b4e19443..c4eefbc9 100644 --- a/tests/test_money/no_mingle.catala.A.out +++ b/tests/test_money/no_mingle.catala.A.out @@ -1,6 +1,6 @@ -[ERROR] Error during typechecking, types dec and money are incompatible +[ERROR] Error during typechecking, types decimal and money are incompatible [ERROR] -[ERROR] Type dec coming from expression: +[ERROR] Type decimal coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | [ERROR] 12 | def z := (x *$ y) @@ -11,3 +11,27 @@ [ERROR] | [ERROR] 4 | new scope A: [ERROR] | ^ +[ERROR] +[ERROR] Type decimal → money coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 12 | def z := (x *$ y) +[ERROR] | ^^ +[ERROR] +[ERROR] Type money → any type coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 12 | def z := (x *$ y) +[ERROR] | ^^^^^^ +[ERROR] +[ERROR] Type money → decimal → money coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 12 | def z := (x *$ y) +[ERROR] | ^^ +[ERROR] +[ERROR] Type money → money → any type coming from expression: +[ERROR] --> test_money/no_mingle.catala +[ERROR] | +[ERROR] 12 | def z := (x *$ y) +[ERROR] | ^^^^^^ From a195a64677f1a632dff562e082a2bf0c06d25620 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 14:00:00 +0100 Subject: [PATCH 074/142] Duration is number of days --- src/catala/catala_surface/desugaring.ml | 41 +++------------------- src/catala/default_calculus/ast.ml | 2 +- src/catala/default_calculus/interpreter.ml | 28 ++++++--------- src/catala/default_calculus/print.ml | 6 +--- tests/test_date/durations.catala | 4 +-- tests/test_date/durations.catala.A.out | 2 +- tests/test_date/simple.catala.A.out | 2 +- 7 files changed, 21 insertions(+), 64 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 9a17f350..5cbaedc9 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -93,42 +93,11 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | MoneyAmount i -> Scopelang.Ast.ELit (Dcalc.Ast.LMoney Z.((i.money_amount_units * of_int 100) + i.money_amount_cents)) - | Number ((Int i, i_pos), Some (Year, _)) -> - Scopelang.Ast.ELit - (Dcalc.Ast.LDuration - (ODuration.make ~forward:true - ~year: - ( try Z.to_int i - with Failure _ -> - Errors.raise_spanned_error - "This duration is too big to fit in Catala's duration computation \ - engine" - i_pos ) - ())) - | Number ((Int i, i_pos), Some (Month, _)) -> - Scopelang.Ast.ELit - (Dcalc.Ast.LDuration - (ODuration.make ~forward:true - ~month: - ( try Z.to_int i - with Failure _ -> - Errors.raise_spanned_error - "This duration is too big to fit in Catala's duration computation \ - engine" - i_pos ) - ())) - | Number ((Int i, i_pos), Some (Day, _)) -> - Scopelang.Ast.ELit - (Dcalc.Ast.LDuration - (ODuration.make ~forward:true - ~day: - ( try Z.to_int i - with Failure _ -> - Errors.raise_spanned_error - "This duration is too big to fit in Catala's duration computation \ - engine" - i_pos ) - ())) + | Number ((Int i, _), Some (Year, _)) -> + Scopelang.Ast.ELit (Dcalc.Ast.LDuration Z.(of_int 365 * i)) + | Number ((Int i, _), Some (Month, _)) -> + Scopelang.Ast.ELit (Dcalc.Ast.LDuration Z.(of_int 30 * i)) + | Number ((Int i, _), Some (Day, _)) -> Scopelang.Ast.ELit (Dcalc.Ast.LDuration i) | Number ((Dec (_, _), _), Some ((Year | Month | Day), _)) -> Errors.raise_spanned_error "Impossible to specify decimal amounts of days, months or years" pos diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 293903a2..8bc22e8c 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -25,7 +25,7 @@ type typ = type date = ODate.Unix.t -type duration = ODate.Unix.d +type duration = Z.t type lit = | LBool of bool diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 48be0686..037b398c 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -69,13 +69,13 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis (Some "The null denominator:", Pos.get_position (List.nth args 2)); ] | A.Binop (A.Add KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - A.ELit (LDuration (ODuration.( + ) i1 i2)) + A.ELit (LDuration (Z.( + ) i1 i2)) | A.Binop (A.Sub KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - A.ELit (LDuration (ODuration.( - ) i1 i2)) + A.ELit (LDuration (Z.( - ) i1 i2)) | A.Binop (A.Sub KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> - A.ELit (LDuration (ODate.Unix.between i1 i2)) + A.ELit (LDuration (Z.of_int (ODuration.To.day (ODate.Unix.between i2 i1)))) | A.Binop (A.Add KDate), [ ELit (LDate i1); ELit (LDuration i2) ] -> - A.ELit (LDate (ODate.Unix.move i1 i2)) + A.ELit (LDate (ODate.Unix.advance_by_days i1 (Z.to_int i2))) | A.Binop (A.Lt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 < i2)) | A.Binop (A.Lte KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <= i2)) | A.Binop (A.Gt KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 > i2)) @@ -85,17 +85,13 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop (A.Gt KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) | A.Binop (A.Gte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) | A.Binop (A.Lt KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (ODuration.is_positive diff)) + A.ELit (LBool (i1 < i2)) | A.Binop (A.Lte KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (ODuration.is_positive diff || ODuration.is_instantenous diff)) + A.ELit (LBool (i1 <= i2)) | A.Binop (A.Gt KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (ODuration.is_negative diff)) + A.ELit (LBool (i1 > i2)) | A.Binop (A.Gte KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (ODuration.is_negative diff || ODuration.is_instantenous diff)) + A.ELit (LBool (i1 >= i2)) | A.Binop (A.Lt KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 < 0)) | A.Binop (A.Lte KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> @@ -104,18 +100,14 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis A.ELit (LBool (ODate.Unix.compare i1 i2 > 0)) | A.Binop (A.Gte KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 >= 0)) - | A.Binop A.Eq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (ODuration.is_instantenous diff)) + | A.Binop A.Eq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 = 0)) | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) - | A.Binop A.Neq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> - let diff = ODuration.( - ) i2 i1 in - A.ELit (LBool (not (ODuration.is_instantenous diff))) + | A.Binop A.Neq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 <> 0)) | A.Binop A.Neq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <> i2)) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 14487340..8e0ba0cf 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -91,11 +91,7 @@ let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = | LDate d -> Format.fprintf fmt "%s" (ODate.Unix.To.string (Option.get (ODate.Unix.To.generate_printer "%Y-%m-%d")) d) - | LDuration d -> - Format.fprintf fmt "%s" - (ODuration.To.string - (Option.get (ODuration.To.generate_printer "[%Y] years or [%M] months of [%D] days")) - d) + | LDuration d -> Format.fprintf fmt "%a days" Z.pp_print d let format_op_kind (fmt : Format.formatter) (k : op_kind) = Format.fprintf fmt "%s" diff --git a/tests/test_date/durations.catala b/tests/test_date/durations.catala index 8ad0787d..e838b0a9 100644 --- a/tests/test_date/durations.catala +++ b/tests/test_date/durations.catala @@ -10,6 +10,6 @@ new scope A: scope A: def x := |01/01/2019| def y := |30/09/2002| - def z := x -@ y >=^ 16 year - def z2 := x -@ y <^ 20 year + def z := y +@ (x -@ y) = x + def z2 := x -@ y = 16 year +^ 3 month +^ 7 day */ \ No newline at end of file diff --git a/tests/test_date/durations.catala.A.out b/tests/test_date/durations.catala.A.out index 0d683c24..041e78ab 100644 --- a/tests/test_date/durations.catala.A.out +++ b/tests/test_date/durations.catala.A.out @@ -1,4 +1,4 @@ [RESULT] x -> 2019-01-01 [RESULT] y -> 2002-09-30 [RESULT] z -> true -[RESULT] z2 -> false +[RESULT] z2 -> true diff --git a/tests/test_date/simple.catala.A.out b/tests/test_date/simple.catala.A.out index 865056ea..328a8520 100644 --- a/tests/test_date/simple.catala.A.out +++ b/tests/test_date/simple.catala.A.out @@ -1,3 +1,3 @@ [RESULT] x -> 2019-01-01 [RESULT] y -> 2002-09-30 -[RESULT] z -> 16 years or 195 months of 5937 days +[RESULT] z -> 5937 days From 26eff2a49fee101bf560787304fceca596c16568 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 16:58:32 +0100 Subject: [PATCH 075/142] Testing section 132 --- examples/us_tax_code/preamble.catala_en | 8 +++ examples/us_tax_code/section_132.catala_en | 34 +++++++---- .../tests/master_section_132.catala_en | 5 ++ .../tests/test_section_132.catala_en | 60 +++++++++++++++++++ src/catala/catala_surface/parser_driver.ml | 9 +-- src/catala/default_calculus/interpreter.ml | 11 +++- src/catala/default_calculus/print.ml | 2 +- src/catala/driver.ml | 3 +- src/catala/scope_language/scope_to_dcalc.ml | 37 +++++++----- 9 files changed, 132 insertions(+), 37 deletions(-) create mode 100644 examples/us_tax_code/tests/master_section_132.catala_en create mode 100644 examples/us_tax_code/tests/test_section_132.catala_en diff --git a/examples/us_tax_code/preamble.catala_en b/examples/us_tax_code/preamble.catala_en index 7cd5c0e0..2f7ced5a 100644 --- a/examples/us_tax_code/preamble.catala_en +++ b/examples/us_tax_code/preamble.catala_en @@ -1 +1,9 @@ @@The US Tax Code@@ + + +@@Begin metadata@@ +/* +declaration structure Person: + data id content integer +*/ +@@End metadata@@ \ No newline at end of file diff --git a/examples/us_tax_code/section_132.catala_en b/examples/us_tax_code/section_132.catala_en index cd47db87..fc22bbeb 100644 --- a/examples/us_tax_code/section_132.catala_en +++ b/examples/us_tax_code/section_132.catala_en @@ -15,6 +15,16 @@ declaration scope QualifiedEmployeeDiscount: context employee_discount content money context aggregate_cost content money context discount_type content DiscountType + context is_property content boolean + context is_services content boolean + +scope QualifiedEmployeeDiscount: + definition is_property equals match discount_type with pattern + -- Property: true + -- Services: false + definition is_services equals match discount_type with pattern + -- Property: false + -- Services: true */ @@End metadata@@ @@ -30,11 +40,11 @@ the property is being offered by the employer to customers, or /* scope QualifiedEmployeeDiscount : definition qualified_employee_discount - under condition discount_type with pattern Property consequence + under condition is_property consequence equals - if employee_discount > - customer_price * gross_profit_percentage - then customer_price * gross_profit_percentage + if employee_discount >$ + customer_price *$ gross_profit_percentage + then customer_price *$ gross_profit_percentage else employee_discount */ (B) in the case of services, 20 percent of the price at which the services are @@ -42,11 +52,11 @@ being offered by the employer to customers. /* scope QualifiedEmployeeDiscount : definition qualified_employee_discount - under condition discount_type with pattern Services consequence + under condition is_services consequence equals - if employee_discount > - customer_price * 20% - then customer_price * 20% + if employee_discount >$ + customer_price *$ 20% + then customer_price *$ 20% else employee_discount */ @@(2) Gross profit percentage@@++ @@ -60,11 +70,11 @@ to customers over the aggregate cost of such property to the employer, is of (ii) the aggregate sale price of such property. /* scope QualifiedEmployeeDiscount - under condition discount_type with pattern Property : - assertion customer_price >= aggregate_cost + under condition is_property : + assertion customer_price >=$ aggregate_cost definition gross_profit_percentage equals - (customer_price - aggregate_cost) / customer_price + (customer_price -$ aggregate_cost) /$ customer_price */ @(B) Determination of gross profit percentage@ Gross profit percentage shall be determined on the basis of— @@ -91,7 +101,7 @@ scope QualifiedEmployeeDiscount: assertion customer_price >= employee_price definition employee_discount equals - employee_price - customer_price + customer_price -$ employee_price */ @(4) Qualified property or services@ The term “qualified property or services” means any property (other than real diff --git a/examples/us_tax_code/tests/master_section_132.catala_en b/examples/us_tax_code/tests/master_section_132.catala_en new file mode 100644 index 00000000..e61ed549 --- /dev/null +++ b/examples/us_tax_code/tests/master_section_132.catala_en @@ -0,0 +1,5 @@ +@@Master file@@ + +@@Include: ../section_132.catala_en@@ + +@@Include: test_section_132.catala_en@@ \ No newline at end of file diff --git a/examples/us_tax_code/tests/test_section_132.catala_en b/examples/us_tax_code/tests/test_section_132.catala_en new file mode 100644 index 00000000..e281309f --- /dev/null +++ b/examples/us_tax_code/tests/test_section_132.catala_en @@ -0,0 +1,60 @@ +@Test@ + +/* +declaration scope TestSection132_1: + context section_132 scope QualifiedEmployeeDiscount + context qualified_employee_discount content money + context employee_discount content money + context gross_profit_percentage content decimal + +scope TestSection132_1: + definition section_132.customer_price equals $1500 + definition section_132.employee_price equals $1000 + definition section_132.aggregate_cost equals $900 + definition section_132.discount_type equals Property + definition employee_discount equals + section_132.employee_discount + definition gross_profit_percentage equals + section_132.gross_profit_percentage + definition qualified_employee_discount equals + section_132.qualified_employee_discount +*/ + +/* +declaration scope TestSection132_2: + context section_132 scope QualifiedEmployeeDiscount + context qualified_employee_discount content money + context employee_discount content money + context gross_profit_percentage content decimal + +scope TestSection132_2: + definition section_132.customer_price equals $1500 + definition section_132.employee_price equals $1000 + definition section_132.aggregate_cost equals $1200 + definition section_132.discount_type equals Property + definition employee_discount equals + section_132.employee_discount + definition gross_profit_percentage equals + section_132.gross_profit_percentage + definition qualified_employee_discount equals + section_132.qualified_employee_discount +*/ + +/* +declaration scope TestSection132_3: + context section_132 scope QualifiedEmployeeDiscount + context qualified_employee_discount content money + context employee_discount content money + context gross_profit_percentage content decimal + +scope TestSection132_3: + definition section_132.customer_price equals $1500 + definition section_132.employee_price equals $1000 + definition section_132.discount_type equals Services + definition employee_discount equals + section_132.employee_discount + definition gross_profit_percentage equals + section_132.gross_profit_percentage + definition qualified_employee_discount equals + section_132.qualified_employee_discount +*/ \ No newline at end of file diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index e138409b..b7d2c135 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -61,10 +61,11 @@ let raise_parser_error (error_loc : Pos.t) (last_good_loc : Pos.t option) (token (Printf.sprintf "Syntax error at token %s\n%s" (Cli.print_with_style syntax_hints_style "\"%s\"" token) msg) - ( ( match last_good_loc with - | None -> [] - | Some last_good_loc -> [ (Some "Last good token:", last_good_loc) ] ) - @ [ (Some "Error token:", error_loc) ] ) + ( (Some "Error token:", error_loc) + :: + ( match last_good_loc with + | None -> [] + | Some last_good_loc -> [ (Some "Last good token:", last_good_loc) ] ) ) let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * Parser.token) list) (last_input_needed : 'semantic_value I.env option) : 'a = diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 037b398c..35dee6d1 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -84,6 +84,10 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop (A.Lte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <= i2)) | A.Binop (A.Gt KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 > i2)) | A.Binop (A.Gte KRat), [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 >= i2)) + | A.Binop (A.Lt KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 < i2)) + | A.Binop (A.Lte KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 <= i2)) + | A.Binop (A.Gt KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 > i2)) + | A.Binop (A.Gte KMoney), [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 >= i2)) | A.Binop (A.Lt KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 < i2)) | A.Binop (A.Lte KDuration), [ ELit (LDuration i1); ELit (LDuration i2) ] -> @@ -131,7 +135,9 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis "Operator applied to the wrong arguments\n(should nothappen if the term was well-typed)" ( [ (Some "Operator:", Pos.get_position op) ] @ List.mapi - (fun i arg -> (Some ("Argument n°" ^ string_of_int (i + 1)), Pos.get_position arg)) + (fun i arg -> + ( Some (Format.asprintf "Argument n°%d, value %a" (i + 1) Print.format_expr arg), + Pos.get_position arg )) args ) ) op @@ -144,7 +150,6 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = | EApp (e1, args) -> ( let e1 = evaluate_expr e1 in let args = List.map evaluate_expr args in - match Pos.unmark e1 with | EAbs (_, binder, _) -> if Bindlib.mbinder_arity binder = List.length args then @@ -154,7 +159,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = (Format.asprintf "wrong function call, expected %d arguments, got %d" (Bindlib.mbinder_arity binder) (List.length args)) (Pos.get_position e) - | EOp op -> evaluate_operator (Pos.same_pos_as op e1) args + | EOp op -> Pos.same_pos_as (Pos.unmark (evaluate_operator (Pos.same_pos_as op e1) args)) e | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e | _ -> Errors.raise_spanned_error diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 8e0ba0cf..199a1f88 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -114,7 +114,7 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" - (match Pos.unmark op with Minus _ -> "-" | Not -> "~" | ErrorOnEmpty -> "error_on_empty") + (match Pos.unmark op with Minus _ -> "-" | Not -> "~" | ErrorOnEmpty -> "error_empty") let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ -> true | _ -> false diff --git a/src/catala/driver.ml b/src/catala/driver.ml index eb923361..ac05e4d1 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -133,7 +133,8 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ List.iter (fun (var, result) -> Cli.result_print - (Format.asprintf "%s -> %a" (Bindlib.name_of var) Dcalc.Print.format_expr result)) + (Format.asprintf "@[%s@ =@ %a@]" (Bindlib.name_of var) Dcalc.Print.format_expr + result)) results; 0 with Errors.StructuredError (msg, pos) -> diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 58e77c24..da301b07 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -21,6 +21,7 @@ type scope_sigs_ctx = ((Ast.ScopeVar.t * Dcalc.Ast.typ) list * Dcalc.Ast.Var.t) type ctx = { structs : Ast.struct_ctx; enums : Ast.enum_ctx; + scope_name : Ast.ScopeName.t; scopes_parameters : scope_sigs_ctx; scope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t; subscope_vars : (Dcalc.Ast.Var.t * Dcalc.Ast.typ) Ast.ScopeVarMap.t Ast.SubScopeMap.t; @@ -28,10 +29,11 @@ type ctx = { } let empty_ctx (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) (scopes_ctx : scope_sigs_ctx) - = + (scope_name : Ast.ScopeName.t) = { structs = struct_ctx; enums = enum_ctx; + scope_name; scopes_parameters = scopes_ctx; scope_vars = Ast.ScopeVarMap.empty; subscope_vars = Ast.SubScopeMap.empty; @@ -251,17 +253,17 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos in let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in let new_e = translate_expr ctx e in - let new_e = - Bindlib.box_apply - (fun new_e -> - ( Dcalc.Ast.EApp - ( (Dcalc.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.ErrorOnEmpty), Pos.get_position a_name), - [ new_e ] ), - Pos.get_position new_e )) - new_e - in let a_expr = Dcalc.Ast.make_var (a_var, var_def_pos) in let merged_expr = merge_defaults a_expr new_e in + let merged_expr = + Bindlib.box_apply + (fun merged_expr -> + ( Dcalc.Ast.EApp + ( (Dcalc.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.ErrorOnEmpty), Pos.get_position a_name), + [ merged_expr ] ), + Pos.get_position merged_expr )) + merged_expr + in let next_e = Dcalc.Ast.make_let_in a_var tau merged_expr next_e in (next_e, new_ctx) | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> @@ -396,8 +398,9 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : | hd :: tl -> translate_rule ctx hd tl pos_sigma let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) - (sctx : scope_sigs_ctx) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = - let ctx = empty_ctx struct_ctx enum_ctx sctx in + (sctx : scope_sigs_ctx) (scope_name : Ast.ScopeName.t) (sigma : Ast.scope_decl) : + Dcalc.Ast.expr Pos.marked Bindlib.box = + let ctx = empty_ctx struct_ctx enum_ctx sctx scope_name in let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in let rules, ctx = translate_rules ctx sigma.scope_decl_rules pos_sigma in let scope_variables, _ = Ast.ScopeMap.find sigma.scope_decl_name sctx in @@ -434,12 +437,14 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName let struct_ctx = prgm.program_structs in let enum_ctx = prgm.program_enums in let sctx : scope_sigs_ctx = - Ast.ScopeMap.map - (fun scope -> + Ast.ScopeMap.mapi + (fun scope_name scope -> let scope_dvar = Dcalc.Ast.Var.make (Ast.ScopeName.get_info scope.Ast.scope_decl_name) in ( List.map (fun (scope_var, tau) -> - let tau = translate_typ (empty_ctx struct_ctx enum_ctx Ast.ScopeMap.empty) tau in + let tau = + translate_typ (empty_ctx struct_ctx enum_ctx Ast.ScopeMap.empty scope_name) tau + in (scope_var, Pos.unmark tau)) (Ast.ScopeVarMap.bindings scope.scope_sig), scope_dvar )) @@ -456,7 +461,7 @@ let translate_program (prgm : Ast.program) (top_level_scope_name : Ast.ScopeName (fun scope_name (acc : Dcalc.Ast.expr Pos.marked Bindlib.box) -> let scope = Ast.ScopeMap.find scope_name prgm.program_scopes in let pos_scope = Pos.get_position (Ast.ScopeName.get_info scope.scope_decl_name) in - let scope_expr = translate_scope_decl struct_ctx enum_ctx sctx scope in + let scope_expr = translate_scope_decl struct_ctx enum_ctx sctx scope_name scope in let scope_sig, dvar = Ast.ScopeMap.find scope_name sctx in let scope_typ = build_scope_typ_from_sig scope_sig pos_scope in Dcalc.Ast.make_let_in dvar scope_typ scope_expr acc) From ebf14f61211f76beac28ff78a5f5b3443f7d18bc Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 18:11:43 +0100 Subject: [PATCH 076/142] Added assertions, starting to execute section132 --- Makefile | 26 ++++++++------ examples/Makefile | 12 +++++++ examples/Makefile.common | 10 +++--- examples/us_tax_code/section_132.catala_en | 11 ++++-- .../tests/test_section_132.catala_en | 35 +++++-------------- src/catala/catala_surface/desugaring.ml | 29 +++++++++++++++ src/catala/default_calculus/ast.ml | 1 + src/catala/default_calculus/interpreter.ml | 11 ++++++ src/catala/default_calculus/print.ml | 1 + src/catala/default_calculus/typing.ml | 6 ++++ src/catala/desugared/ast.ml | 2 +- src/catala/desugared/desugared_to_scope.ml | 9 ++--- src/catala/driver.ml | 3 ++ src/catala/scope_language/ast.ml | 1 + src/catala/scope_language/dependency.ml | 2 +- src/catala/scope_language/scope_to_dcalc.ml | 19 +++++++--- tests/test_bool/test_bool.catala.TestBool.out | 5 +-- tests/test_date/durations.catala.A.out | 9 ++--- tests/test_date/simple.catala.A.out | 7 ++-- .../test_dec/infinite_precision.catala.A.out | 10 +++--- tests/test_dec/simple.catala.A.out | 7 ++-- tests/test_enum/simple.catala.A.out | 5 +-- tests/test_func/func.catala.R.out | 3 +- tests/test_money/no_mingle.catala.A.out | 4 +-- tests/test_money/simple.catala.A.out | 7 ++-- .../grand_parent_caller.catala.A.out | 3 +- .../grand_parent_caller.catala.B.out | 5 +-- .../grand_parent_caller.catala.C.out | 5 +-- tests/test_scope/sub_scope.catala.A.out | 7 ++-- tests/test_scope/sub_scope.catala.B.out | 5 +-- tests/test_scope/sub_sub_scope.catala.A.out | 5 +-- tests/test_scope/sub_sub_scope.catala.C.out | 3 +- tests/test_struct/nested3.catala.A.out | 3 +- tests/test_struct/nested3.catala.B.out | 5 +-- tests/test_struct/simple.catala.A.out | 5 +-- 35 files changed, 183 insertions(+), 98 deletions(-) create mode 100644 examples/Makefile diff --git a/Makefile b/Makefile index 1065c56d..9650a465 100644 --- a/Makefile +++ b/Makefile @@ -109,23 +109,24 @@ CODE_GENERAL_IMPOTS_DIR=$(EXAMPLES_DIR)/code_general_impots US_TAX_CODE_DIR=$(EXAMPLES_DIR)/us_tax_code TUTORIAL_DIR=$(EXAMPLES_DIR)/tutorial -allocations_familiales: pygments build +literate_allocations_familiales: pygments build $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) $@.tex $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) $@.html -code_general_impots: pygments build +literate_code_general_impots: pygments build $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) $@.tex $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) $@.html -us_tax_code: pygments build +literate_us_tax_code: pygments build $(MAKE) -C $(US_TAX_CODE_DIR) $@.tex $(MAKE) -C $(US_TAX_CODE_DIR) $@.html -tutorial_en: pygments build +literate_tutorial_en: pygments build $(MAKE) -C $(TUTORIAL_DIR) $@.tex $(MAKE) -C $(TUTORIAL_DIR) $@.html -all_examples: allocations_familiales code_general_impots us_tax_code tutorial_en +literate_examples: literate_allocations_familiales literate_code_general_impots \ + literate_us_tax_code literate_tutorial_en ########################################## # Execute test suite @@ -133,8 +134,13 @@ all_examples: allocations_familiales code_general_impots us_tax_code tutorial_en .FORCE: -tests: build .FORCE - $(MAKE) -C tests +test_suite: .FORCE + @$(MAKE) --no-print-directory -C tests + +test_examples: .FORCE + @$(MAKE) --no-print-directory -C examples test_examples + +tests: test_suite test_examples ########################################## # Website assets @@ -147,13 +153,13 @@ catala.html: src/catala/utils/cli.ml dune exec src/catala.exe -- --help=groff | man2html | sed -e '1,8d' \ | tac | sed "1,20d" | tac > $@ -website-assets: doc all_examples grammar.html catala.html +website-assets: doc literate_examples grammar.html catala.html ########################################## # Misceallenous ########################################## -all: install-dependencies build doc tests all_examples website-assets +all: install-dependencies build doc tests literate_examples website-assets clean: dune clean @@ -168,6 +174,6 @@ inspect: ########################################## # Special targets ########################################## -.PHONY: inspect clean all all_examples english allocations_familiales pygments \ +.PHONY: inspect clean all literate_examples english allocations_familiales pygments \ install build format install-dependencies install-dependencies-ocaml \ catala.html diff --git a/examples/Makefile b/examples/Makefile new file mode 100644 index 00000000..6f09840e --- /dev/null +++ b/examples/Makefile @@ -0,0 +1,12 @@ +test_us_tax_code: + @SCOPE="TestSection132_1" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ + > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } + @echo "[PASS us_tax_code/section_132.catala_en (1/3)]" + @SCOPE="TestSection132_2" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ + > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } + @echo "[PASS us_tax_code/section_132.catala_en (2/3)]" + @SCOPE="TestSection132_3" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ + > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } + @echo "[PASS us_tax_code/section_132.catala_en (3/3)]" + +test_examples: test_us_tax_code \ No newline at end of file diff --git a/examples/Makefile.common b/examples/Makefile.common index e88c920c..e33e4571 100644 --- a/examples/Makefile.common +++ b/examples/Makefile.common @@ -7,7 +7,7 @@ LATEXMK=latexmk PYGMENTIZE_FR=../../syntax_highlighting/fr/pygments/pygments/env/bin/pygmentize PYGMENTIZE_EN=../../syntax_highlighting/en/pygments/pygments/env/bin/pygmentize -CATALA=dune exec --no-print-director ../../src/catala.exe -- --debug --language=$(CATALA_LANG) +CATALA=dune exec --no-print-director ../../src/catala.exe -- $(CATALA_OPTS) --language=$(CATALA_LANG) LEGIFRANCE_CATALA=dune exec ../../src/legifrance_catala.exe -- @@ -29,14 +29,14 @@ endif ########################################## %.run: %.catala_$(CATALA_LANG) $(CATALA_EXE) - $(CATALA) Makefile $< - $(CATALA) \ + @$(CATALA) Makefile $< + @$(CATALA) \ Interpret \ -s $(SCOPE) \ $< %.tex: %.catala_$(CATALA_LANG) $(CATALA_EXE) - $(CATALA) Makefile $< + @$(CATALA) Makefile $< $(CATALA) \ --wrap \ --pygmentize=$(PYGMENTIZE) \ @@ -44,7 +44,7 @@ endif $< %.html: %.catala_$(CATALA_LANG) $(CATALA_EXE) - $(CATALA) Makefile $< + @$(CATALA) Makefile $< $(CATALA) \ --wrap \ --pygmentize=$(PYGMENTIZE) \ diff --git a/examples/us_tax_code/section_132.catala_en b/examples/us_tax_code/section_132.catala_en index fc22bbeb..44c530a4 100644 --- a/examples/us_tax_code/section_132.catala_en +++ b/examples/us_tax_code/section_132.catala_en @@ -58,6 +58,12 @@ equals customer_price *$ 20% then customer_price *$ 20% else employee_discount + +scope QualifiedEmployeeDiscount under condition is_services: + # When selling a service, one does not need the aggregate cost. + # We provide a default value here so that the computations run smooth. + definition aggregate_cost equals $0 + definition gross_profit_percentage equals 0% */ @@(2) Gross profit percentage@@++ @@ -69,8 +75,7 @@ to customers over the aggregate cost of such property to the employer, is of (ii) the aggregate sale price of such property. /* -scope QualifiedEmployeeDiscount - under condition is_property : +scope QualifiedEmployeeDiscount under condition is_property: assertion customer_price >=$ aggregate_cost definition gross_profit_percentage equals @@ -98,7 +103,7 @@ an employee for use by such employee, is less than employer to customers. /* scope QualifiedEmployeeDiscount: - assertion customer_price >= employee_price + assertion customer_price >=$ employee_price definition employee_discount equals customer_price -$ employee_price diff --git a/examples/us_tax_code/tests/test_section_132.catala_en b/examples/us_tax_code/tests/test_section_132.catala_en index e281309f..ec772a0a 100644 --- a/examples/us_tax_code/tests/test_section_132.catala_en +++ b/examples/us_tax_code/tests/test_section_132.catala_en @@ -3,58 +3,39 @@ /* declaration scope TestSection132_1: context section_132 scope QualifiedEmployeeDiscount - context qualified_employee_discount content money - context employee_discount content money - context gross_profit_percentage content decimal scope TestSection132_1: definition section_132.customer_price equals $1500 definition section_132.employee_price equals $1000 definition section_132.aggregate_cost equals $900 definition section_132.discount_type equals Property - definition employee_discount equals - section_132.employee_discount - definition gross_profit_percentage equals - section_132.gross_profit_percentage - definition qualified_employee_discount equals - section_132.qualified_employee_discount + assertion section_132.employee_discount = $500 + assertion section_132.gross_profit_percentage = 0.4 + assertion section_132.qualified_employee_discount = $500 */ /* declaration scope TestSection132_2: context section_132 scope QualifiedEmployeeDiscount - context qualified_employee_discount content money - context employee_discount content money - context gross_profit_percentage content decimal scope TestSection132_2: definition section_132.customer_price equals $1500 definition section_132.employee_price equals $1000 definition section_132.aggregate_cost equals $1200 definition section_132.discount_type equals Property - definition employee_discount equals - section_132.employee_discount - definition gross_profit_percentage equals - section_132.gross_profit_percentage - definition qualified_employee_discount equals - section_132.qualified_employee_discount + assertion section_132.employee_discount = $500 + assertion section_132.gross_profit_percentage = 0.2 + assertion section_132.qualified_employee_discount = $300.00 */ /* declaration scope TestSection132_3: context section_132 scope QualifiedEmployeeDiscount - context qualified_employee_discount content money - context employee_discount content money - context gross_profit_percentage content decimal scope TestSection132_3: definition section_132.customer_price equals $1500 definition section_132.employee_price equals $1000 definition section_132.discount_type equals Services - definition employee_discount equals - section_132.employee_discount - definition gross_profit_percentage equals - section_132.gross_profit_percentage - definition qualified_employee_discount equals - section_132.qualified_employee_discount + assertion section_132.employee_discount = $500 + assertion section_132.qualified_employee_discount = $300 */ \ No newline at end of file diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 5cbaedc9..12c90b4c 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -450,6 +450,34 @@ let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) in process_def precond scope ctxt prgm def +(** Process an assertion from the surface language *) +let process_assert (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) + (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) + (prgm : Desugared.Ast.program) (ass : Ast.assertion) : Desugared.Ast.program = + let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm.program_scopes in + let ass = + translate_expr scope_uid None ctxt + ( match ass.Ast.assertion_condition with + | None -> ass.Ast.assertion_content + | Some cond -> + ( Ast.IfThenElse + (cond, ass.Ast.assertion_content, Pos.same_pos_as (Ast.Literal (Ast.Bool true)) cond), + Pos.get_position cond ) ) + in + let ass = + match precond with + | Some precond -> + Bindlib.box_apply2 + (fun precond ass -> + ( Scopelang.Ast.EIfThenElse + (precond, ass, Pos.same_pos_as (Scopelang.Ast.ELit (Dcalc.Ast.LBool true)) precond), + Pos.get_position precond )) + precond ass + | None -> ass + in + let new_scope = { scope with scope_assertions = ass :: scope.scope_assertions } in + { prgm with program_scopes = Scopelang.Ast.ScopeMap.add scope_uid new_scope prgm.program_scopes } + let process_scope_use_item (precond : Ast.expression Pos.marked option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (item : Ast.scope_use_item Pos.marked) : Desugared.Ast.program = @@ -457,6 +485,7 @@ let process_scope_use_item (precond : Ast.expression Pos.marked option) match Pos.unmark item with | Ast.Rule rule -> process_rule precond scope ctxt prgm rule | Ast.Definition def -> process_def precond scope ctxt prgm def + | Ast.Assertion ass -> process_assert precond scope ctxt prgm ass | _ -> prgm let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 8bc22e8c..559265ac 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -75,6 +75,7 @@ type expr = | ELit of lit | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list + | EAssert of expr Pos.marked | EOp of operator | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 35dee6d1..17957c26 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -107,6 +107,7 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop A.Eq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 = 0)) + | A.Binop A.Eq, [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) @@ -114,6 +115,7 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop A.Neq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 <> 0)) + | A.Binop A.Neq, [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <> i2)) | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) @@ -258,6 +260,15 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = "Expected a boolean literal for the result of this condition (should not happen if the \ term was well-typed)" (Pos.get_position cond) ) + | EAssert e' -> ( + match Pos.unmark (evaluate_expr e') with + | ELit (LBool true) -> Pos.same_pos_as (Ast.ELit LUnit) e' + | ELit (LBool false) -> Errors.raise_spanned_error "Assertion failed" (Pos.get_position e') + | _ -> + Errors.raise_spanned_error + "Expected a boolean literal for the result of this assertion (should not happen if the \ + term was well-typed)" + (Pos.get_position e') ) let empty_thunked_term : Ast.expr Pos.marked = let silent = Ast.Var.make ("_", Pos.no_pos) in diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 199a1f88..925968d1 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -193,3 +193,4 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = Format.fprintf fmt "@[⟨%a ⊢ %a |@ %a⟩@]" format_expr just format_expr cons (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) subs + | EAssert e' -> Format.fprintf fmt "@[assert@ (%a)@]" format_expr e' diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index a83ff31e..f63a04f6 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -239,6 +239,9 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m let tt = typecheck_expr_bottom_up env et in typecheck_expr_top_down env ef tt; tt + | EAssert e' -> + typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); + UnionFind.make (Pos.same_pos_as (TLit TUnit) e') and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = @@ -364,6 +367,9 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); typecheck_expr_top_down env et tau; typecheck_expr_top_down env ef tau + | EAssert e' -> + typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); + unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e')) let infer_type (e : A.expr Pos.marked) : A.typ Pos.marked = let ty = typecheck_expr_bottom_up A.VarMap.empty e in diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 4d7f6cc1..ba50e072 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -70,7 +70,7 @@ let empty_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked opti parent_rule = None; } -type assertion = Scopelang.Ast.expr Pos.marked +type assertion = Scopelang.Ast.expr Pos.marked Bindlib.box type variation_typ = Increasing | Decreasing diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 56fe0382..970ac996 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -142,10 +142,6 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = (fun vertex -> match vertex with | Dependency.Vertex.Var (var : Scopelang.Ast.ScopeVar.t) -> - (* Cli.debug_print (Format.asprintf "Finding %a in %a" - Scopelang.Ast.ScopeVar.format_t var (Format.pp_print_list ~pp_sep:(fun fmt () -> - Format.fprintf fmt ", ") (fun fmt (d, _) -> Format.fprintf fmt "%a" - Ast.ScopeDef.format_t d)) (Ast.ScopeDefMap.bindings scope.scope_defs)); *) let var_def, var_typ = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in @@ -199,6 +195,11 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = sub_scope_vars_redefs @ [ Scopelang.Ast.Call (sub_scope, sub_scope_index) ]) scope_ordering) in + (* Then, after having computed all the scopes variables, we add the assertions *) + let scope_decl_rules = + scope_decl_rules + @ List.map (fun e -> Scopelang.Ast.Assertion (Bindlib.unbox e)) scope.Ast.scope_assertions + in let scope_sig = Scopelang.Ast.ScopeVarSet.fold (fun var acc -> diff --git a/src/catala/driver.ml b/src/catala/driver.ml index ac05e4d1..74fa9be8 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -130,6 +130,9 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ (fun (v1, _) (v2, _) -> String.compare (Bindlib.name_of v1) (Bindlib.name_of v2)) results in + Cli.result_print + (Format.asprintf "Computation successful!%s" + (if List.length results > 0 then " Results:" else "")); List.iter (fun (var, result) -> Cli.result_print diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 23dba6bf..90ffafc9 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -142,6 +142,7 @@ module VarMap = Map.Make (Var) type rule = | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked + | Assertion of expr Pos.marked | Call of ScopeName.t * SubScopeName.t type scope_decl = { diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index d6e69f4c..3e960080 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -54,7 +54,7 @@ let build_program_dep_graph (prgm : Ast.program) : SDependencies.t = List.fold_left (fun acc r -> match r with - | Ast.Definition _ -> acc + | Ast.Definition _ | Ast.Assertion _ -> acc | Ast.Call (subscope, subindex) -> if subscope = scope_name then Errors.raise_spanned_error diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index da301b07..78e64698 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -227,10 +227,10 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po with Not_found -> Errors.raise_spanned_error (Format.asprintf - "The variable %a.%a cannot be used here, as subscope %a's results will not have \ - been computed yet" - Ast.SubScopeName.format_t (Pos.unmark s) Ast.ScopeVar.format_t (Pos.unmark a) - Ast.SubScopeName.format_t (Pos.unmark s)) + "The variable %a.%a cannot be used here,\n\ + as subscope %a's results will not have been computed yet" Ast.SubScopeName.format_t + (Pos.unmark s) Ast.ScopeVar.format_t (Pos.unmark a) Ast.SubScopeName.format_t + (Pos.unmark s)) (Pos.get_position e) ) | EIfThenElse (cond, et, ef) -> Bindlib.box_apply3 @@ -380,6 +380,15 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos pos_sigma ) call_expr results_bindings, new_ctx ) + | Assertion e -> + let next_e, new_ctx = translate_rules ctx rest pos_sigma in + let new_e = translate_expr ctx e in + ( Dcalc.Ast.make_let_in + (Dcalc.Ast.Var.make ("_", Pos.no_pos)) + (Dcalc.Ast.TLit TUnit, Pos.no_pos) + (Bindlib.box_apply (fun new_e -> Pos.same_pos_as (Dcalc.Ast.EAssert new_e) e) new_e) + next_e, + new_ctx ) and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = @@ -412,7 +421,7 @@ let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) scope_variables in Dcalc.Ast.make_abs - (Array.of_list ((List.map (fun (_, _, x) -> x)) scope_variables)) + (Array.of_list (List.map (fun (_, _, x) -> x) scope_variables)) rules pos_sigma (List.map (fun (_, tau, _) -> diff --git a/tests/test_bool/test_bool.catala.TestBool.out b/tests/test_bool/test_bool.catala.TestBool.out index 7b15996f..1aec45c0 100644 --- a/tests/test_bool/test_bool.catala.TestBool.out +++ b/tests/test_bool/test_bool.catala.TestBool.out @@ -1,2 +1,3 @@ -[RESULT] bar -> 1 -[RESULT] foo -> true +[RESULT] Computation successful! Results: +[RESULT] bar = 1 +[RESULT] foo = true diff --git a/tests/test_date/durations.catala.A.out b/tests/test_date/durations.catala.A.out index 041e78ab..5f4830ef 100644 --- a/tests/test_date/durations.catala.A.out +++ b/tests/test_date/durations.catala.A.out @@ -1,4 +1,5 @@ -[RESULT] x -> 2019-01-01 -[RESULT] y -> 2002-09-30 -[RESULT] z -> true -[RESULT] z2 -> true +[RESULT] Computation successful! Results: +[RESULT] x = 2019-01-01 +[RESULT] y = 2002-09-30 +[RESULT] z = true +[RESULT] z2 = true diff --git a/tests/test_date/simple.catala.A.out b/tests/test_date/simple.catala.A.out index 328a8520..d4a33863 100644 --- a/tests/test_date/simple.catala.A.out +++ b/tests/test_date/simple.catala.A.out @@ -1,3 +1,4 @@ -[RESULT] x -> 2019-01-01 -[RESULT] y -> 2002-09-30 -[RESULT] z -> 5937 days +[RESULT] Computation successful! Results: +[RESULT] x = 2019-01-01 +[RESULT] y = 2002-09-30 +[RESULT] z = 5937 days diff --git a/tests/test_dec/infinite_precision.catala.A.out b/tests/test_dec/infinite_precision.catala.A.out index 2f4468d4..ada2c13c 100644 --- a/tests/test_dec/infinite_precision.catala.A.out +++ b/tests/test_dec/infinite_precision.catala.A.out @@ -1,4 +1,6 @@ -[RESULT] a -> -0.000000000000000000000000000000000000000000000000000000000078695580959228473468… -[RESULT] x -> 84.64866565265689623 -[RESULT] y -> -4.3682977870532065498 -[RESULT] z -> 654265429805103220650980650.570540510654 +[RESULT] Computation successful! Results: +[RESULT] a = +[RESULT] -0.000000000000000000000000000000000000000000000000000000000078695580959228473468… +[RESULT] x = 84.64866565265689623 +[RESULT] y = -4.3682977870532065498 +[RESULT] z = 654265429805103220650980650.570540510654 diff --git a/tests/test_dec/simple.catala.A.out b/tests/test_dec/simple.catala.A.out index 67b7a267..ccba3f94 100644 --- a/tests/test_dec/simple.catala.A.out +++ b/tests/test_dec/simple.catala.A.out @@ -1,3 +1,4 @@ -[RESULT] x -> 84.0648665 -[RESULT] y -> 4.368297 -[RESULT] z -> 19.24431111254569000230… +[RESULT] Computation successful! Results: +[RESULT] x = 84.0648665 +[RESULT] y = 4.368297 +[RESULT] z = 19.24431111254569000230… diff --git a/tests/test_enum/simple.catala.A.out b/tests/test_enum/simple.catala.A.out index 9cf56e3e..f96f9b73 100644 --- a/tests/test_enum/simple.catala.A.out +++ b/tests/test_enum/simple.catala.A.out @@ -1,2 +1,3 @@ -[RESULT] x -> Case1 2 -[RESULT] y -> 42 +[RESULT] Computation successful! Results: +[RESULT] x = Case1 2 +[RESULT] y = 42 diff --git a/tests/test_func/func.catala.R.out b/tests/test_func/func.catala.R.out index ad91a9a0..300773d6 100644 --- a/tests/test_func/func.catala.R.out +++ b/tests/test_func/func.catala.R.out @@ -1 +1,2 @@ -[RESULT] r -> 30 +[RESULT] Computation successful! Results: +[RESULT] r = 30 diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out index c4eefbc9..70c03391 100644 --- a/tests/test_money/no_mingle.catala.A.out +++ b/tests/test_money/no_mingle.catala.A.out @@ -18,7 +18,7 @@ [ERROR] 12 | def z := (x *$ y) [ERROR] | ^^ [ERROR] -[ERROR] Type money → any type coming from expression: +[ERROR] Type money → money coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | [ERROR] 12 | def z := (x *$ y) @@ -30,7 +30,7 @@ [ERROR] 12 | def z := (x *$ y) [ERROR] | ^^ [ERROR] -[ERROR] Type money → money → any type coming from expression: +[ERROR] Type money → money → money coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | [ERROR] 12 | def z := (x *$ y) diff --git a/tests/test_money/simple.catala.A.out b/tests/test_money/simple.catala.A.out index 26094971..e4bcb522 100644 --- a/tests/test_money/simple.catala.A.out +++ b/tests/test_money/simple.catala.A.out @@ -1,3 +1,4 @@ -[RESULT] x -> $123.54 -[RESULT] y -> $8548650.96 -[RESULT] z -> $7.23 +[RESULT] Computation successful! Results: +[RESULT] x = $123.54 +[RESULT] y = $8548650.96 +[RESULT] z = $7.23 diff --git a/tests/test_scope/grand_parent_caller.catala.A.out b/tests/test_scope/grand_parent_caller.catala.A.out index 6cc0064e..3e7d18ba 100644 --- a/tests/test_scope/grand_parent_caller.catala.A.out +++ b/tests/test_scope/grand_parent_caller.catala.A.out @@ -1 +1,2 @@ -[RESULT] x -> 0 +[RESULT] Computation successful! Results: +[RESULT] x = 0 diff --git a/tests/test_scope/grand_parent_caller.catala.B.out b/tests/test_scope/grand_parent_caller.catala.B.out index b1eb98a7..1ce0ed16 100644 --- a/tests/test_scope/grand_parent_caller.catala.B.out +++ b/tests/test_scope/grand_parent_caller.catala.B.out @@ -1,2 +1,3 @@ -[RESULT] y1 -> 1 -[RESULT] y2 -> 1 +[RESULT] Computation successful! Results: +[RESULT] y1 = 1 +[RESULT] y2 = 1 diff --git a/tests/test_scope/grand_parent_caller.catala.C.out b/tests/test_scope/grand_parent_caller.catala.C.out index cfc18223..299a271c 100644 --- a/tests/test_scope/grand_parent_caller.catala.C.out +++ b/tests/test_scope/grand_parent_caller.catala.C.out @@ -1,2 +1,3 @@ -[RESULT] z1 -> 2 -[RESULT] z2 -> 2 +[RESULT] Computation successful! Results: +[RESULT] z1 = 2 +[RESULT] z2 = 2 diff --git a/tests/test_scope/sub_scope.catala.A.out b/tests/test_scope/sub_scope.catala.A.out index 08227657..359b080f 100644 --- a/tests/test_scope/sub_scope.catala.A.out +++ b/tests/test_scope/sub_scope.catala.A.out @@ -1,3 +1,4 @@ -[RESULT] a -> -1 -[RESULT] a_base -> 1 -[RESULT] b -> false +[RESULT] Computation successful! Results: +[RESULT] a = -1 +[RESULT] a_base = 1 +[RESULT] b = false diff --git a/tests/test_scope/sub_scope.catala.B.out b/tests/test_scope/sub_scope.catala.B.out index cc4ef583..e8af119e 100644 --- a/tests/test_scope/sub_scope.catala.B.out +++ b/tests/test_scope/sub_scope.catala.B.out @@ -1,2 +1,3 @@ -[RESULT] a -> 42 -[RESULT] b -> true +[RESULT] Computation successful! Results: +[RESULT] a = 42 +[RESULT] b = true diff --git a/tests/test_scope/sub_sub_scope.catala.A.out b/tests/test_scope/sub_sub_scope.catala.A.out index 0f4b2ef8..ea07d167 100644 --- a/tests/test_scope/sub_sub_scope.catala.A.out +++ b/tests/test_scope/sub_sub_scope.catala.A.out @@ -1,2 +1,3 @@ -[RESULT] u -> true -[RESULT] x -> 0 +[RESULT] Computation successful! Results: +[RESULT] u = true +[RESULT] x = 0 diff --git a/tests/test_scope/sub_sub_scope.catala.C.out b/tests/test_scope/sub_sub_scope.catala.C.out index 70b6389a..1aa6eb1b 100644 --- a/tests/test_scope/sub_sub_scope.catala.C.out +++ b/tests/test_scope/sub_sub_scope.catala.C.out @@ -1 +1,2 @@ -[RESULT] z -> 2 +[RESULT] Computation successful! Results: +[RESULT] z = 2 diff --git a/tests/test_struct/nested3.catala.A.out b/tests/test_struct/nested3.catala.A.out index d8f09825..19684eab 100644 --- a/tests/test_struct/nested3.catala.A.out +++ b/tests/test_struct/nested3.catala.A.out @@ -1 +1,2 @@ -[RESULT] t -> ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) +[RESULT] Computation successful! Results: +[RESULT] t = ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) diff --git a/tests/test_struct/nested3.catala.B.out b/tests/test_struct/nested3.catala.B.out index 7c755661..6bd1ec5b 100644 --- a/tests/test_struct/nested3.catala.B.out +++ b/tests/test_struct/nested3.catala.B.out @@ -1,2 +1,3 @@ -[RESULT] out -> 1 -[RESULT] t -> ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) +[RESULT] Computation successful! Results: +[RESULT] out = 1 +[RESULT] t = ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) diff --git a/tests/test_struct/simple.catala.A.out b/tests/test_struct/simple.catala.A.out index 3921742f..9f5a68ed 100644 --- a/tests/test_struct/simple.catala.A.out +++ b/tests/test_struct/simple.catala.A.out @@ -1,2 +1,3 @@ -[RESULT] s -> ("x": 1,"y": 2) -[RESULT] z -> 3 +[RESULT] Computation successful! Results: +[RESULT] s = ("x": 1,"y": 2) +[RESULT] z = 3 From c5048378a2d8b0d0e70187c27880a51e8e161f1f Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 18:16:20 +0100 Subject: [PATCH 077/142] Removed duplicated CI target --- .github/workflows/build.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 452e99ae..1a2f80a6 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -59,11 +59,6 @@ jobs: eval $(opam env) make tests - - name: Make examples - run: | - eval $(opam env) - make all_examples - - name: Make assets and documentation run: | eval $(opam env) From 8f8d3224002510becfa85ddc261b7f89a1a11f65 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 10 Dec 2020 18:21:48 +0100 Subject: [PATCH 078/142] Fixed makefile wrangling --- Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Makefile b/Makefile index 9650a465..3347bf4d 100644 --- a/Makefile +++ b/Makefile @@ -110,20 +110,20 @@ US_TAX_CODE_DIR=$(EXAMPLES_DIR)/us_tax_code TUTORIAL_DIR=$(EXAMPLES_DIR)/tutorial literate_allocations_familiales: pygments build - $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) $@.tex - $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) $@.html + $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) allocations_familiales.tex + $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) allocations_familiales.html literate_code_general_impots: pygments build - $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) $@.tex - $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) $@.html + $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) code_general_impots.tex + $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) code_general_impots.html literate_us_tax_code: pygments build - $(MAKE) -C $(US_TAX_CODE_DIR) $@.tex - $(MAKE) -C $(US_TAX_CODE_DIR) $@.html + $(MAKE) -C $(US_TAX_CODE_DIR) us_tax_code.tex + $(MAKE) -C $(US_TAX_CODE_DIR) us_tax_code.html literate_tutorial_en: pygments build - $(MAKE) -C $(TUTORIAL_DIR) $@.tex - $(MAKE) -C $(TUTORIAL_DIR) $@.html + $(MAKE) -C $(TUTORIAL_DIR) tutorial_en.tex + $(MAKE) -C $(TUTORIAL_DIR) tutorial_en.html literate_examples: literate_allocations_familiales literate_code_general_impots \ literate_us_tax_code literate_tutorial_en From 2fed7c23a05806b7e5d25ae53c2a83e3932469aa Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 11 Dec 2020 10:51:46 +0100 Subject: [PATCH 079/142] Added logging --- src/catala/default_calculus/ast.ml | 8 +- src/catala/default_calculus/interpreter.ml | 19 ++++ src/catala/default_calculus/print.ml | 20 ++++- src/catala/default_calculus/typing.ml | 1 + src/catala/driver.ml | 4 +- src/catala/scope_language/scope_to_dcalc.ml | 98 +++++++++++++++++---- src/catala/utils/cli.ml | 18 +++- 7 files changed, 145 insertions(+), 23 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 559265ac..36c83bd2 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -58,7 +58,13 @@ type binop = | Eq | Neq -type unop = Not | Minus of op_kind | ErrorOnEmpty +type log_entry = VarDef | BeginCall | EndCall + +type unop = + | Not + | Minus of op_kind + | ErrorOnEmpty + | Log of log_entry * Utils.Uid.MarkedString.info list type operator = Binop of binop | Unop of unop diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 17957c26..3d4420bc 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -131,6 +131,25 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis situation)" (Pos.get_position op) else e' + | A.Unop (A.Log (entry, infos)), [ e' ] -> + if !Cli.trace_flag then + match entry with + | VarDef -> + Cli.log_print + (Format.asprintf "%a %a = %a" Print.format_log_entry entry + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") + (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) + infos Print.format_expr (e', Pos.no_pos)) + | _ -> + Cli.log_print + (Format.asprintf "%a %a" Print.format_log_entry entry + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") + (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) + infos) + else (); + e' | A.Unop _, [ ELit LEmptyError ] -> A.ELit LEmptyError | _ -> Errors.raise_multispanned_error diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 925968d1..44f42809 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -112,12 +112,28 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = | Gt k -> Format.fprintf fmt "%s%a" ">" format_op_kind k | Gte k -> Format.fprintf fmt "%s%a" ">=" format_op_kind k +let format_log_entry (fmt : Format.formatter) (entry : log_entry) : unit = + Format.fprintf fmt "%s" + ( match entry with + | VarDef -> "Defining variable" + | BeginCall -> "Calling subscope" + | EndCall -> "Returned from subscope" ) + let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = Format.fprintf fmt "%s" - (match Pos.unmark op with Minus _ -> "-" | Not -> "~" | ErrorOnEmpty -> "error_empty") + ( match Pos.unmark op with + | Minus _ -> "-" + | Not -> "~" + | ErrorOnEmpty -> "error_empty" + | Log (entry, infos) -> + Format.asprintf "log@[[%a|%a]@]" format_log_entry entry + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") + (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) + infos ) let needs_parens (e : expr Pos.marked) : bool = - match Pos.unmark e with EAbs _ -> true | _ -> false + match Pos.unmark e with EAbs _ | EApp _ -> true | _ -> false let format_var (fmt : Format.formatter) (v : Var.t) : unit = Format.fprintf fmt "%s" (Bindlib.name_of v) diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index f63a04f6..2a58f21f 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -109,6 +109,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Unop (A.Minus KDuration) -> arr dut dut | A.Unop A.Not -> arr bt bt | A.Unop A.ErrorOnEmpty -> arr any any + | A.Unop (A.Log _) -> arr any any | Binop (Mult (KDate | KDuration)) | Binop (Div (KDate | KDuration)) | Unop (Minus KDate) -> Errors.raise_spanned_error "This operator is not available!" pos diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 74fa9be8..e811c027 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -18,10 +18,12 @@ module Errors = Utils.Errors (** Entry function for the executable. Returns a negative number in case of error. *) let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_output : bool) (pygmentize_loc : string option) (backend : string) (language : string option) - (max_prec_digits : int option) (ex_scope : string option) (output_file : string option) : int = + (max_prec_digits : int option) (trace : bool) (ex_scope : string option) + (output_file : string option) : int = try Cli.debug_flag := debug; Cli.style_flag := not unstyled; + Cli.trace_flag := trace; Cli.debug_print "Reading files..."; (match max_prec_digits with None -> () | Some i -> Cli.max_prec_digits := i); let language = diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 78e64698..cef03149 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -238,7 +238,8 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po (translate_expr ctx cond) (translate_expr ctx et) (translate_expr ctx ef) | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) ) -let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos_sigma : Pos.t) : +let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) + ((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rule with | Definition ((ScopeVar a, var_def_pos), tau, e) -> @@ -251,7 +252,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos scope_vars = Ast.ScopeVarMap.add (Pos.unmark a) (a_var, Pos.unmark tau) ctx.scope_vars; } in - let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in + let next_e, new_ctx = translate_rules new_ctx rest (sigma_name, pos_sigma) in let new_e = translate_expr ctx e in let a_expr = Dcalc.Ast.make_var (a_var, var_def_pos) in let merged_expr = merge_defaults a_expr new_e in @@ -264,6 +265,18 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos Pos.get_position merged_expr )) merged_expr in + let merged_expr = + Bindlib.box_apply + (fun merged_expr -> + ( Dcalc.Ast.EApp + ( ( Dcalc.Ast.EOp + (Dcalc.Ast.Unop + (Dcalc.Ast.Log (Dcalc.Ast.VarDef, [ (sigma_name, pos_sigma); a_name ]))), + Pos.get_position a_name ), + [ merged_expr ] ), + Pos.get_position merged_expr )) + merged_expr + in let next_e = Dcalc.Ast.make_let_in a_var tau merged_expr next_e in (next_e, new_ctx) | Definition ((SubScopeVar (_subs_name, subs_index, subs_var), var_def_pos), tau, e) -> @@ -293,7 +306,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos ctx.subscope_vars; } in - let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in + let next_e, new_ctx = translate_rules new_ctx rest (sigma_name, pos_sigma) in let intermediate_e = Dcalc.Ast.make_abs (Array.of_list [ Pos.unmark a_var ]) @@ -302,6 +315,18 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos (Pos.get_position e) in let new_e = translate_expr ctx e in + let new_e = + Bindlib.box_apply + (fun new_e -> + ( Dcalc.Ast.EApp + ( ( Dcalc.Ast.EOp + (Dcalc.Ast.Unop + (Dcalc.Ast.Log (Dcalc.Ast.VarDef, [ (sigma_name, pos_sigma); a_name ]))), + Pos.get_position a_name ), + [ new_e ] ), + Pos.get_position new_e )) + new_e + in let silent_var = Dcalc.Ast.Var.make ("_", Pos.no_pos) in let thunked_new_e = Dcalc.Ast.make_abs @@ -354,15 +379,34 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos ctx.subscope_vars; } in + let subscope_func = + Dcalc.Ast.make_var (scope_dcalc_var, Pos.get_position (Ast.SubScopeName.get_info subindex)) + in + let subscope_func = + Bindlib.box_apply + (fun subscope_func -> + ( Dcalc.Ast.EApp + ( ( Dcalc.Ast.EOp + (Dcalc.Ast.Unop + (Dcalc.Ast.Log + ( Dcalc.Ast.BeginCall, + [ + (sigma_name, pos_sigma); + Ast.SubScopeName.get_info subindex; + Ast.ScopeName.get_info subname; + ] ))), + Pos.get_position subscope_func ), + [ subscope_func ] ), + Pos.get_position subscope_func )) + subscope_func + in let call_expr = Bindlib.box_apply2 (fun e u -> (Dcalc.Ast.EApp (e, u), Pos.no_pos)) - (Dcalc.Ast.make_var - (scope_dcalc_var, Pos.get_position (Ast.SubScopeName.get_info subindex))) - (Bindlib.box_list subscope_args) + subscope_func (Bindlib.box_list subscope_args) in let result_tuple_var = Dcalc.Ast.Var.make ("result", Pos.no_pos) in - let next_e, new_ctx = translate_rules new_ctx rest pos_sigma in + let next_e, new_ctx = translate_rules new_ctx rest (sigma_name, pos_sigma) in let results_bindings, _ = List.fold_right (fun (_, tau, dvar) (acc, i) -> @@ -375,13 +419,31 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos all_subscope_vars_dcalc (next_e, List.length all_subscope_vars_dcalc - 1) in - ( Dcalc.Ast.make_let_in result_tuple_var - ( Dcalc.Ast.TTuple (List.map (fun (_, tau, _) -> (tau, pos_sigma)) all_subscope_vars_dcalc), - pos_sigma ) - call_expr results_bindings, - new_ctx ) + let results_bindings = + Bindlib.box_apply + (fun results_bindings -> + ( Dcalc.Ast.EApp + ( ( Dcalc.Ast.EOp + (Dcalc.Ast.Unop + (Dcalc.Ast.Log + ( Dcalc.Ast.EndCall, + [ + (sigma_name, pos_sigma); + Ast.SubScopeName.get_info subindex; + Ast.ScopeName.get_info subname; + ] ))), + Pos.get_position results_bindings ), + [ results_bindings ] ), + Pos.get_position results_bindings )) + results_bindings + in + let result_tuple_typ = + ( Dcalc.Ast.TTuple (List.map (fun (_, tau, _) -> (tau, pos_sigma)) all_subscope_vars_dcalc), + pos_sigma ) + in + (Dcalc.Ast.make_let_in result_tuple_var result_tuple_typ call_expr results_bindings, new_ctx) | Assertion e -> - let next_e, new_ctx = translate_rules ctx rest pos_sigma in + let next_e, new_ctx = translate_rules ctx rest (sigma_name, pos_sigma) in let new_e = translate_expr ctx e in ( Dcalc.Ast.make_let_in (Dcalc.Ast.Var.make ("_", Pos.no_pos)) @@ -390,7 +452,8 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (pos next_e, new_ctx ) -and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : +and translate_rules (ctx : ctx) (rules : Ast.rule list) + ((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) : Dcalc.Ast.expr Pos.marked Bindlib.box * ctx = match rules with | [] -> @@ -404,14 +467,14 @@ and translate_rules (ctx : ctx) (rules : Ast.rule list) (pos_sigma : Pos.t) : scope_variables)) in (return_exp, ctx) - | hd :: tl -> translate_rule ctx hd tl pos_sigma + | hd :: tl -> translate_rule ctx hd tl (sigma_name, pos_sigma) let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) (sctx : scope_sigs_ctx) (scope_name : Ast.ScopeName.t) (sigma : Ast.scope_decl) : Dcalc.Ast.expr Pos.marked Bindlib.box = let ctx = empty_ctx struct_ctx enum_ctx sctx scope_name in - let pos_sigma = Pos.get_position (Ast.ScopeName.get_info sigma.scope_decl_name) in - let rules, ctx = translate_rules ctx sigma.scope_decl_rules pos_sigma in + let sigma_info = Ast.ScopeName.get_info sigma.scope_decl_name in + let rules, ctx = translate_rules ctx sigma.scope_decl_rules sigma_info in let scope_variables, _ = Ast.ScopeMap.find sigma.scope_decl_name sctx in let scope_variables = List.map @@ -420,6 +483,7 @@ let translate_scope_decl (struct_ctx : Ast.struct_ctx) (enum_ctx : Ast.enum_ctx) (x, tau, dcalc_x)) scope_variables in + let pos_sigma = Pos.get_position sigma_info in Dcalc.Ast.make_abs (Array.of_list (List.map (fun (_, _, x) -> x) scope_variables)) rules pos_sigma diff --git a/src/catala/utils/cli.ml b/src/catala/utils/cli.ml index 14c63624..a8105632 100644 --- a/src/catala/utils/cli.ml +++ b/src/catala/utils/cli.ml @@ -24,6 +24,8 @@ let style_flag = ref true (* Max number of digits to show for decimal results *) let max_prec_digits = ref 20 +let trace_flag = ref false + open Cmdliner let file = @@ -36,6 +38,9 @@ let debug = Arg.(value & flag & info [ "debug"; "d" ] ~doc:"Prints debug informa let unstyled = Arg.(value & flag & info [ "unstyled" ] ~doc:"Removes styling from terminal output") +let trace_opt = + Arg.(value & flag & info [ "trace"; "t" ] ~doc:"Displays a trace of the intepreter's computation") + let wrap_weaved_output = Arg.( value & flag @@ -92,7 +97,7 @@ let pygmentize_loc = let catala_t f = Term.( const f $ file $ debug $ unstyled $ wrap_weaved_output $ pygmentize_loc $ backend $ language - $ max_prec_digits_opt $ ex_scope $ output) + $ max_prec_digits_opt $ trace_opt $ ex_scope $ output) let info = let doc = @@ -106,11 +111,12 @@ let info = from legislative texts."; `S Manpage.s_authors; `P "Denis Merigoux "; + `P "Nicolas Chataing "; `S Manpage.s_examples; `P "Typical usage:"; `Pre "catala LaTeX file.catala"; `S Manpage.s_bugs; - `P "Please file bug reports at https://gitlab.inria.fr/verifisc/catala/issues"; + `P "Please file bug reports at https://github.com/CatalaLang/catala/issues"; ] in let exits = Term.default_exits @ [ Term.exit_info ~doc:"on error." 1 ] in @@ -140,6 +146,9 @@ let warning_marker () = print_with_style [ ANSITerminal.Bold; ANSITerminal.yello (** Prints [\[RESULT\]] in green on the terminal standard output *) let result_marker () = print_with_style [ ANSITerminal.Bold; ANSITerminal.green ] "[RESULT] " +(** Prints [\[LOG\]] in red on the terminal error output *) +let log_marker () = print_with_style [ ANSITerminal.Bold; ANSITerminal.black ] "[LOG] " + (**{2 Printers}*) (** All the printers below print their argument after the correct marker *) @@ -186,3 +195,8 @@ let result_print (s : string) = Printf.printf "%s\n" (add_prefix_to_each_line s (fun _ -> result_marker ())); flush stdout; flush stdout + +let log_print (s : string) = + Printf.printf "%s\n" (add_prefix_to_each_line s (fun _ -> log_marker ())); + flush stdout; + flush stdout From 4c219f81ffc066d1b675d8d917b56b4e11121878 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 11 Dec 2020 15:24:10 +0100 Subject: [PATCH 080/142] Automatic unit test detection but needs normal include --- examples/Makefile | 42 ++++++++++++++----- .../tests/master_section_132.catala_en | 5 --- .../tests/test_section_132.catala_en | 2 + 3 files changed, 33 insertions(+), 16 deletions(-) delete mode 100644 examples/us_tax_code/tests/master_section_132.catala_en diff --git a/examples/Makefile b/examples/Makefile index 6f09840e..a8279d79 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,12 +1,32 @@ -test_us_tax_code: - @SCOPE="TestSection132_1" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ - > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } - @echo "[PASS us_tax_code/section_132.catala_en (1/3)]" - @SCOPE="TestSection132_2" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ - > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } - @echo "[PASS us_tax_code/section_132.catala_en (2/3)]" - @SCOPE="TestSection132_3" $(MAKE) --no-print-directory -C us_tax_code tests/master_section_132.run \ - > /dev/null || { echo "[FAIL us_tax_code/section_132.catala_en (1/3)]"; exit 1; } - @echo "[PASS us_tax_code/section_132.catala_en (3/3)]" +################################ +# Running legislation unit tests +################################ -test_examples: test_us_tax_code \ No newline at end of file + +# Usage `make ..` +# This Makefile rule assumes the following directory structure: +# foo_example +# tests/ +# foo_test_file1.catala +# foo_test_file2.catala +# ... +# foo_implem.catala +# ... +%.run: .FORCE + @SCOPE="$(word 3,$(subst ., ,$*))" $(MAKE) --no-print-directory -C \ + $(word 1,$(subst ., ,$*)) tests/$(word 2,$(subst ., ,$*)).run \ + > /dev/null || { echo "[FAIL $@]"; exit 1; } + @echo "[PASS $@]" + +TEST_FILES=$(wildcard */tests/*.catala*) + +TEST_FILES_SCOPES=$(foreach TEST_FILE,$(TEST_FILES),\ + $(foreach TEST_SCOPE,\ + $(shell grep -Po "declaration scope [^:]*" $(TEST_FILE) | cut -d " " -f 3), \ + $(word 1,$(subst /, ,$(TEST_FILE))).$(word 3,$(subst /, ,$(TEST_FILE))).$(TEST_SCOPE).run \ + ) \ +) + +test_examples: $(TEST_FILES_SCOPES) + +.FORCE: \ No newline at end of file diff --git a/examples/us_tax_code/tests/master_section_132.catala_en b/examples/us_tax_code/tests/master_section_132.catala_en deleted file mode 100644 index e61ed549..00000000 --- a/examples/us_tax_code/tests/master_section_132.catala_en +++ /dev/null @@ -1,5 +0,0 @@ -@@Master file@@ - -@@Include: ../section_132.catala_en@@ - -@@Include: test_section_132.catala_en@@ \ No newline at end of file diff --git a/examples/us_tax_code/tests/test_section_132.catala_en b/examples/us_tax_code/tests/test_section_132.catala_en index ec772a0a..abe14297 100644 --- a/examples/us_tax_code/tests/test_section_132.catala_en +++ b/examples/us_tax_code/tests/test_section_132.catala_en @@ -1,5 +1,7 @@ @Test@ +@@Include: ../section_132.catala_en@@ + /* declaration scope TestSection132_1: context section_132 scope QualifiedEmployeeDiscount From 1ddd46af559ad0d26f7317c1b7ff68f35ef5aaa5 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 11 Dec 2020 21:17:01 +0100 Subject: [PATCH 081/142] Automatic unit test discovery, improved inclusion system --- examples/Makefile | 2 +- .../decrets_divers.catala_fr | 2 - .../tests/test_section_132.catala_en | 3 +- src/catala/catala_surface/ast.ml | 6 +- src/catala/catala_surface/desugaring.ml | 2 +- src/catala/catala_surface/name_resolution.ml | 2 +- src/catala/catala_surface/parser.messages | 404 +++++++++--------- src/catala/catala_surface/parser.mly | 8 +- src/catala/catala_surface/parser_driver.ml | 119 ++++-- src/catala/catala_surface/parser_errors.ml | 248 +++++------ src/catala/driver.ml | 2 +- src/catala/literate_programming/html.ml | 2 +- src/catala/literate_programming/latex.ml | 18 +- 13 files changed, 423 insertions(+), 395 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index a8279d79..87471edf 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -23,7 +23,7 @@ TEST_FILES=$(wildcard */tests/*.catala*) TEST_FILES_SCOPES=$(foreach TEST_FILE,$(TEST_FILES),\ $(foreach TEST_SCOPE,\ $(shell grep -Po "declaration scope [^:]*" $(TEST_FILE) | cut -d " " -f 3), \ - $(word 1,$(subst /, ,$(TEST_FILE))).$(word 3,$(subst /, ,$(TEST_FILE))).$(TEST_SCOPE).run \ + $(word 1,$(subst /, ,$(TEST_FILE))).$(word 1,$(subst ., ,$(word 3,$(subst /, ,$(TEST_FILE))))).$(TEST_SCOPE).run \ ) \ ) diff --git a/examples/allocations_familiales/decrets_divers.catala_fr b/examples/allocations_familiales/decrets_divers.catala_fr index 49e60aa6..74e1b942 100644 --- a/examples/allocations_familiales/decrets_divers.catala_fr +++ b/examples/allocations_familiales/decrets_divers.catala_fr @@ -32,8 +32,6 @@ Ils indiquent les montants relatifs aux allocations familiales, à l’ Je vous demande de bien vouloir transmettre à la connaissance des organismes débiteurs les présentes instructions. -@@Inclusion: JORFTEXT000000227447@@ - /* # Cependant, le cas de Mayotte n'est pas traité dans la loi et ce sont donc # les règles de cette annexe qui s'apppliquent. diff --git a/examples/us_tax_code/tests/test_section_132.catala_en b/examples/us_tax_code/tests/test_section_132.catala_en index abe14297..157501f6 100644 --- a/examples/us_tax_code/tests/test_section_132.catala_en +++ b/examples/us_tax_code/tests/test_section_132.catala_en @@ -1,7 +1,6 @@ -@Test@ - @@Include: ../section_132.catala_en@@ +@Test@ /* declaration scope TestSection132_1: context section_132 scope QualifiedEmployeeDiscount diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 17e09c36..8dac14b3 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -209,14 +209,12 @@ type law_include = | CatalaFile of string Pos.marked | LegislativeText of string Pos.marked -type law_article_item = - | LawText of string - | CodeBlock of code_block * source_repr - | LawInclude of law_include +type law_article_item = LawText of string | CodeBlock of code_block * source_repr type law_heading = { law_heading_name : string; law_heading_precedence : int } type law_structure = + | LawInclude of law_include | LawHeading of law_heading * law_structure list | LawArticle of law_article * law_article_item list | MetadataBlock of code_block * source_repr diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 12c90b4c..767e4b41 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -556,7 +556,7 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desu | LawArticle (_, children) -> List.fold_left (fun prgm child -> processer_article_item prgm child) prgm children | MetadataBlock (b, c) -> processer_article_item prgm (CodeBlock (b, c)) - | IntermediateText _ -> prgm + | IntermediateText _ | LawInclude _ -> prgm in let processer_item (prgm : Desugared.Ast.program) (item : Ast.program_item) : diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 9bd78d63..2a2632d4 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -338,7 +338,7 @@ let rec process_law_structure (ctxt : context) (s : Ast.law_structure) (fun ctxt child -> process_law_article_item ctxt child process_item) ctxt children | Ast.MetadataBlock (b, c) -> process_law_article_item ctxt (Ast.CodeBlock (b, c)) process_item - | Ast.IntermediateText _ -> ctxt + | Ast.IntermediateText _ | Ast.LawInclude _ -> ctxt (** Process a program item *) let process_program_item (ctxt : context) (item : Ast.program_item) diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index f29f5b1d..be509fe3 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,8 +1,8 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 313. +## Ends in an error in state: 314. ## -## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## BEGIN_CODE option(law_text) code END_CODE @@ -12,9 +12,9 @@ should not happen, please file an issue at https://github.com/CatalaLang/catala/ source_file_or_master: BEGIN_METADATA BEGIN_CODE YEAR ## -## Ends in an error in state: 19. +## Ends in an error in state: 20. ## -## metadata_block -> BEGIN_CODE . option(law_text) code END_CODE option(law_text) END_METADATA [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## metadata_block -> BEGIN_CODE . option(law_text) code END_CODE option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## BEGIN_CODE @@ -24,9 +24,9 @@ expected a declaration or a scope use source_file_or_master: BEGIN_METADATA YEAR ## -## Ends in an error in state: 17. +## Ends in an error in state: 18. ## -## source_file_item -> BEGIN_METADATA . option(law_text) metadata_block [ LAW_TEXT LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## source_file_item -> BEGIN_METADATA . option(law_text) metadata_block [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## BEGIN_METADATA @@ -36,7 +36,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 307. +## Ends in an error in state: 308. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -49,7 +49,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 302. +## Ends in an error in state: 303. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -61,7 +61,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 301. +## Ends in an error in state: 302. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -73,7 +73,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 300. +## Ends in an error in state: 301. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -85,7 +85,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 300. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -97,7 +97,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 299. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -109,7 +109,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 297. +## Ends in an error in state: 298. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -121,7 +121,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 292. +## Ends in an error in state: 293. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -133,7 +133,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 290. +## Ends in an error in state: 291. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -145,7 +145,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 289. +## Ends in an error in state: 290. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -157,7 +157,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 294. +## Ends in an error in state: 295. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -170,7 +170,7 @@ expected the next context item, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 287. +## Ends in an error in state: 288. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -182,7 +182,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 287. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -196,7 +196,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 286. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -210,7 +210,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 284. +## Ends in an error in state: 285. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -222,7 +222,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 283. +## Ends in an error in state: 284. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -234,7 +234,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 283. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -246,7 +246,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 269. +## Ends in an error in state: 270. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -258,7 +258,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR ## -## Ends in an error in state: 266. +## Ends in an error in state: 267. ## ## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -270,7 +270,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 277. +## Ends in an error in state: 278. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 274. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -294,7 +294,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 272. +## Ends in an error in state: 273. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -306,7 +306,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 279. +## Ends in an error in state: 280. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -318,7 +318,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 254. +## Ends in an error in state: 255. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -330,7 +330,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 254. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -342,7 +342,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 252. +## Ends in an error in state: 253. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +354,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 251. +## Ends in an error in state: 252. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -366,7 +366,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 251. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -378,7 +378,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 249. +## Ends in an error in state: 250. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -390,7 +390,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 248. +## Ends in an error in state: 249. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -404,7 +404,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 245. +## Ends in an error in state: 246. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -416,23 +416,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 52, spurious reduction of production primitive_expression -> CARDINAL -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression -## In state 242, spurious reduction of production assertion_base -> expression -## In state 243, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 244, spurious reduction of production scope_item -> ASSERTION assertion +## In state 53, spurious reduction of production primitive_expression -> CARDINAL +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 243, spurious reduction of production assertion_base -> expression +## In state 244, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 245, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 239. +## Ends in an error in state: 240. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -444,7 +444,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 238. +## Ends in an error in state: 239. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -455,15 +455,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 237. +## Ends in an error in state: 238. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -475,7 +475,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 241. +## Ends in an error in state: 242. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -487,7 +487,7 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 210. +## Ends in an error in state: 211. ## ## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -498,21 +498,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 52, spurious reduction of production primitive_expression -> CARDINAL -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression -## In state 203, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 53, spurious reduction of production primitive_expression -> CARDINAL +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 204, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 202. +## Ends in an error in state: 203. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -524,7 +524,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 230. +## Ends in an error in state: 231. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -535,15 +535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 232. +## Ends in an error in state: 233. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -554,15 +554,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 231. +## Ends in an error in state: 232. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -574,7 +574,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 229. +## Ends in an error in state: 230. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -586,7 +586,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 228. +## Ends in an error in state: 229. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -598,7 +598,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 225. +## Ends in an error in state: 226. ## ## definition -> qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -610,7 +610,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 223. +## Ends in an error in state: 224. ## ## definition -> qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -622,7 +622,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 224. +## Ends in an error in state: 225. ## ## definition -> qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -634,7 +634,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 222. +## Ends in an error in state: 223. ## ## definition -> qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -645,15 +645,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 221. +## Ends in an error in state: 222. ## ## scope_item -> DEFINITION . definition [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -665,7 +665,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 220. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -677,7 +677,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 207. +## Ends in an error in state: 208. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -689,7 +689,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 201. +## Ends in an error in state: 202. ## ## rule -> rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -701,7 +701,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 214. +## Ends in an error in state: 215. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -713,7 +713,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 204. +## Ends in an error in state: 205. ## ## rule -> rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -725,7 +725,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 213. +## Ends in an error in state: 214. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -736,15 +736,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 218, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 200, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 218. +## Ends in an error in state: 219. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -757,7 +757,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 200. ## ## scope_item -> RULE . rule [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -769,7 +769,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 198. +## Ends in an error in state: 199. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -781,7 +781,7 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 52. +## Ends in an error in state: 53. ## ## aggregate_func -> CARDINAL . [ FOR ] ## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -794,7 +794,7 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 150. +## Ends in an error in state: 151. ## ## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -808,7 +808,7 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 149. +## Ends in an error in state: 150. ## ## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -820,7 +820,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 74. +## Ends in an error in state: 75. ## ## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -832,7 +832,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 165. +## Ends in an error in state: 166. ## ## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -844,7 +844,7 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 171. +## Ends in an error in state: 172. ## ## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -856,7 +856,7 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 170. +## Ends in an error in state: 171. ## ## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -867,14 +867,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 170. ## ## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -886,7 +886,7 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 168. +## Ends in an error in state: 169. ## ## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -898,7 +898,7 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 167. +## Ends in an error in state: 168. ## ## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -910,7 +910,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 158. +## Ends in an error in state: 159. ## ## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -922,7 +922,7 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 162. +## Ends in an error in state: 163. ## ## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -933,14 +933,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 162. ## ## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -952,7 +952,7 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 161. ## ## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -964,7 +964,7 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 159. +## Ends in an error in state: 160. ## ## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -976,7 +976,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 47. +## Ends in an error in state: 48. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -988,7 +988,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 173. +## Ends in an error in state: 174. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -999,20 +999,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 176. +## Ends in an error in state: 177. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1024,7 +1024,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 175. +## Ends in an error in state: 176. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1035,20 +1035,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 174. +## Ends in an error in state: 175. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1060,7 +1060,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 45. +## Ends in an error in state: 46. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1072,7 +1072,7 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 65. +## Ends in an error in state: 66. ## ## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1084,7 +1084,7 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 178. +## Ends in an error in state: 179. ## ## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1095,20 +1095,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 43. +## Ends in an error in state: 44. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1120,7 +1120,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 180. +## Ends in an error in state: 181. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1131,14 +1131,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 183. +## Ends in an error in state: 184. ## ## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1149,20 +1149,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 140, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 187, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 141, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 188, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 186. +## Ends in an error in state: 187. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1174,7 +1174,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 191. +## Ends in an error in state: 192. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1186,7 +1186,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 185. +## Ends in an error in state: 186. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1198,7 +1198,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 189. +## Ends in an error in state: 190. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1211,7 +1211,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 188. +## Ends in an error in state: 189. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1223,7 +1223,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 182. +## Ends in an error in state: 183. ## ## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1235,7 +1235,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 181. +## Ends in an error in state: 182. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1247,7 +1247,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 42. +## Ends in an error in state: 43. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1259,7 +1259,7 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 53. +## Ends in an error in state: 54. ## ## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1271,7 +1271,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 139. +## Ends in an error in state: 140. ## ## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1283,7 +1283,7 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 135. +## Ends in an error in state: 136. ## ## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1295,7 +1295,7 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 134. +## Ends in an error in state: 135. ## ## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1306,14 +1306,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 132. +## Ends in an error in state: 133. ## ## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1325,7 +1325,7 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 131. +## Ends in an error in state: 132. ## ## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1337,7 +1337,7 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 130. +## Ends in an error in state: 131. ## ## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1349,7 +1349,7 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 129. +## Ends in an error in state: 130. ## ## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1361,7 +1361,7 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 59. +## Ends in an error in state: 60. ## ## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1373,7 +1373,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 197. +## Ends in an error in state: 198. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1384,22 +1384,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression -## In state 119, spurious reduction of production mult_expression -> base_expression -## In state 106, spurious reduction of production sum_expression -> mult_expression -## In state 82, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> compare_expression -## In state 157, spurious reduction of production expression -> logical_expression -## In state 195, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 196, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 196, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 197, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 57. +## Ends in an error in state: 58. ## ## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1411,7 +1411,7 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 155. +## Ends in an error in state: 156. ## ## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1423,7 +1423,7 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 119. +## Ends in an error in state: 120. ## ## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1435,15 +1435,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression -## In state 61, spurious reduction of production base_expression -> primitive_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 126. +## Ends in an error in state: 127. ## ## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1455,7 +1455,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 105. +## Ends in an error in state: 106. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1467,7 +1467,7 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 64. +## Ends in an error in state: 65. ## ## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1479,7 +1479,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 145. +## Ends in an error in state: 146. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1491,7 +1491,7 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 117. +## Ends in an error in state: 118. ## ## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1503,7 +1503,7 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 61. +## Ends in an error in state: 62. ## ## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1517,14 +1517,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 56, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 62. +## Ends in an error in state: 63. ## ## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1536,7 +1536,7 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 56. +## Ends in an error in state: 57. ## ## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -1550,7 +1550,7 @@ expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL DIV INT_LITERAL YEAR ## -## Ends in an error in state: 31. +## Ends in an error in state: 32. ## ## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1562,7 +1562,7 @@ expected a delimiter to finish the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL DIV YEAR ## -## Ends in an error in state: 30. +## Ends in an error in state: 31. ## ## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1574,7 +1574,7 @@ expected the third component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV INT_LITERAL YEAR ## -## Ends in an error in state: 29. +## Ends in an error in state: 30. ## ## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1586,7 +1586,7 @@ expected a "/" source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL DIV YEAR ## -## Ends in an error in state: 28. +## Ends in an error in state: 29. ## ## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1598,7 +1598,7 @@ expected the second component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL INT_LITERAL YEAR ## -## Ends in an error in state: 27. +## Ends in an error in state: 28. ## ## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1610,7 +1610,7 @@ expected a "/" source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION VERTICAL YEAR ## -## Ends in an error in state: 25. +## Ends in an error in state: 26. ## ## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1622,7 +1622,7 @@ expected the first component of the date literal source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION YEAR ## -## Ends in an error in state: 24. +## Ends in an error in state: 25. ## ## scope_use_condition -> UNDER_CONDITION . expression [ COLON ] ## @@ -1634,7 +1634,7 @@ expected an expression which will act as the condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 23. +## Ends in an error in state: 24. ## ## code_item -> SCOPE constructor . option(scope_use_condition) COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1646,7 +1646,7 @@ expected a scope use precondition or a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE YEAR ## -## Ends in an error in state: 21. +## Ends in an error in state: 22. ## ## code_item -> SCOPE . constructor option(scope_use_condition) COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1672,7 +1672,7 @@ source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## ## Ends in an error in state: 329. ## -## law_articles_items -> law_article_item . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## law_article_item @@ -1682,9 +1682,9 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 322. +## Ends in an error in state: 323. ## -## source_file_article -> law_article . law_articles_items [ LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## ## The known suffix of the stack is as follows: ## law_article @@ -1694,7 +1694,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 317. +## Ends in an error in state: 318. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index b4b96838..412752a3 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -546,9 +546,6 @@ law_article_item: let (code, pos) = code_and_pos in CodeBlock (code, (text, pos)) } -| includ = LAW_INCLUDE { - LawInclude includ -} law_article: | title = LAW_ARTICLE { @@ -590,6 +587,9 @@ source_file_item: let (code, source_repr) = code in LawStructure (MetadataBlock (code, source_repr)) } +| includ = LAW_INCLUDE { + LawStructure (LawInclude includ) +} source_file_after_text: | i = source_file_article f = source_file_after_text { @@ -632,7 +632,7 @@ source_file_or_master: | [] -> assert false (* there should be at least one rest element *) | rest_head::rest_tail -> begin match first_item with - | LawStructure (LawArticle _ | MetadataBlock _ | IntermediateText _) -> + | LawStructure (LawArticle _ | MetadataBlock _ | IntermediateText _ | LawInclude _) -> (* if an article or an include is just before a new heading or a new article, then we don't merge it with what comes next *) first_item::rest_head::rest_tail diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index b7d2c135..708bcc8a 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -154,52 +154,85 @@ let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * with Sedlexing.MalFormed | Sedlexing.InvalidCodepoint _ -> Lexer.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) -let rec parse_source_files (source_files : string list) (language : Cli.frontend_lang) : Ast.program - = - match source_files with - | [] -> { program_items = []; program_source_files = [] } - | source_file :: rest -> ( - Cli.debug_print (Printf.sprintf "Parsing %s" source_file); - let input = try open_in source_file with Sys_error msg -> Errors.raise_error msg in - let lexbuf = Sedlexing.Utf8.from_channel input in - Sedlexing.set_filename lexbuf source_file; - Parse_utils.current_file := source_file; - let lexer_lang = - match language with - | `Fr -> Lexer_fr.lexer_fr - | `En -> Lexer_en.lexer_en - | `NonVerbose -> Lexer.lexer +let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) : Ast.program = + Cli.debug_print (Printf.sprintf "Parsing %s" source_file); + let input = try open_in source_file with Sys_error msg -> Errors.raise_error msg in + let lexbuf = Sedlexing.Utf8.from_channel input in + Sedlexing.set_filename lexbuf source_file; + Parse_utils.current_file := source_file; + let lexer_lang = + match language with + | `Fr -> Lexer_fr.lexer_fr + | `En -> Lexer_en.lexer_en + | `NonVerbose -> Lexer.lexer + in + let token_list_lang = + match language with + | `Fr -> Lexer_fr.token_list_fr + | `En -> Lexer_en.token_list_en + | `NonVerbose -> Lexer.token_list + in + let commands_or_includes = + sedlex_with_menhir lexer_lang token_list_lang Parser.Incremental.source_file_or_master lexbuf + in + close_in input; + match commands_or_includes with + | Ast.SourceFile commands -> + let program = expand_includes source_file commands language in + { + program_items = program.Ast.program_items; + program_source_files = source_file :: program.Ast.program_source_files; + } + | Ast.MasterFile includes -> + let current_source_file_dirname = Filename.dirname source_file in + let includes = + List.map + (fun includ -> + (if current_source_file_dirname = "./" then "" else current_source_file_dirname ^ "/") + ^ Pos.unmark includ) + includes in - let token_list_lang = - match language with - | `Fr -> Lexer_fr.token_list_fr - | `En -> Lexer_en.token_list_en - | `NonVerbose -> Lexer.token_list + let new_program = + List.fold_left + (fun acc includ_file -> + let includ_program = parse_source_file includ_file language in + { + Ast.program_source_files = + acc.Ast.program_source_files @ includ_program.program_source_files; + Ast.program_items = acc.Ast.program_items @ includ_program.program_items; + }) + { Ast.program_source_files = []; Ast.program_items = [] } + includes in - let commands_or_includes = - sedlex_with_menhir lexer_lang token_list_lang Parser.Incremental.source_file_or_master - lexbuf - in - close_in input; - match commands_or_includes with - | Ast.SourceFile commands -> - let rest_program = parse_source_files rest language in + { new_program with program_source_files = source_file :: new_program.program_source_files } + +and expand_includes (source_file : string) (commands : Ast.program_item list) + (language : Cli.frontend_lang) : Ast.program = + List.fold_left + (fun acc command -> + match command with + | Ast.LawStructure (LawInclude (Ast.CatalaFile sub_source)) -> + let source_dir = Filename.dirname source_file in + let sub_source = Filename.concat source_dir (Pos.unmark sub_source) in + let includ_program = parse_source_file sub_source language in { - program_items = commands @ rest_program.Ast.program_items; - program_source_files = source_file :: rest_program.Ast.program_source_files; + Ast.program_source_files = + acc.Ast.program_source_files @ includ_program.program_source_files; + Ast.program_items = acc.Ast.program_items @ includ_program.program_items; } - | Ast.MasterFile includes -> - let current_source_file_dirname = Filename.dirname source_file in - let includes = - List.map - (fun includ -> - ( if current_source_file_dirname = "./" then "" - else current_source_file_dirname ^ "/" ) - ^ Pos.unmark includ) - includes + | Ast.LawStructure (Ast.LawHeading (heading, commands')) -> + let { Ast.program_items = commands'; Ast.program_source_files = new_sources } = + expand_includes source_file (List.map (fun x -> Ast.LawStructure x) commands') language in - let new_program = parse_source_files (includes @ rest) language in { - new_program with - program_source_files = source_file :: new_program.program_source_files; - } ) + Ast.program_source_files = acc.Ast.program_source_files @ new_sources; + Ast.program_items = + acc.Ast.program_items + @ [ + Ast.LawStructure + (Ast.LawHeading (heading, List.map (fun (Ast.LawStructure x) -> x) commands')); + ]; + } + | i -> { acc with Ast.program_items = acc.Ast.program_items @ [ i ] }) + { Ast.program_source_files = []; Ast.program_items = [] } + commands diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 89197bb1..dd067584 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -11,146 +11,146 @@ let message s = | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 317 -> "expected some text, another heading or a law article\n" - | 322 -> "expected a code block, a metadata block, more law text or a heading\n" + | 318 -> "expected some text, another heading or a law article\n" + | 323 -> "expected a code block, a metadata block, more law text or a heading\n" | 329 -> "expected a code block, a metadata block, more law text or a heading\n" | 324 -> "expected a declaration or a scope use\n" - | 21 -> "expected the name of the scope you want to use\n" - | 23 -> "expected a scope use precondition or a colon\n" - | 24 -> "expected an expression which will act as the condition\n" - | 25 -> "expected the first component of the date literal\n" - | 27 -> "expected a \"/\"\n" - | 28 -> "expected the second component of the date literal\n" - | 29 -> "expected a \"/\"\n" - | 30 -> "expected the third component of the date literal\n" - | 31 -> "expected a delimiter to finish the date literal\n" - | 56 -> "expected an operator to compose the expression on the left with\n" - | 62 -> "expected an enum constructor to test if the expression on the left\n" - | 61 -> "expected an operator to compose the expression on the left with\n" - | 117 -> "expected an expression on the right side of the sum or minus operator\n" - | 145 -> "expected an expression on the right side of the logical operator\n" - | 64 -> "expected an expression for the argument of this function call\n" - | 105 -> "expected an expression on the right side of the comparison operator\n" - | 126 -> "expected an expression on the right side of the multiplication or division operator\n" - | 119 -> "expected an operator to compose the expression on the left\n" - | 155 -> "expected an expression standing for the set you want to test for membership\n" - | 57 -> "expected an identifier standing for a struct field or a subscope name\n" - | 197 -> "expected a colon after the scope use precondition\n" - | 59 -> "expected a constructor, to get the payload of this enum case\n" - | 129 -> "expected the \"for\" keyword to spell the aggregation\n" - | 130 -> "expected an identifier for the aggregation bound variable\n" - | 131 -> "expected the \"in\" keyword\n" - | 132 -> + | 22 -> "expected the name of the scope you want to use\n" + | 24 -> "expected a scope use precondition or a colon\n" + | 25 -> "expected an expression which will act as the condition\n" + | 26 -> "expected the first component of the date literal\n" + | 28 -> "expected a \"/\"\n" + | 29 -> "expected the second component of the date literal\n" + | 30 -> "expected a \"/\"\n" + | 31 -> "expected the third component of the date literal\n" + | 32 -> "expected a delimiter to finish the date literal\n" + | 57 -> "expected an operator to compose the expression on the left with\n" + | 63 -> "expected an enum constructor to test if the expression on the left\n" + | 62 -> "expected an operator to compose the expression on the left with\n" + | 118 -> "expected an expression on the right side of the sum or minus operator\n" + | 146 -> "expected an expression on the right side of the logical operator\n" + | 65 -> "expected an expression for the argument of this function call\n" + | 106 -> "expected an expression on the right side of the comparison operator\n" + | 127 -> "expected an expression on the right side of the multiplication or division operator\n" + | 120 -> "expected an operator to compose the expression on the left\n" + | 156 -> "expected an expression standing for the set you want to test for membership\n" + | 58 -> "expected an identifier standing for a struct field or a subscope name\n" + | 198 -> "expected a colon after the scope use precondition\n" + | 60 -> "expected a constructor, to get the payload of this enum case\n" + | 130 -> "expected the \"for\" keyword to spell the aggregation\n" + | 131 -> "expected an identifier for the aggregation bound variable\n" + | 132 -> "expected the \"in\" keyword\n" + | 133 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 134 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 135 -> "expected an expression to compute its aggregation over the set\n" - | 139 -> "expected an expression to take the negation of\n" - | 53 -> "expected an expression to take the opposite of\n" - | 42 -> "expected an expression to match with\n" - | 181 -> "expected a pattern matching case\n" - | 182 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 188 -> + | 135 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 136 -> "expected an expression to compute its aggregation over the set\n" + | 140 -> "expected an expression to take the negation of\n" + | 54 -> "expected an expression to take the opposite of\n" + | 43 -> "expected an expression to match with\n" + | 182 -> "expected a pattern matching case\n" + | 183 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 189 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 189 -> "expected an identifier for this enum case binding\n" - | 185 -> "expected a colon and then the expression for this matching case\n" - | 191 -> "expected a colon or a binding for the enum constructor payload\n" - | 186 -> "expected an expression for this pattern matching case\n" - | 183 -> + | 190 -> "expected an identifier for this enum case binding\n" + | 186 -> "expected a colon and then the expression for this matching case\n" + | 192 -> "expected a colon or a binding for the enum constructor payload\n" + | 187 -> "expected an expression for this pattern matching case\n" + | 184 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 180 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 43 -> "expected an expression inside the parenthesis\n" - | 178 -> "unmatched parenthesis that should have been closed by here\n" - | 65 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 45 -> "expected an expression for the test of the conditional\n" - | 174 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 175 -> + | 181 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 44 -> "expected an expression inside the parenthesis\n" + | 179 -> "unmatched parenthesis that should have been closed by here\n" + | 66 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 46 -> "expected an expression for the test of the conditional\n" + | 175 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 176 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 176 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 173 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 47 -> + | 177 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 174 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 48 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 159 -> "expected an identifier for the bound variable of the universal test\n" - | 160 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 161 -> "expected the expression designating the set on which to perform the universal test\n" - | 162 -> "expected the \"we have\" keyword for this universal test\n" - | 158 -> "expected an expression for the universal test\n" - | 167 -> "expected an identifier that will designate the existential witness for the test\n" - | 168 -> "expected the \"in\" keyword to continue this existential test\n" - | 169 -> "expected an expression that designates the set subject to the existential test\n" - | 170 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 171 -> "expected a keyword to complete the \"such that\" construction\n" - | 165 -> "expected an expression for the existential test\n" - | 74 -> + | 160 -> "expected an identifier for the bound variable of the universal test\n" + | 161 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 162 -> "expected the expression designating the set on which to perform the universal test\n" + | 163 -> "expected the \"we have\" keyword for this universal test\n" + | 159 -> "expected an expression for the universal test\n" + | 168 -> "expected an identifier that will designate the existential witness for the test\n" + | 169 -> "expected the \"in\" keyword to continue this existential test\n" + | 170 -> "expected an expression that designates the set subject to the existential test\n" + | 171 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 172 -> "expected a keyword to complete the \"such that\" construction\n" + | 166 -> "expected an expression for the existential test\n" + | 75 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 149 -> "expected an expression for the content of this enum case\n" - | 150 -> + | 150 -> "expected an expression for the content of this enum case\n" + | 151 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 52 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 198 -> "expected a scope use item: a rule, definition or assertion\n" - | 199 -> "expected the name of the variable subject to the rule\n" - | 218 -> + | 53 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 199 -> "expected a scope use item: a rule, definition or assertion\n" + | 200 -> "expected the name of the variable subject to the rule\n" + | 219 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 213 -> "expected a condition or a consequence for this rule\n" - | 204 -> "expected filled or not filled for a rule consequence\n" - | 214 -> "expected the name of the parameter for this dependent variable \n" - | 201 -> "expected the expression of the rule\n" - | 207 -> "expected the filled keyword the this rule \n" - | 219 -> "expected a struct field or a sub-scope context item after the dot\n" - | 221 -> "expected the name of the variable you want to define\n" - | 222 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 224 -> "expected an expression for the consequence of this definition under condition\n" - | 223 -> + | 214 -> "expected a condition or a consequence for this rule\n" + | 205 -> "expected filled or not filled for a rule consequence\n" + | 215 -> "expected the name of the parameter for this dependent variable \n" + | 202 -> "expected the expression of the rule\n" + | 208 -> "expected the filled keyword the this rule \n" + | 220 -> "expected a struct field or a sub-scope context item after the dot\n" + | 222 -> "expected the name of the variable you want to define\n" + | 223 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 225 -> "expected an expression for the consequence of this definition under condition\n" + | 224 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 225 -> "expected an expression for the definition\n" - | 228 -> "expected an expression that shoud be asserted during execution\n" - | 229 -> "expecting the name of the varying variable\n" - | 231 -> "the variable varies with an expression that was expected here\n" - | 232 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 230 -> "expected an indication about what this variable varies with\n" - | 202 -> "expected an expression for this condition\n" - | 210 -> "expected a consequence for this definition under condition\n" - | 241 -> "expected an expression for this definition under condition\n" - | 237 -> "expected the name of the variable that should be fixed\n" - | 238 -> "expected the legislative text by which the value of the variable is fixed\n" + | 226 -> "expected an expression for the definition\n" + | 229 -> "expected an expression that shoud be asserted during execution\n" + | 230 -> "expecting the name of the varying variable\n" + | 232 -> "the variable varies with an expression that was expected here\n" + | 233 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 231 -> "expected an indication about what this variable varies with\n" + | 203 -> "expected an expression for this condition\n" + | 211 -> "expected a consequence for this definition under condition\n" + | 242 -> "expected an expression for this definition under condition\n" + | 238 -> "expected the name of the variable that should be fixed\n" | 239 -> "expected the legislative text by which the value of the variable is fixed\n" - | 245 -> "expected a new scope use item \n" - | 248 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 249 -> "expected the struct name\n" - | 250 -> "expected a colon\n" - | 251 -> "expected struct data or condition\n" - | 252 -> "expected the name of this struct data \n" - | 253 -> "expected the type of this struct data, introduced by the content keyword\n" - | 254 -> "expected the type of this struct data\n" - | 279 -> "expected the name of this struct condition\n" - | 272 -> "expected a new struct data, or another declaration or scope use\n" - | 273 -> "expected the type of the parameter of this struct data function\n" - | 277 -> "expected a new struct data, or another declaration or scope use\n" - | 266 -> "expected a new struct data, or another declaration or scope use\n" - | 269 -> "expected a new struct data, or another declaration or scope use\n" - | 282 -> "expected the name of the scope you are declaring\n" - | 283 -> "expected a colon followed by the list of context items of this scope\n" - | 284 -> "expected a context item introduced by \"context\"\n" - | 285 -> "expected the name of this new context item\n" - | 286 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 287 -> "expected the name of the subscope for this context item\n" - | 294 -> "expected the next context item, or another declaration or scope use\n" - | 289 -> "expected the type of this context item\n" - | 290 -> "expected the next context item or a dependency declaration for this item\n" - | 292 -> "expected the next context item or a dependency declaration for this item\n" - | 297 -> "expected the name of your enum\n" - | 298 -> "expected a colon\n" - | 299 -> "expected an enum case\n" - | 300 -> "expected the name of an enum case \n" - | 301 -> "expected a payload for your enum case, or another case or declaration \n" - | 302 -> "expected a content type\n" - | 307 -> "expected another enum case, or a new declaration or scope use\n" - | 17 -> "expected a declaration or a scope use\n" - | 19 -> "expected a declaration or a scope use\n" - | 313 -> + | 240 -> "expected the legislative text by which the value of the variable is fixed\n" + | 246 -> "expected a new scope use item \n" + | 249 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 250 -> "expected the struct name\n" + | 251 -> "expected a colon\n" + | 252 -> "expected struct data or condition\n" + | 253 -> "expected the name of this struct data \n" + | 254 -> "expected the type of this struct data, introduced by the content keyword\n" + | 255 -> "expected the type of this struct data\n" + | 280 -> "expected the name of this struct condition\n" + | 273 -> "expected a new struct data, or another declaration or scope use\n" + | 274 -> "expected the type of the parameter of this struct data function\n" + | 278 -> "expected a new struct data, or another declaration or scope use\n" + | 267 -> "expected a new struct data, or another declaration or scope use\n" + | 270 -> "expected a new struct data, or another declaration or scope use\n" + | 283 -> "expected the name of the scope you are declaring\n" + | 284 -> "expected a colon followed by the list of context items of this scope\n" + | 285 -> "expected a context item introduced by \"context\"\n" + | 286 -> "expected the name of this new context item\n" + | 287 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 288 -> "expected the name of the subscope for this context item\n" + | 295 -> "expected the next context item, or another declaration or scope use\n" + | 290 -> "expected the type of this context item\n" + | 291 -> "expected the next context item or a dependency declaration for this item\n" + | 293 -> "expected the next context item or a dependency declaration for this item\n" + | 298 -> "expected the name of your enum\n" + | 299 -> "expected a colon\n" + | 300 -> "expected an enum case\n" + | 301 -> "expected the name of an enum case \n" + | 302 -> "expected a payload for your enum case, or another case or declaration \n" + | 303 -> "expected a content type\n" + | 308 -> "expected another enum case, or a new declaration or scope use\n" + | 18 -> "expected a declaration or a scope use\n" + | 20 -> "expected a declaration or a scope use\n" + | 314 -> "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" | _ -> raise Not_found diff --git a/src/catala/driver.ml b/src/catala/driver.ml index e811c027..c0d7bec3 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -46,7 +46,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ Errors.raise_error (Printf.sprintf "The selected backend (%s) is not supported by Catala" backend) in - let program = Surface.Parser_driver.parse_source_files [ source_file ] language in + let program = Surface.Parser_driver.parse_source_file source_file language in match backend with | Cli.Makefile -> let backend_extensions_list = [ ".tex" ] in diff --git a/src/catala/literate_programming/html.ml b/src/catala/literate_programming/html.ml index 74cc9bdb..68b28c83 100644 --- a/src/catala/literate_programming/html.ml +++ b/src/catala/literate_programming/html.ml @@ -150,7 +150,6 @@ let law_article_item_to_html (custom_pygments : string option) (language : C.bac Format.fprintf fmt "
\n
%s
\n%s\n
" (Pos.get_file (Pos.get_position c)) (pygmentize_code (Pos.same_pos_as ("/*" ^ pprinted_c ^ "*/") c) language custom_pygments) - | A.LawInclude _ -> () let rec law_structure_to_html (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (i : A.law_structure) : unit = @@ -164,6 +163,7 @@ let rec law_structure_to_html (custom_pygments : string option) (language : C.ba ~pp_sep:(fun fmt () -> Format.fprintf fmt "\n") (law_structure_to_html custom_pygments language) fmt children + | A.LawInclude _ -> () | A.LawArticle (a, children) -> Format.fprintf fmt "
\n\n
%s
\n" diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index aa47fe51..416dc8a8 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -135,15 +135,6 @@ let law_article_item_to_latex (language : C.backend_lang) (fmt : Format.formatte (Pos.get_start_line (Pos.get_position c)) (match language with `Fr -> "catala_fr" | `En -> "catala_en") (math_syms_replace (Pos.unmark c)) - | A.LawInclude (A.PdfFile ((file, _), page)) -> - let label = file ^ match page with None -> "" | Some p -> Format.sprintf "_page_%d," p in - Format.fprintf fmt - "\\begin{center}\\textit{Annexe incluse, retranscrite page \\pageref{%s}}\\end{center} \ - \\begin{figure}[p]\\begin{center}\\includegraphics[%swidth=\\textwidth]{%s}\\label{%s}\\end{center}\\end{figure}" - label - (match page with None -> "" | Some p -> Format.sprintf "page=%d," p) - file label - | A.LawInclude (A.CatalaFile _ | A.LegislativeText _) -> () let rec law_structure_to_latex (language : C.backend_lang) (fmt : Format.formatter) (i : A.law_structure) : unit = @@ -160,6 +151,15 @@ let rec law_structure_to_latex (language : C.backend_lang) (fmt : Format.formatt Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "\n\n") (law_structure_to_latex language) fmt children + | A.LawInclude (A.PdfFile ((file, _), page)) -> + let label = file ^ match page with None -> "" | Some p -> Format.sprintf "_page_%d," p in + Format.fprintf fmt + "\\begin{center}\\textit{Annexe incluse, retranscrite page \\pageref{%s}}\\end{center} \ + \\begin{figure}[p]\\begin{center}\\includegraphics[%swidth=\\textwidth]{%s}\\label{%s}\\end{center}\\end{figure}" + label + (match page with None -> "" | Some p -> Format.sprintf "page=%d," p) + file label + | A.LawInclude (A.CatalaFile _ | A.LegislativeText _) -> () | A.LawArticle (article, children) -> Format.fprintf fmt "\\paragraph{%s}\n\n" (pre_latexify (Pos.unmark article.law_article_name)); Format.pp_print_list From f282d9586be302e370789354aebb2ee48f3c4908 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 14 Dec 2020 10:59:15 +0100 Subject: [PATCH 082/142] Improved readmes --- CONTRIBUTING.md | 28 ++++- INSTALL.md | 62 +++++----- README.md | 109 ++++++++---------- catala.opam | 6 +- doc/{ => images}/CatalaScreenShot.png | Bin doc/{ => images}/ScreenShotVSCode.png | Bin doc/{ => images}/logo.png | Bin doc/{ => images}/logo.svg | 0 doc/{ => out_of_date}/enlish_token_list.md | 0 doc/{ => out_of_date}/motivation.tex | 0 doc/{ => out_of_date}/questionnaire.tex | 0 .../questionnaire_for_lawyers.tex | 0 doc/{ => out_of_date}/reading_guide.tex | 0 dune-project | 7 +- install_opam.sh | 3 - tests/README.md | 17 ++- 16 files changed, 130 insertions(+), 102 deletions(-) rename doc/{ => images}/CatalaScreenShot.png (100%) rename doc/{ => images}/ScreenShotVSCode.png (100%) rename doc/{ => images}/logo.png (100%) rename doc/{ => images}/logo.svg (100%) rename doc/{ => out_of_date}/enlish_token_list.md (100%) rename doc/{ => out_of_date}/motivation.tex (100%) rename doc/{ => out_of_date}/questionnaire.tex (100%) rename doc/{ => out_of_date}/questionnaire_for_lawyers.tex (100%) rename doc/{ => out_of_date}/reading_guide.tex (100%) delete mode 100755 install_opam.sh diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ff6c3ac2..d949b201 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,18 @@ # Contributing to Catala -The project is open to external contributions, in the spirit of open source. If you want to open a pull request, please follow the instructions below. +The project is open to external contributions, in the spirit of open source. +If you want to open a pull request, please follow the instructions below. -To ask a question to the Catala team, please open an issue on this repository. If you want to contribute to the project on a longer-term basis, or if you have specific competences as a socio-fiscal lawyer or a programming language specialist, please email the authors at denis.merigoux@inria.fr. The Catala team meets over visioconference once in a week. +To ask a question to the Catala team, please open an issue on this repository. +If you want to contribute to the project on a longer-term basis, or if you have +specific competences as a socio-fiscal lawyer or a programming language specialist, +please [contact the authors](mailto:contact@catala-lang.org). +The Catala team meets over visioconference once every two weeks. Please note that the copyright of this code is owned by Inria; -by contributing, you disclaim all copyright interests in favor of Inria. Both the code for the compiler and the examples in this repository are distributed under the Apache2 license. +by contributing, you disclaim all copyright interests in favor of Inria. +Both the code for the compiler and the examples in this repository are +distributed under the Apache2 license. ## Writing Catala examples @@ -99,3 +106,18 @@ Again, make sure to regularly check that your example is parsing correctly. The ## Working on the compiler The Catala compiler is a standard dune-managed OCaml project. You can look at the [online OCaml documentation](https://catala-lang.org/ocaml_docs/) for the different modules' interfaces. + +## Internationalization + +The Catala language should be adapted to any legislative text that follows a +general-to-specifics statutes order. Therefore, there exists multiple versions +of the Catala surface syntax, adapted to the language of the legislative text. + +Currently, Catala supports English and French legislative text via the +`--language=en` or `--language=fr` option. + +Technically, support for new languages can be added via a new lexer. If you want +to add a new language, you can start from +[existing lexer examples](src/catala/catala_surface/lexer_fr.ml), tweak and open +a pull request. If you don't feel familiar enough with OCaml to do so, please +leave an issue on this repository. diff --git a/INSTALL.md b/INSTALL.md index ee20fa76..3afb6f51 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,29 +1,26 @@ -# Installing the Catala compiler +# Building and installing the Catala language ## Requirements -The Catala compiler is written using OCaml. To install OCaml on your machine and -if you're running Linux ou MacOS, open a terminal and enter : +The Catala compiler is written using OCaml. First, you have to install `opam`, +OCaml's distribution and package manager. Follow the [instructions on the `opam` +website](https://opam.ocaml.org/doc/Install.html). - ./install_opam.sh - -This will install `opam`, the OCaml dependency manager and the -base OCaml compiler. If you're on Windows, the simplest solution -would be to use Cygwin or the Windows Subsystem for Linux. Catala has been tested -with OCaml version 4.09.1. You can switch to this version by typing : - - opam switch create 4.09.1 - -or +Next, you will need to use the correct version of OCaml. Catala has been tested +with OCaml compiler versions that are at least 4.09.1. To switch to OCaml 4.09.1., +just use: opam switch 4.09.1 -if this version of OCaml is already installed. Next, install all the build -dependencies with +If you get a `No switch 4.09.1 is currently installed` error message, follow +the hint and enter `opam switch create 4.09.1`. + +Next, install all the OCaml packages that Catala depend on, as well as some +git submodules, with make install-dependencies -This should ensure everything is set up for developping on the Catala compiler ! +This should ensure everything is set up for developping on the Catala compiler! Other features for generation of files and literate programming also require the following executables to be present @@ -41,7 +38,7 @@ On ArchLinux : sudo pacman -S python-virtualenv man2html rsync -## Installation +## Build The project is distributed as a Dune artifact. Use standard dune commands to build and install the library. Makefile aliases are here to help you: running @@ -50,12 +47,27 @@ and install the library. Makefile aliases are here to help you: running builds the compiler from its OCaml sources. +## Install + +The installation of the Catala compiler is handled through `opam`. Since the +Catala compiler is not yet published to the `opam` repository, you can install +a local version from this Git repository by using + + opam install ./ + +To uninstall, use + + opam unpin catala ### Generating website assets The Catala website features assets generated by the Catala compiler. They are -needed to build the website. To produce them, simply run from this repository's -root directory +needed to build the website. To produce them, simply run + + make website-assets + +Then, use a helper script to copy them over to the `assets` directory of the +Catala website. ./generate_website_assets.sh /assets @@ -63,15 +75,6 @@ You will need the `man2html` executable to generate the HTML versions of the man pages, as well as the `rsync` executable to transfer files (preferred to `cp`) because it also works with a remote server. -### Opam package - -If you want to install the library as an opam -package, use the following command at the root of the repository: - - opam install ./ - -You can then use the compiler with the `catala` command. - ## Usage Use `catala --help` to get more information about the command line options available. @@ -119,7 +122,8 @@ augmented with the Catala plugin, simply enter make pygments This will execute the -script `syntax_highlighting/fr/pygments/set_up_pygments.sh` and `syntax_highlighting/en/pygments/set_up_pygments.sh`. +script `syntax_highlighting/fr/pygments/set_up_pygments.sh` and +`syntax_highlighting/en/pygments/set_up_pygments.sh`. The scripts set up a virtual environement in `syntax_highlighting/fr/pygments/pygments/env` or diff --git a/README.md b/README.md index 2729ece6..02661c79 100644 --- a/README.md +++ b/README.md @@ -1,27 +1,30 @@
-Catala logo +Catala logo
# Catala Catala is a domain-specific language for deriving -faithful-by-construction algorithms from legislative texts. +faithful-by-construction algorithms from legislative texts. To learn quickly +about the language and its features, you can jump right to the official +[Catala tutorial](https://catala-lang.org/en/examples/tutorial). ## Concepts -Catala is a programming language adapted for socio-fiscal legislative literate programming. By annotating each line of the -legislative text with its meaning in terms of code, one can derive -an implementation of complex socio-fiscal mechanisms that enjoys -a high level of assurance regarding the code-law faithfulness. +Catala is a programming language adapted for socio-fiscal legislative literate +programming. By annotating each line of the legislative text with its meaning +in terms of code, one can derive an implementation of complex socio-fiscal +mechanisms that enjoys a high level of assurance regarding the code-law +faithfulness. -Concretely, you have to first gather all the laws, executive orders, previous cases, etc. that contain information about the -socio-fiscal mechanism that you want to implement. Then, you can -proceed to annotate the text article by article, in your favorite -text editor : +Concretely, you have to first gather all the laws, executive orders, previous +cases, etc. that contain information about the socio-fiscal mechanism that +you want to implement. Then, you can proceed to annotate the text article by +article, in your favorite text editor :
-Screenshot +Screenshot
Once your code is complete and tested, you can use the Catala @@ -32,72 +35,58 @@ can be reviewed and certified correct by the domain experts, which are in this case lawyers and not programmers.
-Screenshot +Screenshot
The Catala language is special because its logical structure mimics the logical structure of the law. Indeed, the core concept of -"definition-under-conditions" that builds on default logic has been formalized by Professor of Law Sarah Lawsky in her article [A Logic for Statutes](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3088206). The Catala language is the only -programming language to our knowledge that embeds default logic -as a first-class feature, which is why it is the only language -perfectly adapted to literate legislative programming. - - -## Catala motivating example : French "allocations familiales" - -In the `example/allocations_familiales` folder, you will find the -`allocations_familiales.catala` file which contains the -algorithm computing French family benefits. The algorithm consists of annotations to the legislative -texts that define the family benetifs, using the literate programming paradigm. The Catala -compiler can extract from the `.catala` file a lawyer-readable version of the annotated text. - -Currently, this lawyer-readable version comes in the form of a LaTeX document. -You will need to have a standard LaTeX distribution installed as well as the -`latexmk` build tool in order to enjoy the automated document generation process. - -To get that lawyer-readable version (which is a LaTeX-created) PDF, simply use - - make -C allocations_familiales allocations_familiales.pdf - -from the repository root, once you have managed to install the -compiler using [the dedicated readme](INSTALL.md). You can then open `examples/allocations_familiales/allocations_familiales.pdf` - -## Languages - -The Catala language should be adapted to any legislative text that follows a general-to-specifics statutes order. Therefore, there exists multiple versions of the Catala surface syntax, adapted to the language of the lefislative text. - -Currently, Catala supports English and French legislations via the `--language=en` or `--language=fr` option. Contact the authors -if you are interested in adding support for another language. - -## Limitations and disclaimer - -### Early stage project - -Catala is a research project from Inria, the French National -Research Institute for Computer Science. The compiler is yet very -unstable and lacks most of its features. Currently, it only -parses the surface language to producde the lawyer-readable PDF, -no interpreter or compiler backend is provided. - -However, the language is bound to have a complete formal semantics -in the near future. This semantics will guide the compiler -implementation. +"definition-under-conditions" that builds on default logic has been formalized +by Professor of Law Sarah Lawsky in her article +[A Logic for Statutes](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3088206). +The Catala language is the only programming language to our knowledge that +embeds default logic as a first-class feature, which is why it is the only +language perfectly adapted to literate legislative programming. ## Installation See [the dedicated readme](INSTALL.md). -## Test suite +## Examples -See [the dedicated readme](tests/README.md). +See [the dedicated readme](examples/README.md). ## Contributing See [the dedicated readme](CONTRIBUTING.md). +## Test suite + +See [the dedicated readme](tests/README.md). + +## Documentation + +### Formal semantics + +See [the dedicated readme](doc/formalization/README.md). + +### Compiler documentation + +See [the dedicated readme](src/README.md). + ## License -The library is released under the Apache license (version 2). +The library is released under the [Apache license (version 2)](LICENSE.txt). + +## Limitations and disclaimer + +Catala is a research project from Inria, the French National +Research Institute for Computer Science. The compiler is yet +unstable and lacks some of its features. Currently, here is the list +of existing features: + +* Literate programming output to HTML or LaTeX +* Typechecker and interpreter for most of the language + ## Pierre Catala diff --git a/catala.opam b/catala.opam index 99a58642..1bdedd02 100644 --- a/catala.opam +++ b/catala.opam @@ -6,7 +6,7 @@ description: """ The Catala language is designed to be a low-level target for higher-level specification languages for fiscal legislation. """ -maintainer: ["denis.merigoux@inria.fr"] +maintainer: ["contact@catala-lang.org"] authors: ["Denis Merigoux"] license: "Apache2" homepage: "https://github.com/CatalaLang/catala" @@ -17,11 +17,15 @@ depends: [ "sedlex" {>= "2.1"} "menhir" {>= "20200211"} "menhirLib" {>= "20200211"} + "unionfind" {>= "20200320"} + "bindlib" {>= "5.0.1"} "dune-build-info" {>= "2.0.1"} "cmdliner" {>= "1.0.4"} "re" {>= "1.9.0"} + "zarith" {>= "1.10"} "dune" {build} "ocamlgraph" {>= "1.8.8"} + "odate" {>= "0.6"} ] build: [ ["dune" "subst"] {pinned} diff --git a/doc/CatalaScreenShot.png b/doc/images/CatalaScreenShot.png similarity index 100% rename from doc/CatalaScreenShot.png rename to doc/images/CatalaScreenShot.png diff --git a/doc/ScreenShotVSCode.png b/doc/images/ScreenShotVSCode.png similarity index 100% rename from doc/ScreenShotVSCode.png rename to doc/images/ScreenShotVSCode.png diff --git a/doc/logo.png b/doc/images/logo.png similarity index 100% rename from doc/logo.png rename to doc/images/logo.png diff --git a/doc/logo.svg b/doc/images/logo.svg similarity index 100% rename from doc/logo.svg rename to doc/images/logo.svg diff --git a/doc/enlish_token_list.md b/doc/out_of_date/enlish_token_list.md similarity index 100% rename from doc/enlish_token_list.md rename to doc/out_of_date/enlish_token_list.md diff --git a/doc/motivation.tex b/doc/out_of_date/motivation.tex similarity index 100% rename from doc/motivation.tex rename to doc/out_of_date/motivation.tex diff --git a/doc/questionnaire.tex b/doc/out_of_date/questionnaire.tex similarity index 100% rename from doc/questionnaire.tex rename to doc/out_of_date/questionnaire.tex diff --git a/doc/questionnaire_for_lawyers.tex b/doc/out_of_date/questionnaire_for_lawyers.tex similarity index 100% rename from doc/questionnaire_for_lawyers.tex rename to doc/out_of_date/questionnaire_for_lawyers.tex diff --git a/doc/reading_guide.tex b/doc/out_of_date/reading_guide.tex similarity index 100% rename from doc/reading_guide.tex rename to doc/out_of_date/reading_guide.tex diff --git a/dune-project b/dune-project index 1c7ab125..c6665207 100644 --- a/dune-project +++ b/dune-project @@ -8,7 +8,7 @@ (homepage https://github.com/CatalaLang/catala) (bug_reports https://github.com/CatalaLang/catala/issues) (authors "Denis Merigoux") -(maintainers "denis.merigoux@inria.fr") +(maintainers "contact@catala-lang.org") (license Apache2) @@ -24,13 +24,16 @@ (sedlex (>= 2.1)) (menhir (>= 20200211)) (menhirLib (>= 20200211)) + (unionfind (>= 20200320)) + (bindlib (>= 5.0.1)) (dune-build-info (>= 2.0.1)) (cmdliner (>= 1.0.4)) (re (>= 1.9.0)) + (zarith (>= 1.10)) (dune (and :build )) (ocamlgraph (>= 1.8.8)) + (odate (>= 0.6)) ) ) - (using menhir 2.1) diff --git a/install_opam.sh b/install_opam.sh deleted file mode 100755 index 364c0593..00000000 --- a/install_opam.sh +++ /dev/null @@ -1,3 +0,0 @@ -#! /usr/bin/env bash - -sh <(curl -sL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh) diff --git a/tests/README.md b/tests/README.md index ffdf81b4..e833c60a 100644 --- a/tests/README.md +++ b/tests/README.md @@ -1,10 +1,14 @@ # Catala test suite -This folder contains Catala source files designed to test the features of the language. +This folder contains Catala source files designed to test the features of the +language. -It uses `make` to launch tests and compare the test terminal output with an expected output. +It uses `make pass_tests` to launch tests and compare the test terminal output +with an expected output. -When you create a new test, please register it in the `Makefile` following the other examples. Expected outputs are stored using the convention `.catala..out` in the corresponding test folder. +When you create a new test, please register it in the `Makefile` following the +other examples. Expected outputs are stored using the convention +`.catala..out` in the corresponding test folder. For both workflows: use `CATALA_OPTS="..." make ...` to pass in Catala compiler options when debugging. @@ -33,4 +37,9 @@ options when debugging. `make foo/bar.catala.A.in`. 5. Re-reun `make` to check that everything passes. 6. That's it, you've fixed the Catala test suite to adapt for changes in the - language. \ No newline at end of file + language. + +If a compiler change causes a lot of regressions (error message formatting changes +for instance), you can mass-reset the expected the outputs with `make reset_tests`. +**Caution**: use at your own risk, regressions should be fixed one by one in +general. \ No newline at end of file From d5fc383dd22f94b27711228b64202442a1a4b211 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 14 Dec 2020 15:23:04 +0100 Subject: [PATCH 083/142] Added ocamldoc, doc'ed Surface --- src/catala/catala_surface/ast.ml | 2 + src/catala/catala_surface/desugaring.ml | 62 +++++--- src/catala/catala_surface/dune | 3 +- src/catala/catala_surface/lexer.ml | 17 +++ src/catala/catala_surface/lexer_en.ml | 4 + src/catala/catala_surface/lexer_fr.ml | 6 + src/catala/catala_surface/name_resolution.ml | 150 ++++++++++--------- src/catala/catala_surface/parser_driver.ml | 30 +++- src/catala/catala_surface/surface.mld | 73 +++++++++ src/catala/default_calculus/dcalc.mld | 1 + src/catala/desugared/desugared.mld | 1 + src/catala/desugared/dune | 3 +- src/catala/index.mld | 66 ++++++++ src/catala/scope_language/dune | 3 +- src/catala/scope_language/scopelang.mld | 1 + src/legifrance_catala.ml | 15 -- 16 files changed, 321 insertions(+), 116 deletions(-) create mode 100644 src/catala/catala_surface/surface.mld create mode 100644 src/catala/default_calculus/dcalc.mld create mode 100644 src/catala/desugared/desugared.mld create mode 100644 src/catala/index.mld create mode 100644 src/catala/scope_language/scopelang.mld delete mode 100644 src/legifrance_catala.ml diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 8dac14b3..425d7e39 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -12,6 +12,8 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Abstract syntax tree built by the Catala parser *) + module Pos = Utils.Pos type constructor = string diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 767e4b41..67cf28ec 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -12,12 +12,16 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Translation from {!module: Surface.Ast} to {!module: Desugaring.Ast}. + + - Removes syntactic sugars + - Separate code from legislation *) + module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli -(** The optional argument subdef allows to choose between differents uids in case the expression is - a redefinition of a subvariable *) +(** {1 Translating expressions} *) let translate_op_kind (k : Ast.op_kind) : Dcalc.Ast.op_kind = match k with @@ -45,14 +49,22 @@ let translate_binop (op : Ast.binop) : Dcalc.Ast.binop = let translate_unop (op : Ast.unop) : Dcalc.Ast.unop = match op with Not -> Not | Minus l -> Minus (translate_op_kind l) +(** The two modules below help performing operations on map with the {!type: Bindlib.box}. Indeed, + Catala uses the {{:https://lepigre.fr/ocaml-bindlib/} Bindlib} library to represent bound + variables in the AST. In this translation, bound variables are used to represent function + parameters or pattern macthing bindings. *) + module LiftStructFieldMap = Bindlib.Lift (Scopelang.Ast.StructFieldMap) module LiftEnumConstructorMap = Bindlib.Lift (Scopelang.Ast.EnumConstructorMap) -let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) - (def_key : Desugared.Ast.ScopeDef.t option) (ctxt : Name_resolution.context) +(** Usage: [translate_expr scope ctxt expr] + + Translates [expr] into its desugared equivalent. [scope] is used to disambiguate the scope and + subscopes variables than occur in the expresion *) +let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) ((expr, pos) : Ast.expression Pos.marked) : Scopelang.Ast.expr Pos.marked Bindlib.box = let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in - let rec_helper = translate_expr scope def_key ctxt in + let rec_helper = translate_expr scope ctxt in match expr with | IfThenElse (e_if, e_then, e_else) -> Bindlib.box_apply3 @@ -147,7 +159,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) pos ) | _ -> (* In this case e.x is the struct field x access of expression e *) - let e = translate_expr scope def_key ctxt e in + let e = translate_expr scope ctxt e in let x_possible_structs = try Desugared.Ast.IdentMap.find (Pos.unmark x) ctxt.field_idmap with Not_found -> @@ -200,7 +212,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) Scopelang.Ast.StructFieldName.format_t f_uid) [ (None, Pos.get_position f_e); (None, Pos.get_position (Bindlib.unbox e_field)) ] ); - let f_e = translate_expr scope def_key ctxt f_e in + let f_e = translate_expr scope ctxt f_e in Scopelang.Ast.StructFieldMap.add f_uid f_e s_fields) Scopelang.Ast.StructFieldMap.empty fields in @@ -228,7 +240,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (Pos.get_position constructor) else let e_uid, c_uid = Scopelang.Ast.EnumMap.choose possible_c_uids in - let payload = Option.map (translate_expr scope def_key ctxt) payload in + let payload = Option.map (translate_expr scope ctxt) payload in Bindlib.box_apply (fun payload -> ( Scopelang.Ast.EEnumInj @@ -240,7 +252,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) pos )) (Bindlib.box_opt payload) | MatchWith (e1, (cases, _cases_pos)) -> - let e1 = translate_expr scope def_key ctxt e1 in + let e1 = translate_expr scope ctxt e1 in let cases_d, e_uid = List.fold_left (fun (cases_d, e_uid) (case, pos_case) -> @@ -295,7 +307,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) let ctxt, param_var = Name_resolution.add_def_local_var ctxt param in (ctxt, (param_var, Pos.get_position param)) in - let case_body = translate_expr scope def_key ctxt case.Ast.match_case_expr in + let case_body = translate_expr scope ctxt case.Ast.match_case_expr in let e_binder = Bindlib.bind_mvar (Array.of_list [ param_var ]) case_body in let case_expr = Bindlib.box_apply2 @@ -327,8 +339,11 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented for this expression" pos -(* Translation from the parsed ast to the scope language *) +(** {1 Translating scope definitions} *) +(** A scope use can be annotated with a pervasive precondition, in which case this precondition has + to be appended to the justifications of each definition in the subscope use. This is what this + function does. *) let merge_conditions (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (cond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (default_pos : Pos.t) : Scopelang.Ast.expr Pos.marked Bindlib.box = @@ -344,18 +359,15 @@ let merge_conditions (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option | Some cond, None | None, Some cond -> cond | None, None -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), default_pos) +(** Translates a surface definition into condition into a desugared {!type: Desugared.Ast.rule} *) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t Pos.marked option) (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (just : Ast.expression Pos.marked option) (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = - let just = - match just with - | Some just -> Some (translate_expr scope (Some def_key) ctxt just) - | None -> None - in + let just = match just with Some just -> Some (translate_expr scope ctxt just) | None -> None in let just = merge_conditions precond just (Pos.get_position cons) in - let cons = translate_expr scope (Some def_key) ctxt cons in + let cons = translate_expr scope ctxt cons in { just; cons; @@ -376,7 +388,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); } -(* Process a definition *) +(** Wrapper around {!val: process_default} that performs some name disambiguation *) let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (def : Ast.definition) : Desugared.Ast.program = @@ -435,7 +447,7 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) program_scopes = Scopelang.Ast.ScopeMap.add scope_uid scope_updated prgm.program_scopes; } -(** Process a rule from the surface language *) +(** Translates a {!type: Surface.Ast.rule} from the surface language *) let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (rule : Ast.rule) : Desugared.Ast.program = @@ -450,13 +462,13 @@ let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) in process_def precond scope ctxt prgm def -(** Process an assertion from the surface language *) +(** Translates assertions *) let process_assert (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (ass : Ast.assertion) : Desugared.Ast.program = let scope : Desugared.Ast.scope = Scopelang.Ast.ScopeMap.find scope_uid prgm.program_scopes in let ass = - translate_expr scope_uid None ctxt + translate_expr scope_uid ctxt ( match ass.Ast.assertion_condition with | None -> ass.Ast.assertion_content | Some cond -> @@ -478,16 +490,20 @@ let process_assert (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) let new_scope = { scope with scope_assertions = ass :: scope.scope_assertions } in { prgm with program_scopes = Scopelang.Ast.ScopeMap.add scope_uid new_scope prgm.program_scopes } +(** Translates a surface definition, rule or assertion *) let process_scope_use_item (precond : Ast.expression Pos.marked option) (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (item : Ast.scope_use_item Pos.marked) : Desugared.Ast.program = - let precond = Option.map (translate_expr scope None ctxt) precond in + let precond = Option.map (translate_expr scope ctxt) precond in match Pos.unmark item with | Ast.Rule rule -> process_rule precond scope ctxt prgm rule | Ast.Definition def -> process_def precond scope ctxt prgm def | Ast.Assertion ass -> process_assert precond scope ctxt prgm ass | _ -> prgm +(** {1 Translating top-level items} *) + +(** Translates a surface scope use, which is a bunch of definitions *) let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.program) (use : Ast.scope_use) : Desugared.Ast.program = let name = fst use.scope_use_name in @@ -502,7 +518,7 @@ let process_scope_use (ctxt : Name_resolution.context) (prgm : Desugared.Ast.pro let precond = use.scope_use_condition in List.fold_left (process_scope_use_item precond scope_uid ctxt) prgm use.scope_use_items -(** Scopes processing *) +(** Main function of this module *) let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desugared.Ast.program = let empty_prgm = { diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index ac5827ac..af62d0bd 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -10,4 +10,5 @@ (flags --table)) (documentation - (package catala)) + (package catala) + (mld_files surface)) diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 7e6fe031..5c40eddc 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -12,23 +12,34 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Concise syntax with English abbreviated keywords. *) + open Parser open Sedlexing module Pos = Utils.Pos module Errors = Utils.Errors module R = Re.Pcre +(** Boolean reference, used by the lexer as the mutable state to distinguish whether it is lexing + code or law. *) let is_code : bool ref = ref false +(** Mutable string reference that accumulates the string representation of the body of code being + lexed. This string representation is used in the literate programming backends to faithfully + capture the spacing pattern of the original program *) let code_string_acc : string ref = ref "" +(** Updates {!val:code_string_acc} with the current lexeme *) let update_acc (lexbuf : lexbuf) : unit = code_string_acc := !code_string_acc ^ Utf8.lexeme lexbuf +(** Error-generating helper *) let raise_lexer_error (loc : Pos.t) (token : string) = Errors.raise_spanned_error (Printf.sprintf "Parsing error after token \"%s\": what comes after is unknown" token) loc +(** Associative list matching each punctuation string part of the Catala syntax with its {!module: + Surface.Parser} token. Same for all the input languages (English, French, etc.) *) let token_list_language_agnostic : (string * token) list = [ ("->", ARROW); @@ -51,6 +62,8 @@ let token_list_language_agnostic : (string * token) list = ("--", ALT); ] +(** Same as {!val: token_list_language_agnostic}, but with tokens whose string varies with the input + language. *) let token_list : (string * token) list = [ ("scope", SCOPE); @@ -109,6 +122,7 @@ let token_list : (string * token) list = ] @ token_list_language_agnostic +(** Main lexing function used in a code block *) let rec lex_code (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in @@ -468,6 +482,7 @@ let rec lex_code (lexbuf : lexbuf) : token = INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> raise_lexer_error prev_pos prev_lexeme +(** Main lexing function used outside code blocks *) let lex_law (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in @@ -527,4 +542,6 @@ let lex_law (lexbuf : lexbuf) : token = | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) | _ -> raise_lexer_error prev_pos prev_lexeme +(** Entry point of the lexer, distributes to {!val: lex_code} or {!val: lex_law} depending of {!val: + is_code}. *) let lexer lexbuf = if !is_code then lex_code lexbuf else lex_law lexbuf diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 7c57cb5e..bb092b31 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -19,6 +19,8 @@ module Errors = Utils.Errors module L = Lexer module R = Re.Pcre +(** Same as {!val: Surface.Lexer.token_list_language_agnostic}, but with tokens specialized to + English. *) let token_list_en : (string * token) list = [ ("scope", SCOPE); @@ -77,6 +79,7 @@ let token_list_en : (string * token) list = ] @ L.token_list_language_agnostic +(** Main lexing function used in code blocks *) let rec lex_code_en (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in @@ -436,6 +439,7 @@ let rec lex_code_en (lexbuf : lexbuf) : token = INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error prev_pos prev_lexeme +(** Main lexing function used outside code blocks *) let lex_law_en (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 0d018440..76760c9e 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -19,6 +19,8 @@ module Errors = Utils.Errors module L = Lexer module R = Re.Pcre +(** Same as {!val: Surface.Lexer.token_list_language_agnostic}, but with tokens specialized to + French. *) let token_list_fr : (string * token) list = [ ("champ d'application", SCOPE); @@ -77,6 +79,7 @@ let token_list_fr : (string * token) list = ] @ L.token_list_language_agnostic +(** Main lexing function used in code blocks *) let rec lex_code_fr (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in @@ -445,6 +448,7 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = INT_LITERAL (Z.of_string (Utf8.lexeme lexbuf)) | _ -> L.raise_lexer_error prev_pos prev_lexeme +(** Main lexing function used outside code blocks *) let lex_law_fr (lexbuf : lexbuf) : token = let prev_lexeme = Utf8.lexeme lexbuf in let prev_pos = lexing_positions lexbuf in @@ -519,5 +523,7 @@ let lex_law_fr (lexbuf : lexbuf) : token = | Plus (Compl ('@' | '/')) -> LAW_TEXT (Utf8.lexeme lexbuf) | _ -> L.raise_lexer_error prev_pos prev_lexeme +(** Entry point of the lexer, distributes to {!val: lex_code_fr} or {!val: lex_law_fr} depending of + {!val: Surface.Lexer.is_code}. *) let lexer_fr (lexbuf : lexbuf) : token = if !L.is_code then lex_code_fr lexbuf else lex_law_fr lexbuf diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 2a2632d4..1f6a8f14 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -18,50 +18,106 @@ module Pos = Utils.Pos module Errors = Utils.Errors +(** {1 Name resolution context} *) + type ident = string type typ = Scopelang.Ast.typ -(** Inside a definition, local variables can be introduced by functions arguments or pattern - matching *) - type scope_context = { - var_idmap : Scopelang.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; + var_idmap : Scopelang.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; (** Scope variables *) sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Desugared.Ast.IdentMap.t; + (** Sub-scopes variables *) sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; + (** To what scope sub-scopes refer to? *) } (** Inside a scope, we distinguish between the variables and the subscopes. *) type struct_context = typ Pos.marked Scopelang.Ast.StructFieldMap.t +(** Types of the fields of a struct *) type enum_context = typ Pos.marked Scopelang.Ast.EnumConstructorMap.t +(** Types of the payloads of the cases of an enum *) type context = { local_var_idmap : Scopelang.Ast.Var.t Desugared.Ast.IdentMap.t; - scope_idmap : Scopelang.Ast.ScopeName.t Desugared.Ast.IdentMap.t; - scopes : scope_context Scopelang.Ast.ScopeMap.t; - structs : struct_context Scopelang.Ast.StructMap.t; + (** Inside a definition, local variables can be introduced by functions arguments or pattern + matching *) + scope_idmap : Scopelang.Ast.ScopeName.t Desugared.Ast.IdentMap.t; (** The names of the scopes *) struct_idmap : Scopelang.Ast.StructName.t Desugared.Ast.IdentMap.t; + (** The names of the structs *) field_idmap : Scopelang.Ast.StructFieldName.t Scopelang.Ast.StructMap.t Desugared.Ast.IdentMap.t; - enums : enum_context Scopelang.Ast.EnumMap.t; - enum_idmap : Scopelang.Ast.EnumName.t Desugared.Ast.IdentMap.t; + (** The names of the struct fields. Names of fields can be shared between different structs *) + enum_idmap : Scopelang.Ast.EnumName.t Desugared.Ast.IdentMap.t; (** The names of the enums *) constructor_idmap : Scopelang.Ast.EnumConstructor.t Scopelang.Ast.EnumMap.t Desugared.Ast.IdentMap.t; + (** The names of the enum constructors. Constructor names can be shared between different + enums *) + scopes : scope_context Scopelang.Ast.ScopeMap.t; (** For each scope, its context *) + structs : struct_context Scopelang.Ast.StructMap.t; (** For each struct, its context *) + enums : enum_context Scopelang.Ast.EnumMap.t; (** For each enum, its context *) var_typs : typ Pos.marked Scopelang.Ast.ScopeVarMap.t; + (** The types of each scope variable declared *) } +(** Main context used throughout {!module: Surface.Desugaring} *) +(** {1 Helpers} *) + +(** Temporary function raising an error message saying that a feature is not supported yet *) let raise_unsupported_feature (msg : string) (pos : Pos.t) = Errors.raise_spanned_error (Printf.sprintf "Unsupported feature: %s" msg) pos +(** Function to call whenever an identifier used somewhere has not been declared in the program + previously *) let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = Errors.raise_spanned_error (Printf.sprintf "%s: unknown identifier %s" (Pos.unmark ident) msg) (Pos.get_position ident) -(** Get the type associated to an uid *) +(** Gets the type associated to an uid *) let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ Pos.marked = Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs +(** Get the variable uid inside the scope given in argument *) +let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) + ((x, pos) : ident Pos.marked) : Scopelang.Ast.ScopeVar.t = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + match Desugared.Ast.IdentMap.find_opt x scope.var_idmap with + | None -> raise_unknown_identifier "for a var of this scope" (x, pos) + | Some uid -> uid + +(** Get the subscope uid inside the scope given in argument *) +let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) + ((y, pos) : ident Pos.marked) : Scopelang.Ast.SubScopeName.t = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + match Desugared.Ast.IdentMap.find_opt y scope.sub_scopes_idmap with + | None -> raise_unknown_identifier "for a subscope of this scope" (y, pos) + | Some sub_uid -> sub_uid + +(** [is_subscope_uid scope_uid ctxt y] returns true if [y] belongs to the subscopes of [scope_uid]. *) +let is_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) (y : ident) : bool = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + Desugared.Ast.IdentMap.mem y scope.sub_scopes_idmap + +(** Checks if the var_uid belongs to the scope scope_uid *) +let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) + (scope_uid : Scopelang.Ast.ScopeName.t) : bool = + let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in + Desugared.Ast.IdentMap.exists + (fun _ var_uid -> Scopelang.Ast.ScopeVar.compare uid var_uid = 0) + scope.var_idmap + +(** Retrieves the type of a scope definition from the context *) +let get_def_typ (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : typ Pos.marked = + match def with + | Desugared.Ast.ScopeDef.SubScopeVar (_, x) + (* we don't need to look at the subscope prefix because [x] is already the uid referring back to + the original subscope *) + | Desugared.Ast.ScopeDef.Var x -> + Scopelang.Ast.ScopeVarMap.find x ctxt.var_typs + +(** {1 Declarations pass} *) + (** Process a subscope declaration *) let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Ast.scope_decl_context_scope) : context = @@ -93,6 +149,7 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } +(** Process a basic type (all types except function types) *) let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : Scopelang.Ast.typ Pos.marked = match typ with @@ -118,6 +175,7 @@ let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) Errors.raise_spanned_error "Unknown type, not a struct or enum previously declared" typ_pos ) ) ) +(** Process a type (function or not) *) let process_type (ctxt : context) ((typ, typ_pos) : Ast.typ Pos.marked) : Scopelang.Ast.typ Pos.marked = match typ with @@ -201,28 +259,7 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = (fun ctxt item -> process_item_decl scope_uid ctxt (Pos.unmark item)) ctxt decl.scope_decl_context -let qident_to_scope_def (ctxt : context) (scope_uid : Scopelang.Ast.ScopeName.t) - (id : Ast.qident Pos.marked) : Desugared.Ast.ScopeDef.t = - let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - match Pos.unmark id with - | [ x ] -> ( - match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) scope_ctxt.var_idmap with - | None -> raise_unknown_identifier "for a var of the scope" x - | Some id -> Desugared.Ast.ScopeDef.Var id ) - | [ s; x ] when Desugared.Ast.IdentMap.mem (Pos.unmark s) scope_ctxt.sub_scopes_idmap -> ( - let sub_scope_uid = Desugared.Ast.IdentMap.find (Pos.unmark s) scope_ctxt.sub_scopes_idmap in - let real_sub_scope_uid = Scopelang.Ast.SubScopeMap.find sub_scope_uid scope_ctxt.sub_scopes in - let sub_scope_ctx = Scopelang.Ast.ScopeMap.find real_sub_scope_uid ctxt.scopes in - match Desugared.Ast.IdentMap.find_opt (Pos.unmark x) sub_scope_ctx.var_idmap with - | None -> raise_unknown_identifier "for a var of this subscope" x - | Some id -> Desugared.Ast.ScopeDef.SubScopeVar (sub_scope_uid, id) ) - | [ s; _ ] -> - Errors.raise_spanned_error "This identifier should refer to a subscope, but does not" - (Pos.get_position s) - | _ -> - Errors.raise_spanned_error "Only scope vars or subscope vars can be defined" - (Pos.get_position id) - +(** Process a struct declaration *) let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = let s_uid = Scopelang.Ast.StructName.fresh sdecl.struct_decl_name in let ctxt = @@ -267,6 +304,7 @@ let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context = }) ctxt sdecl.struct_decl_fields +(** Process an enum declaration *) let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = let e_uid = Scopelang.Ast.EnumName.fresh edecl.enum_decl_name in let ctxt = @@ -309,7 +347,7 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context = }) ctxt edecl.enum_decl_cases -(** Process a code item : for now it only handles scope decls *) +(** Process a code item that is a declaration *) let process_decl_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = match Pos.unmark item with | ScopeDecl decl -> process_scope_decl ctxt decl @@ -322,12 +360,12 @@ let process_code_block (ctxt : context) (block : Ast.code_block) (process_item : context -> Ast.code_item Pos.marked -> context) : context = List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block -(** Process a program item *) +(** Process a law article item, only considering the code blocks *) let process_law_article_item (ctxt : context) (item : Ast.law_article_item) (process_item : context -> Ast.code_item Pos.marked -> context) : context = match item with CodeBlock (block, _) -> process_code_block ctxt block process_item | _ -> ctxt -(** Process a law structure *) +(** Process a law structure, only considering the code blocks *) let rec process_law_structure (ctxt : context) (s : Ast.law_structure) (process_item : context -> Ast.code_item Pos.marked -> context) : context = match s with @@ -340,12 +378,14 @@ let rec process_law_structure (ctxt : context) (s : Ast.law_structure) | Ast.MetadataBlock (b, c) -> process_law_article_item ctxt (Ast.CodeBlock (b, c)) process_item | Ast.IntermediateText _ | Ast.LawInclude _ -> ctxt -(** Process a program item *) +(** Process a program item, only considering the code blocks *) let process_program_item (ctxt : context) (item : Ast.program_item) (process_item : context -> Ast.code_item Pos.marked -> context) : context = match item with Ast.LawStructure s -> process_law_structure ctxt s process_item -(** Derive the context from metadata, in two passes *) +(** {1 API} *) + +(** Derive the context from metadata, in one pass over the declarations *) let form_context (prgm : Ast.program) : context = let empty_ctxt = { @@ -367,39 +407,3 @@ let form_context (prgm : Ast.program) : context = empty_ctxt prgm.program_items in ctxt - -(** Get the variable uid inside the scope given in argument *) -let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) - ((x, pos) : ident Pos.marked) : Scopelang.Ast.ScopeVar.t = - let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - match Desugared.Ast.IdentMap.find_opt x scope.var_idmap with - | None -> raise_unknown_identifier "for a var of this scope" (x, pos) - | Some uid -> uid - -(** Get the subscope uid inside the scope given in argument *) -let get_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) - ((y, pos) : ident Pos.marked) : Scopelang.Ast.SubScopeName.t = - let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - match Desugared.Ast.IdentMap.find_opt y scope.sub_scopes_idmap with - | None -> raise_unknown_identifier "for a subscope of this scope" (y, pos) - | Some sub_uid -> sub_uid - -let is_subscope_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) (y : ident) : bool = - let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - Desugared.Ast.IdentMap.mem y scope.sub_scopes_idmap - -(** Checks if the var_uid belongs to the scope scope_uid *) -let belongs_to (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) - (scope_uid : Scopelang.Ast.ScopeName.t) : bool = - let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in - Desugared.Ast.IdentMap.exists - (fun _ var_uid -> Scopelang.Ast.ScopeVar.compare uid var_uid = 0) - scope.var_idmap - -let get_def_typ (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : typ Pos.marked = - match def with - | Desugared.Ast.ScopeDef.SubScopeVar (_, x) - (* we don't need to look at the subscope prefix because [x] is already the uid referring back to - the original subscope *) - | Desugared.Ast.ScopeDef.Var x -> - Scopelang.Ast.ScopeVarMap.find x ctxt.var_typs diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index 708bcc8a..a72b6578 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -12,20 +12,27 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Wrapping module around parser and lexer that offers the {!val: parse_source_file} API *) + open Sedlexing module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli module I = Parser.MenhirInterpreter +(** {1 Internal functions} *) + +(** Returns the state number from the Menhir environment *) let state (env : 'semantic_value I.env) : int = match Lazy.force (I.stack env) with | MenhirLib.General.Nil -> 0 | MenhirLib.General.Cons (Element (s, _, _, _), _) -> I.number s -(** Computes the levenshtein distance between two strings *) +(** Three-way minimum *) let minimum a b c = min a (min b c) +(** Computes the levenshtein distance between two strings, used to provide error messages + suggestions *) let levenshtein_distance (s : string) (t : string) : int = let m = String.length s and n = String.length t in (* for all i and j, d.(i).(j) will hold the Levenshtein distance between the first i characters of @@ -53,8 +60,14 @@ let levenshtein_distance (s : string) (t : string) : int = d.(m).(n) +(** Style with which to display syntax hints in the terminal output *) let syntax_hints_style = [ ANSITerminal.yellow ] +(** Usage: [raise_parser_error error_loc last_good_loc token msg] + + Raises an error message featuring the [error_loc] position where the parser has failed, the + [token] on which the parser has failed, and the error message [msg]. If available, displays + [last_good_loc] the location of the last token correctly parsed. *) let raise_parser_error (error_loc : Pos.t) (last_good_loc : Pos.t option) (token : string) (msg : string) : 'a = Errors.raise_multispanned_error @@ -67,6 +80,13 @@ let raise_parser_error (error_loc : Pos.t) (last_good_loc : Pos.t option) (token | None -> [] | Some last_good_loc -> [ (Some "Last good token:", last_good_loc) ] ) ) +(** Usage: [fail lexbuf env token_list last_input_needed] + + Raises an error with meaningful hints about what the parsing error was. [lexbuf] is the lexing + buffer state at the failure point, [env] is the Menhir environment and [last_input_needed] is + the last checkpoint of a valid Menhir state before the parsing error. [token_list] is provided + by things like {!val: Surface.Lexer.token_list_language_agnostic} and is used to provide + suggestions of the tokens acceptable at the failure point *) let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * Parser.token) list) (last_input_needed : 'semantic_value I.env option) : 'a = let wrong_token = Utf8.lexeme lexbuf in @@ -98,7 +118,6 @@ let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * if levx = levy then String.length x - String.length y else levx - levy) acceptable_tokens in - let similar_token_msg = if List.length similar_acceptable_tokens = 0 then None else @@ -126,6 +145,7 @@ let fail (lexbuf : lexbuf) (env : 'semantic_value I.env) (token_list : (string * in raise_parser_error (lexing_positions lexbuf) last_positions (Utf8.lexeme lexbuf) msg +(** Main parsing loop *) let rec loop (next_token : unit -> Parser.token * Lexing.position * Lexing.position) (token_list : (string * Parser.token) list) (lexbuf : lexbuf) (last_input_needed : 'semantic_value I.env option) (checkpoint : 'semantic_value I.checkpoint) : @@ -144,6 +164,8 @@ let rec loop (next_token : unit -> Parser.token * Lexing.position * Lexing.posit (* Cannot happen as we stop at syntax error immediatly *) assert false +(** Stub that wraps the parsing main loop and handles the Menhir/Sedlex type difference for + [lexbuf]. *) let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * Parser.token) list) (target_rule : Lexing.position -> 'semantic_value I.checkpoint) (lexbuf : lexbuf) : Ast.source_file_or_master = @@ -154,6 +176,9 @@ let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * with Sedlexing.MalFormed | Sedlexing.InvalidCodepoint _ -> Lexer.raise_lexer_error (lexing_positions lexbuf) (Utf8.lexeme lexbuf) +(** {1 API} *) + +(** Parses a single source file *) let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) : Ast.program = Cli.debug_print (Printf.sprintf "Parsing %s" source_file); let input = try open_in source_file with Sys_error msg -> Errors.raise_error msg in @@ -206,6 +231,7 @@ let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) in { new_program with program_source_files = source_file :: new_program.program_source_files } +(** Expands the include directives in a parsing result, thus parsing new source files *) and expand_includes (source_file : string) (commands : Ast.program_item list) (language : Cli.frontend_lang) : Ast.program = List.fold_left diff --git a/src/catala/catala_surface/surface.mld b/src/catala/catala_surface/surface.mld new file mode 100644 index 00000000..fca041ae --- /dev/null +++ b/src/catala/catala_surface/surface.mld @@ -0,0 +1,73 @@ +{0 Catala surface representation } + +This representation is the first in the compilation chain +(see {{: index.html#architecture} Architecture}). Its purpose is to +host the output of the Catala parser, before any transformations have been made. + +The module describing the abstract syntax tree is: + +{!modules: Surface.Ast} + +{1 Lexing } + +Relevant modules: + +{!modules: Surface.Lexer Surface.Lexer_fr Surface.Lexer_en} + +The lexing in the Catala compiler is done using +{{: https://github.com/ocaml-community/sedlex} sedlex}, the modern OCaml lexer +that offers full support for UTF-8. This support enables users of non-English +languages to use their favorite diacritics and symbols in their code. + +While the parser of Catala is unique, three different lexers can be used to +produce the parser tokens. + +{ul +{li {!module: Surface.Lexer} corresponds to a concise and programming-language-like + syntax for Catala. Examples of this syntax can be found in the test suite + of the compiler.} +{li {!module: Surface.Lexer_en} is the adaptation of {!module: Surface.Lexer} + with verbose English keywords matching legal concepts.} +{li {!module: Surface.Lexer_fr} is the adaptation of {!module: Surface.Lexer} + with verbose French keywords matching legal concepts.} +} + +{1 Parsing } + +Relevant modules: + +{!modules: Surface.Parser Surface.Parser_driver Surface.Parser_errors} + +The Catala compiler uses {{: http://cambium.inria.fr/~fpottier/menhir/} Menhir} +to perform its parsing. + +{!module: Surface.Parser} is the main file where the parser tokens and the +grammar is declared. It is automatically translated into its parsing automata +equivalent by Menhir. + +In order to provide decent syntax error messages, the Catala compiler uses the +novel error handling provided by Menhir and detailed in Section 11 of the +{{: http://cambium.inria.fr/~fpottier/menhir/manual.pdf} Menhir manual}. + +A [parser.messages] source file has been manually annotated with custom +error message for every potential erroneous state of the parser, and Menhir +automatically generated the {!module: Surface.Parser_errors} module containing +the function linking the erroneous parser states to the custom error message. + +To wrap it up, {!module: Surface.Parser_driver} glues all the parsing and +lexing together to perform the translation from source code to abstract syntax +tree, with meaningful error messages. + +{1 Name resolution and translation } + +Relevant modules: + +{!modules: Surface.Name_resolution Surface.Desugaring} + +The desugaring consists of translating {!module: Surface.Ast} to +{!module: Desugared.Ast}. The translation is implemented in +{!module: Surface.Desugaring}, but it relies on a helper module to perform the +name resolution: {!module: Surface.Name_resolution}. Indeed, in +{!module: Surface.Ast}, the variables identifiers are just [string], whereas in +{!module: Desugared.Ast} they have been turned into well-categorized types +with an unique identifier like {!type: Scopelang.Ast.ScopeName.t}. diff --git a/src/catala/default_calculus/dcalc.mld b/src/catala/default_calculus/dcalc.mld new file mode 100644 index 00000000..9c7bf6da --- /dev/null +++ b/src/catala/default_calculus/dcalc.mld @@ -0,0 +1 @@ +{0 Default calculus} \ No newline at end of file diff --git a/src/catala/desugared/desugared.mld b/src/catala/desugared/desugared.mld new file mode 100644 index 00000000..e18187a2 --- /dev/null +++ b/src/catala/desugared/desugared.mld @@ -0,0 +1 @@ +{0 Desugared representation } \ No newline at end of file diff --git a/src/catala/desugared/dune b/src/catala/desugared/dune index 18e8eb47..9d5fb83f 100644 --- a/src/catala/desugared/dune +++ b/src/catala/desugared/dune @@ -4,4 +4,5 @@ (libraries utils dcalc scopelang ocamlgraph)) (documentation - (package catala)) + (package catala) + (mld_files desugared)) diff --git a/src/catala/index.mld b/src/catala/index.mld new file mode 100644 index 00000000..25a82ab9 --- /dev/null +++ b/src/catala/index.mld @@ -0,0 +1,66 @@ +{0 The Catala compiler} + +{1 Architecture} + +The architecture of the Catala compiler is inspired by +{{: https://compcert.org/} CompCert} or the {{: https://nanopass.org/} Nanopass} +framework, and is structured around many intermediate representations connected +by successive translations passes. + +Here is the recap picture of the different intermediate representations of the +Catala compiler (made with an {{: https://textik.com/#c1c1fecda5209492} ASCII diagram tool}): + +{v + +---------------+ + | | + | Surface AST | + | | + +---------------+ + | + * Separate code from legislation | + * Remove syntactic sugars | + v + +---------------+ + | | + | Desugared AST | + | | + +---------------+ + | + * Build rule trees for each definition | + * Order variable computations inside scope | + v + +--------------------+ + | | + | Scope language AST | + | | + +--------------------+ + | + * Convert scopes into functions | + * Thunking of subscope arguments | + | + v + +----------------------+ + | | + | Default calculus AST | + | | + +----------------------+ v} + +{1 List of top-level modules } + +Each of those intermediate representation is bundled into its own `dune` bundle +module. Click on the items below if you want to dive straight into the signatures. + +{!modules: Surface Desugared Scopelang Dcalc } + +More documentation can be found on each intermediate representations here. + +{ul +{li {{: surface.html} The surface representation}} +{li {{: desugared.html} The desugared representation}} +{li {{: scopelang.html} The scope language }} +{li {{: dcalc.html} The default calculus}} +} + +Last, two more modules contain additional features for the compiler: + +{!modules: Utils Literate } \ No newline at end of file diff --git a/src/catala/scope_language/dune b/src/catala/scope_language/dune index 4e462492..79e59dc1 100644 --- a/src/catala/scope_language/dune +++ b/src/catala/scope_language/dune @@ -4,4 +4,5 @@ (libraries utils dcalc ocamlgraph)) (documentation - (package catala)) + (package catala) + (mld_files scopelang)) diff --git a/src/catala/scope_language/scopelang.mld b/src/catala/scope_language/scopelang.mld new file mode 100644 index 00000000..71f5c721 --- /dev/null +++ b/src/catala/scope_language/scopelang.mld @@ -0,0 +1 @@ +{0 The scope language } \ No newline at end of file diff --git a/src/legifrance_catala.ml b/src/legifrance_catala.ml deleted file mode 100644 index f88d5b5a..00000000 --- a/src/legifrance_catala.ml +++ /dev/null @@ -1,15 +0,0 @@ -(* This file is part of the Catala compiler, a specification language for tax and social benefits - computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux - - - Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - in compliance with the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software distributed under the License - is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express - or implied. See the License for the specific language governing permissions and limitations under - the License. *) - -let _ = Legifrance_catala.Main.main () From 6eabdb1356fbf662f1f4ed0305e34e06b9d57b8d Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 14 Dec 2020 17:00:42 +0100 Subject: [PATCH 084/142] Doc'ed Scopelang --- src/catala/catala_surface/ast.ml | 12 ++- src/catala/catala_surface/surface.mld | 3 +- src/catala/desugared/ast.ml | 20 +++-- src/catala/desugared/dependency.ml | 24 ++++-- src/catala/desugared/desugared.mld | 31 +++++++- src/catala/desugared/desugared_to_scope.ml | 24 +++++- src/catala/scope_language/ast.ml | 91 ++++++++++++---------- src/catala/scope_language/scopelang.mld | 35 ++++++++- 8 files changed, 179 insertions(+), 61 deletions(-) diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 425d7e39..74d2e97d 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -17,8 +17,10 @@ module Pos = Utils.Pos type constructor = string +(** Constructors are CamlCase *) type ident = string +(** Idents are snake_case *) type qident = ident Pos.marked list @@ -65,7 +67,12 @@ type enum_decl = { type match_case_pattern = constructor Pos.marked list * ident Pos.marked option -type op_kind = KInt | KDec | KMoney | KDate | KDuration +type op_kind = + | KInt (** No suffix *) + | KDec (** Suffix: [.] *) + | KMoney (** Suffix: [$] *) + | KDate (** Suffix: [@] *) + | KDuration (** Suffix: [^] *) type binop = | And @@ -131,8 +138,7 @@ and expression = | StructLit of constructor Pos.marked * (ident Pos.marked * expression Pos.marked) list | Ident of ident | Dotted of expression Pos.marked * ident Pos.marked - -(* Dotted is for both struct field projection and sub-scope variables *) + (** Dotted is for both struct field projection and sub-scope variables *) type rule = { rule_parameter : ident Pos.marked option; diff --git a/src/catala/catala_surface/surface.mld b/src/catala/catala_surface/surface.mld index fca041ae..394f656e 100644 --- a/src/catala/catala_surface/surface.mld +++ b/src/catala/catala_surface/surface.mld @@ -65,7 +65,8 @@ Relevant modules: {!modules: Surface.Name_resolution Surface.Desugaring} The desugaring consists of translating {!module: Surface.Ast} to -{!module: Desugared.Ast}. The translation is implemented in +{!module: Desugared.Ast} of the {{: desugared.html} desugared representation}. +The translation is implemented in {!module: Surface.Desugaring}, but it relies on a helper module to perform the name resolution: {!module: Surface.Name_resolution}. Indeed, in {!module: Surface.Ast}, the variables identifiers are just [string], whereas in diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index ba50e072..2941b0dc 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -12,13 +12,18 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Abstract syntax tree of the desugared representation *) + module Pos = Utils.Pos module Uid = Utils.Uid -module IdentMap = Map.Make (String) -module RuleName = Uid.Make (Uid.MarkedString) () +(** {1 Names, Maps and Keys} *) -module RuleMap = Map.Make (RuleName) +module IdentMap : Map.S with type key = String.t = Map.Make (String) + +module RuleName : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid.MarkedString) () + +module RuleMap : Map.S with type key = RuleName.t = Map.Make (RuleName) (** Inside a scope, a definition can refer either to a scope def, or a subscope def *) module ScopeDef = struct @@ -47,10 +52,11 @@ module ScopeDef = struct | SubScopeVar (_, v) -> Scopelang.Ast.ScopeVar.hash v end -module ScopeDefMap = Map.Make (ScopeDef) -module ScopeDefSet = Set.Make (ScopeDef) +module ScopeDefMap : Map.S with type key = ScopeDef.t = Map.Make (ScopeDef) -(* Scopes *) +module ScopeDefSet : Set.S with type elt = ScopeDef.t = Set.Make (ScopeDef) + +(** {1 AST} *) type rule = { just : Scopelang.Ast.expr Pos.marked Bindlib.box; @@ -95,6 +101,8 @@ type program = { program_structs : Scopelang.Ast.struct_ctx; } +(** {1 Helpers} *) + let free_variables (def : rule RuleMap.t) : Pos.t ScopeDefMap.t = let add_locs (acc : Pos.t ScopeDefMap.t) (locs : Scopelang.Ast.LocationSet.t) : Pos.t ScopeDefMap.t = diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index 7c5eea1b..b1295594 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -12,18 +12,21 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Scope dependencies computations using {{:http://ocamlgraph.lri.fr/} OCamlgraph} *) + module Pos = Utils.Pos module Errors = Utils.Errors -(** The vertices of the scope dependency graph are either : +(** {1 Graph declaration} *) + +(** Vertices: scope variables or subscopes. + + The vertices of the scope dependency graph are either : - the variables of the scope ; - the subscopes of the scope. - Indeed, during interpretation, subscopes are executed atomically. - - In the graph, x -> y if x is used in the definition of y. *) - + Indeed, during interpretation, subscopes are executed atomically. *) module Vertex = struct type t = Var of Scopelang.Ast.ScopeVar.t | SubScope of Scopelang.Ast.SubScopeName.t @@ -46,7 +49,8 @@ module Vertex = struct | SubScope v -> Scopelang.Ast.SubScopeName.format_t fmt v end -(** On the edges, the label is the expression responsible for the use of the variable *) +(** On the edges, the label is the position of the expression responsible for the use of the + variable. In the graph, [x -> y] if [x] is used in the definition of [y].*) module Edge = struct type t = Pos.t @@ -56,11 +60,18 @@ module Edge = struct end module ScopeDependencies = Graph.Persistent.Digraph.ConcreteBidirectionalLabeled (Vertex) (Edge) +(** Module of the graph, provided by OCamlGraph *) + module TopologicalTraversal = Graph.Topological.Make (ScopeDependencies) +(** Module of the topological traversal of the graph, provided by OCamlGraph *) module SCC = Graph.Components.Make (ScopeDependencies) (** Tarjan's stongly connected components algorithm, provided by OCamlGraph *) +(** {1 Graph computations} *) + +(** Returns an ordering of the scope variables and subscope compatible with the dependencies of the + computation *) let correct_computation_ordering (g : ScopeDependencies.t) : Vertex.t list = List.rev (TopologicalTraversal.fold (fun sd acc -> sd :: acc) g []) @@ -99,6 +110,7 @@ let check_for_cycle (scope : Ast.scope) (g : ScopeDependencies.t) : unit = ]) scc)) +(** Builds the dependency graph of a particular scope *) let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = let g = ScopeDependencies.empty in (* Add all the vertices to the graph *) diff --git a/src/catala/desugared/desugared.mld b/src/catala/desugared/desugared.mld index e18187a2..c5d617b7 100644 --- a/src/catala/desugared/desugared.mld +++ b/src/catala/desugared/desugared.mld @@ -1 +1,30 @@ -{0 Desugared representation } \ No newline at end of file +{0 Desugared representation } + +This representation is the second in the compilation chain +(see {{: index.html#architecture} Architecture}). Its main difference +with {{: surface.html} the surface representation} is that the legislative +text has been discarded and all the definitions of each variables have been +collected in the same place rather than being scattered across the code base. + +The module describing the abstract syntax tree is: + +{!modules: Desugared.Ast} + +{1 Translation to the scope language} + +Related modules: + +{!modules: Desugared.Dependency Desugared.Desugared_to_scope} + +Before the translation to the {{: scopelang.html} scope language}, +{!module: Desugared.Dependency} checks that within +a scope, there is no computational circular dependency between the variables +of the scope. When the dependency graph is a DAG, +{!module: Desugared.Desugared_to_scope} performs a topological ordering to +produce an ordered list of the scope definitions compatible with the +computation order. All the graph computations are done using the +{{:http://ocamlgraph.lri.fr/} Ocamlgraph} library. + +The other important piece of work performed by +{!module: Desugared.Desugared_to_scope} is the construction of the default trees +(see {!constructor: Dcalc.Ast.EDefault}) from the list of prioritized rules. \ No newline at end of file diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 970ac996..60e16ebb 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -12,14 +12,22 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Translation from {!module: Desugared.Ast} to {!module: Scopelang.Ast} *) + module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli +(** {1 Rule tree construction} *) + type rule_tree = Leaf of Ast.rule | Node of Ast.rule * rule_tree list -(* invariant: one rule in def does not have any parent rule *) -(* invariant: there are no dandling pointer parents in the rules *) +(** Transforms a flat list of rules into a tree, taking into account the priorities declared between + rules + + {e Invariant:} only one rule does not have any parent rule + + {e Invariant:} there are no dandling pointer parents in the rules *) let rec def_map_to_tree (def : Ast.rule Ast.RuleMap.t) : rule_tree = (* first we look to the only rule that does not have any parent *) let has_no_parent _ (r : Ast.rule) = Option.is_none r.Ast.parent_rule in @@ -47,6 +55,9 @@ let rec def_map_to_tree (def : Ast.rule Ast.RuleMap.t) : rule_tree = in Node (no_parent, tree_children) +(** From the {!type: rule_tree}, builds an {!constructor: Dcalc.Ast.EDefault} expression in the + scope language. The [~toplevel] parameter is used to know when to place the toplevel binding in + the case of functions. *) let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t option) (tree : rule_tree) : Scopelang.Ast.expr Pos.marked Bindlib.box = let rule, children = match tree with Leaf r -> (r, []) | Node (r, child) -> (r, child) in @@ -79,10 +90,12 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti if toplevel then Scopelang.Ast.make_abs (Array.of_list [ new_param ]) default Pos.no_pos [ typ ] Pos.no_pos else default - | _ -> assert false + | _ -> (* should not happen *) assert false -(* should not happen *) +(** {1 AST translation} *) +(** Translates a definition inside a scope, the resulting expression should be an {!constructor: + Dcalc.Ast.EDefault} *) let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) (typ : Scopelang.Ast.typ Pos.marked) : Scopelang.Ast.expr Pos.marked = (* Here, we have to transform this list of rules into a default tree. *) @@ -132,6 +145,7 @@ let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) (Option.map (fun _ -> Scopelang.Ast.Var.make ("ρ", Pos.no_pos)) is_def_func) def_tree) +(** Translates a scope *) let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = let scope_dependencies = Dependency.build_scope_dependencies scope in Dependency.check_for_cycle scope scope_dependencies; @@ -213,6 +227,8 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = Scopelang.Ast.scope_sig; } +(** {1 API} *) + let translate_program (pgrm : Ast.program) : Scopelang.Ast.program = { Scopelang.Ast.program_scopes = Scopelang.Ast.ScopeMap.map translate_scope pgrm.program_scopes; diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 90ffafc9..b219f074 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -12,45 +12,54 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Abstract syntax tree of the scope language *) + module Pos = Utils.Pos module Uid = Utils.Uid -module ScopeName = Uid.Make (Uid.MarkedString) () +(** {1 Identifiers} *) -module ScopeNameSet = Set.Make (ScopeName) -module ScopeMap = Map.Make (ScopeName) +module ScopeName : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid.MarkedString) () -module SubScopeName = Uid.Make (Uid.MarkedString) () +module ScopeNameSet : Set.S with type elt = ScopeName.t = Set.Make (ScopeName) -module SubScopeNameSet = Set.Make (SubScopeName) -module SubScopeMap = Map.Make (SubScopeName) +module ScopeMap : Map.S with type key = ScopeName.t = Map.Make (ScopeName) -module ScopeVar = Uid.Make (Uid.MarkedString) () +module SubScopeName : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid.MarkedString) () -module ScopeVarSet = Set.Make (ScopeVar) -module ScopeVarMap = Map.Make (ScopeVar) +module SubScopeNameSet : Set.S with type elt = SubScopeName.t = Set.Make (SubScopeName) -module StructName = Uid.Make (Uid.MarkedString) () +module SubScopeMap : Map.S with type key = SubScopeName.t = Map.Make (SubScopeName) -module StructMap = Map.Make (StructName) +module ScopeVar : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid.MarkedString) () -module StructFieldName = Uid.Make (Uid.MarkedString) () +module ScopeVarSet : Set.S with type elt = ScopeVar.t = Set.Make (ScopeVar) -module StructFieldMap = Map.Make (StructFieldName) +module ScopeVarMap : Map.S with type key = ScopeVar.t = Map.Make (ScopeVar) -module EnumName = Uid.Make (Uid.MarkedString) () +module StructName : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid.MarkedString) () -module EnumMap = Map.Make (EnumName) +module StructMap : Map.S with type key = StructName.t = Map.Make (StructName) -module EnumConstructor = Uid.Make (Uid.MarkedString) () +module StructFieldName : Uid.Id with type info = Uid.MarkedString.info = + Uid.Make (Uid.MarkedString) () -module EnumConstructorMap = Map.Make (EnumConstructor) +module StructFieldMap : Map.S with type key = StructFieldName.t = Map.Make (StructFieldName) + +module EnumName : 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 EnumConstructor : Uid.Id with type info = Uid.MarkedString.info = + Uid.Make (Uid.MarkedString) () + +module EnumConstructorMap : Map.S with type key = EnumConstructor.t = Map.Make (EnumConstructor) type location = | ScopeVar of ScopeVar.t Pos.marked | SubScopeVar of ScopeName.t * SubScopeName.t Pos.marked * ScopeVar.t Pos.marked -module LocationSet = Set.Make (struct +module LocationSet : Set.S with type elt = location Pos.marked = Set.Make (struct type t = location Pos.marked let compare x y = @@ -64,6 +73,8 @@ module LocationSet = Set.Make (struct | SubScopeVar _, ScopeVar _ -> 1 end) +(** {1 Abstract syntax tree} *) + type typ = | TLit of Dcalc.Ast.typ_lit | TStruct of StructName.t @@ -114,6 +125,29 @@ let rec locations_used (e : expr Pos.marked) : LocationSet.t = (LocationSet.union (locations_used just) (locations_used cons)) subs +type rule = + | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked + | Assertion of expr Pos.marked + | Call of ScopeName.t * SubScopeName.t + +type scope_decl = { + scope_decl_name : ScopeName.t; + scope_sig : typ Pos.marked ScopeVarMap.t; + scope_decl_rules : rule list; +} + +type struct_ctx = (StructFieldName.t * typ Pos.marked) list StructMap.t + +type enum_ctx = (EnumConstructor.t * typ Pos.marked) list EnumMap.t + +type program = { + program_scopes : scope_decl ScopeMap.t; + program_enums : enum_ctx; + program_structs : struct_ctx; +} + +(** {1 Variable helpers} *) + module Var = struct type t = expr Bindlib.var @@ -139,24 +173,3 @@ let make_app (e : expr Pos.marked Bindlib.box) (u : expr Pos.marked Bindlib.box Bindlib.box_apply2 (fun e u -> (EApp (e, u), pos)) e (Bindlib.box_list u) module VarMap = Map.Make (Var) - -type rule = - | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked - | Assertion of expr Pos.marked - | Call of ScopeName.t * SubScopeName.t - -type scope_decl = { - scope_decl_name : ScopeName.t; - scope_sig : typ Pos.marked ScopeVarMap.t; - scope_decl_rules : rule list; -} - -type struct_ctx = (StructFieldName.t * typ Pos.marked) list StructMap.t - -type enum_ctx = (EnumConstructor.t * typ Pos.marked) list EnumMap.t - -type program = { - program_scopes : scope_decl ScopeMap.t; - program_enums : enum_ctx; - program_structs : struct_ctx; -} diff --git a/src/catala/scope_language/scopelang.mld b/src/catala/scope_language/scopelang.mld index 71f5c721..addaf813 100644 --- a/src/catala/scope_language/scopelang.mld +++ b/src/catala/scope_language/scopelang.mld @@ -1 +1,34 @@ -{0 The scope language } \ No newline at end of file +{0 The scope language } + +This representation is the second in the compilation chain +(see {{: index.html#architecture} Architecture}). Its main difference +with the previous {{: desugared.html} desugared representation} is that inside +a scope, the definitions are ordered according to their computational +dependency order, and each definition is a {!constructor: Dcalc.Ast.EDefault} tree +instead of a flat list of rules. + +The module describing the abstract syntax tree is: + +{!modules: Scopelang.Ast} + +Printing helpers can be found in {!module: Scopelang.Print}. + +{1 Translation to the default calculus} + +Related modules: + +{!modules: Scopelang.Dependency Scopelang.Scope_to_dcalc} + +The translation from the scope language to the +{{: dcalc.html} default calculus} involves three big features: + +{ol +{li Translating structures and enums into simpler sum and product types} +{li Build thunked signatures for the scopes as functions } +{li Transform the list of scopes into a program} +} + +1 and 3 involve computing dependency graphs for respectively the structs and +enums on one hand, and the inter-scope dependencies on the other hand. Both +can be found in {!module: Scopelang.Dependency}, while +{!module: Scopelang.Scope_to_dcalc} is mostly responsible for 2. \ No newline at end of file From ef38a6f5beb89d5b328810556dd4f8b8b4b032cf Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 14 Dec 2020 17:12:12 +0100 Subject: [PATCH 085/142] Added compiled formalization pdf --- doc/formalization/formalization.pdf | Bin 0 -> 358913 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/formalization/formalization.pdf diff --git a/doc/formalization/formalization.pdf b/doc/formalization/formalization.pdf new file mode 100644 index 0000000000000000000000000000000000000000..5e418d71bde9ee3069ae9991d10e1f6728c4c1af GIT binary patch literal 358913 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%0Asm4G;YYU2+@*)ecu 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 z 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

EZ*zkr1$VaR5D~PbrxN6M5g-j-2y4)Q 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≫ z1?u*ZimG>s<}F#adf7?H;_BqmfD11(g>jsKJq^rQ8_kdx12u93v6IA9&M)OZy3Y@1 z>B@@bJiUU>UROU%&$8!w!&{(EJRlUK&yZrGq`v8T@s!C6iU+ztfXPhvaug>q=iD`< zi|3ir{nHl6|8-B)rf*6rmRlYsc`EHaolwoF<9k4qJtQab(D@76*?ucu;egZ*zMRtA z)1whGC`+2=WgoV?10=*m#_sO2{iH)r`BOEH^jWd#I;{q&>U@b)QYh-0814uyNssgL zK^|3ja+t7Dg>E1=cfKj`4cI$Wf}&=W%*_5+8B-y3yXYbwx)<1_3yTjvRiz)wzLNdj zV?4^O)iOkD?z0)0P54O+^OTfcr$f3KDfSR<`U6*^PkrKF8fJ{CpS^F7>w0-!tZ4N` z`5{mU3f-_@W>@j8k6~VF@POLHVD;D;R}0%h=n#m*UE%;?Mi)GFr&)8Fd62p{7S|X( zX>#b?<~Kw7&pJ)dsg)dz>KHXq1AaADT!=@r)`~7#cy;Ae=*Pbha8n-^?*byS&5ol( z1(?xbU!2NyM4^bfkJxh&A3M;4s;$dJJXsDs5W}k*G#e2I&joSNs_uqVT&J z(piT@VPsiId~1yxl$aN>q51fO6s}ihu|%Zqeq~L+)s%qkJk=b?*Qb67a#X>=&kA4= z`x@0L1;qb@Qv1(!GA}o>L=&Hd75OE`1~NXm2Y@F)H}5lufv*p*fBUT}QBRyF>6gDX zxm))_6()NK*v4$$n2S1+9cilVkX-upAm|0$O&n3S($4J9)JM^G5wqnMQUO>>FIax<-DVslYBN*(Hpv@z0fuQh^ zCDm$TVzbTKK^`N@A;2AQ(`A%&wK-xJB!Og}+K2WlD>Ni?9*?^wU#G22XY;bMt;_^b zehAHvr8}97N|hRXpe=xAs&}h7-TuL589klWc=F?Nw>x(H-K*1x;Ww~n@s2gw!L0$X z+fnxyTaNSc5Rj<}&|paw%k7^5UXodIUPqyW-9c7z3yrkGK%8nE4oz_G{v16fGxVq) zHZ7SLP9_ubVJ~LM49q`BvkALzgsHaR5i9M;* z%*ur^PPhNTq~iV`Oe$tBHrD?@sQxjj*g4qP{m949pGZCYN z?Jrj|F*6efQ!^L=0T>roXR}{+FrHhj-DX<4+uavLv%|n6aD^ZM@YI{U!RIldb572Qxt%2hvF~&e>$`(P zQ!9I5fNDruK0vWdaFYZM2)i(R zkpqMhs1@*v`lz}Za57Ewl}z;toI{wpJ|5mp9v~v7vO2q)3|~l2OIRKcXsHlXs=B87 z`&|umv-g3s0+gz<_x%&cfoL| zb0e#761pAeTmN9b80dsfUdVl}P*57>HGtP{ztmUOyCvi&VC_< z6QGRQ6wt%UkIP6{xE;`dwJM&r@IGi zo`j*7l8>mbUYzbh%*Pw-0p#&{AsTt#8ZHE1LPt+L|BFbqofW;cz17#`F7ZKHka?P; zVB|xIIQGN3zUKaF?{4t3Zf|a7Vf`xUrHTnD;l?W~iJ92C@gvrsl?bq7g$x3g14<+X zI;8tvpj}-Y+?iL)ldAL8&ppOv@r>Oa{Qt=9za57 zt`JyN2K{EYu+IUzWVl*(J97iP6Ogl?`8E9_NGkNQE>Y&cT~_|;&OrdAnuv{363qYh z4@d?0*|hjsl^q%#lK{4aE&gzj{^3Qiw6QvVAWZr}FM|FUPLmnjo5ZkuG8B-tfR^=0 ztV$-|7&&tI_0ujJ66DarXlr2)>aCmFFLxEto-(_=)0fAe9uUs}#LtR59`L>=u{5%U zaB>4@^vMhVOfejQ?7s{^)CVfb>@MyMX1o2#%IY5)xs|(-r@x&6rn|udDojCL0FAn| zL(8~0Rx;<^*`Zs4sm>d;Ge4UrGn*?hPa_;2d|&=%x~D5;JlkU;q3HshlI?4 z&S0Jg%nzYyP&?U9kaJ(&Esu&9CgFY-j@92#eW9ph(D zgk2N?1)c%7jUC)?m;jd@AR!`;MChfV++Jvh#?|%k1!Kd9ohTG782j)N7Cd13EUwJ3 zl_(AozNQ;_mP8{1p_Bj|v;5v%w1hqfl|cO<3~{FR*=cJRw5-vQE)*e`u@YaX{E?NzPmofyV}9}_`T9=hj#Y||UGAL1-o2GY~c2(`KZ zI2Y3N6!`E@J{)1*!!I#jvbPrk+E>;_UC)2b?1c~2TqIoXaDu{&-NgKRaKe+ zz4(gcei}LQrq&lf!;4iWRegy*#pUX-`eCSeZ+{($dfZ7JlWxS5P5=Q7SMOy4s|e0S zpu3-G^nSO*Q<&Fr;0o+CYJFJ>nXQy;NL_-8MfS-7dXrA5Usx=#Fpiwf z41(cz*M+Zr$$7%rNpys0$Wbg3zB<+C>Mlu~Rbib2LD#slGpkFbV);krfMus{!npk3 zl1Ty5^fD;k$KC+){`qi4hrjOha;H|q>h*f)3u@b2=l`I{x;>%cL^^ck5dCApd|w7^ zzw`)dW#qkVrE-MDeJ4qZ-5gl5EZC5DqXG|mY-m?liE>m#*7WRm$zr`IV~p~q-0q3OrFGx2u9mY_*1=7A z_THdc)Ttk#LTRN^K6YWf%3J7#EvW!yjLQv04t2Y)&%Xx{$vSFt;|`k@80(9%K%(Kw&)+z2xu3 z)F-V_j^Jaeb448`mHCH<<7^aLV^OOUeKhU(#Yyd5HKcm9*khJS(C>mQI6eMIyvm+F z1MEf@uwthgJkxDRbYsa66Yxv95cVDoDt|p`#?xX>=vK4%bOsy zU;O#p!5Ftj94RM?ig9FLMp=BQrLcIefyi(_W5k8>OhPV!;o%ipbL>p(tW4f~zsEuN z2&X%45-_*>BV&LXAs23aisP3^TKG?fTDTjXeT>@7Y<0S&105gg2-?p&DkIF>+!X(O zM=z&wMe)=Zm_g><#?2@FO)A(+VUbtJtW5sdJ2HfOST#bcA1sQ8)Cu+wNNsM1APGW~ z%9~neahYmgc6Sr85rQPe(9~&?Vi=Qwjq>Toug!&7nl@8tam4w(`=;10sZjyQmZ98&|%twT*@?gs$_a3F$B*4w-5x?`YcYU?$6Vtj+ zfPTIu&^EPwg|-1}j@=z{ff>51(x~KRVY#Ss_+;kPh)gG#k!hN^&}7Sa@2;zbPAGb1 znVZdBO>>tqYSVyJ+w2Kj^Z!_SR&Oq9xd&R4oWAOo!jis?DsK=RRi(VbwxuIq_C4WP za*J`~D4)!43lM3|ZNB{Jt+0YW9tQx`v6C!SE%j2Yl@gEx&lBfs&av2Woc%>tdASKU zIv zgT1ZJFR^$8*CN6BZq^ek{CN6*R}wfK3VKpN_vgsJ%0@$=%O(vj$qNTOha@VET*ldZ zL58q=A|2-{4{wghXfL@g^o(~`NPmm?Ua;v#Eg~ZR=#zCa93JKJ(mvA2^3>p;h-pWP{`YjVtlMViCHsEk zVPR{9ne=r;pLJ?InhqUdGb2vxFfha7NC;zCUs!jU7vZbK8({?9eZLvX1v3WIWlv&@ zq=SWS&HI}3;LBbNAa)e3>u;;RL6{LxhfqKRM_}0=InJMO#t{{>e8yFeB8&LRB$}?- zXNv9IRQ)ny7}mCKKd6M&NY7G|9qP0x*7(bJod@+=b~(Bra`sFaRT^?dwAsq(&e+Z< zgPQ(06|_0eD&f1_+h^f3EAS4%8GKI;^p(*pidYvR2OpdqSM zbwhA)99Ohp&O_lpnDtzN#Uhe;?gPMgcXC~$dR7}gF6qVrBZv5_dOLoh0P%;D?Bo*5 z*5&gz0A2yptuCssWbk?l169?CiOBIzg<_nOgJ8yiy;27|t z9b>-){MSgAmIK$K{OF(Ym@}hiHv_5(U}Z{AYN;(dx`r)wU1L#Ngs~C^(;s~%x$)q5 zQ|QpePl}GJp_%{DpTy^!4NhOyfA!hTaltdhKX?u{L8A<4%HAo}MKiGqKE}xG$hW+r zV#(zfNv)g(wN?d~H)9f>SSSKI7YuX+DtqNSvM`#3A)!ZMu1U8KS1Q2kC5DFB#!RjK z^swFwRUyvCUR&)f;3_S*4~td>-M+HP2xI!okpIXI-gD1~!kMt4Au00ZyAZ_^YdpkArkw7uG_kc;fnkcjNOCHkObm`&7j)80j6~ZuJFXhp=O$ z6#o}^Q!agDos^_?1z!Cgp#{91@m<)*N9`;Z55@F&u@Bwl4sVc|q2)_{b6g`S6YvJ1 z8%}@0_r){A;)LlTYQFP7llK{mNx@rsg}|+(B9xDWKiPlTxVWlO@3^5JHFy6&5B84x zwm?!du41$S(deusSFPB~@OI{ebx)OyVK@Ua)7O4!Ue_kP(N?N;u=7AFH~EKo>lMSt zThO66Yv;zG+uIIl!h_Gl+TUkGjz4r@TG!M!l3EaB)55biZ9JSFl-I&L4EWdy&a~I4 zqIaqip~#EqbNzS#jq|peXSaK3+1FoBAaA{fXfm?<1t}dZFsLNwECOWlU)h0O`hKgq zmDV;%S5*jrK=UoA6iSB9!QF^+{)zZ_ciVf9DU^gwA0!1t^E5maRKke3Q%Jr-??Vhy*Z#ZA*7C=#Ym;H=9US z!{O+EPCGOhQJd1NP$^D&MXoOpNpgr)X7d|ju?|4Us0*#9B(Wziht|)N0tftf5 z?Wrr{NzkU<`7(H7Mu3x?uZv0B!6v43b#~(rsl$rKxQZ`^&Rk3urMVin)v!lM*~#|b zS+@jRye|uXUaKdw0&{}M0yHpW*3pUfDOWNp`KY9%XaxOXuKmNXW>T~@P6hstZ?5l0hKtSW!BVCydBg%E0Sik) zSW8gq08-!Hp^8R#Y_J3om6L;FLZymoAfVZ~0)6e66na1_pDtd_enMf-zUg@2at(O8a$!A{P_=wU{32 z(nDKAwPQSS17U!Q$R7Ip!agcph>Na;DwJ-&E3z23^}B~aU}*)64DP{Zt>&FTy*&vN z_yktEW0=eE+(@d!9*`X=5sQ%@$ql?pTevvXPd-aMuV1oXr-BFq z`iM88&w~S04nfOm>d4}dXE6oWK2=USG?~W*oq}i&o_tv}?H#A?cLVBxkbt=^%O`(? zyWu@Cy~Z&RJfrEq>DVOgAV)M!-q=v8xBD>V+7S+Ky~A}q*RI)!l~_-EK}|A+Oq;&q zNd#FN1Mi@75Y{`3OX^3<7i@lNHZ^GzgIws_7)?|owGd^nxFCn z`R$fH@CxJTsU>XKBlow-c9*8gk7KQm@H;!qF`b=R;8WuZ3RTLf1wdp_Ac!~eDZslH zHHm%#gl}MF_37`!2+2pWp4cNesq@CWc(M_KAj#%BV3*6#F)d?|{;30YL@aXb({MCg zA8VZ`J zUDc!#`CRMjZ^YhvFXr)N&g?$yv>wiNL7G3Nd#4<6sSy)e! z*c%Guprb8*c4Dp9VZNs{${i+e5(`CR*kOk|NKZI^!^m?1TW8afrky)YxQSk`$CIcH zmyj;1la3dyg?8NA;Bd49Zfubi2y{6yA2-elc`?nvKqj?q3nsj|uVCW?`QUyBj2On=+@Ax^0{b zh+DtAi>@eS!xg(SDvy|2q9wJ5>mZ7sc5Rmx%yuC;@?V1Bwq*MM5qLm9OkAc}_GpYu ziPV1JTw=G=`PzWG!w|)7RA`uHtFKn0^HSQ(V!fO>J*a{3a~XE~G}29iQ%S9w!M{nB zOb)Q|Wpbm0T<<7;3McueXE8ELnLa3cQ_C1xs=Jd5U^^EL+`C@{Ozu!yHwk;(6qbnZ zS*^}ukS|t4oPE+2S@YqcYVsE5O}w}1+9z(h{gXBXaK`(80nh>WoK};x#qI0Xdjw6S zmWw8M6=_nqW)WxRvXpP>(;%X!RY2j{n3Nj8km$nB*FQUSkjAQt(QesIy@3)N;}AUSHguuAG9E;* zysYx43Y2uQsLp-}d`!#yY|k1|X;*m^hbq#YzBV9OZ>+UqbOySp-aW8B@?|1aTiq2q zRgFK@Mp+a>arD3&o77ux!|=?EcRzm1;NfN(+FxHwDJfI`HN2u|Y#2^8z2&E#LL+qukZ38;_VKe~tAz+vZnAhR1bA0^cfJ%k4I3 zo|Jhxm;LlOQIcni*Fi1lIPvwtfz?DL*E>Hdz~y^~OPryB)-dOGXO8aXX9`-3GEwzi zYP~dg^oUWIKfph9dEYj&P4r4v*Xj^59MOh&qEI}<<@WN8Ei;v%xE;;}AJVcN%ovAv zuX}Ek6p2Gn6e%~y782!Jie^Kp){7JU+-d@KxMHE&!H8?43p9&}&^vjesyFW+kISqo z(>Ol*sJP0{!ZC#Xo*vXHeyyBt0XuQ!P+Z!y~-<*tVcn)vW>g z0DA|*4~o3AAG|HOh2Act>Kw1Vd2gqj+T`{+b-Rfr1Li|Iepy( zSrb7X@?H26ef*J>=;jg^Vg0&yam1BKcQV2ON&i6~zwG#HoD#U>L)kk5h#iJmC!Oh{ z*ftvUA&ms|d$T@)J^7%ao5a=0RU5t&U!Sa%OOQNKbHn0_a(;8S+zMHJ62eMgl`oV? zslTMoEQHhw-UFHhY>)ca84j%@t?o8_PKbtgW8K ztxGQ1mKN>?XTLVSyR#1s8r0aS9#sKRLdDF;6fxa|!xQ&bXkmCdYzG^pgXkY!o7WD} zvJ|;Lc-jzY+D?V%!y9*fnZ9y9SmB7&#IrEk8je4M-&3f%Cd6okLeBB+%P1ddtS>1c z7A3{MbK%34QCr@{m8F}6|LfoBS*RRbja@_Ii$JX_HL&bI7;;)qh@dS~PqNx0phsLxz%mbFE>O?vvFBl-H zf{L!!QQa8St_aDRb;QO|$ImkIg6;8uZB3Fsg)JdV`^}InsN3X2h z0l3B*?mPIBzi`XBPB=UZWfAuB^q%TJMi>pQ?_GQ5%sm~I4glz|)joljzpAf?nFjtS z#K!TXuSi|Ig7)4G;Rzn#BWugJ_nVI=+MpHx6p$08UqoNjlBR0bz-D(=QfwE;5yGW` zlkdI2+Hr#;!2GHKjwEBq16TX;Ja}S5eer#Q(4WqD?2Snx6{F*ASFRNR(pUU@SNDWs zfuqF>uw67EtilV{=>72zE{&}VAZk0JMJvj65z3pmK>cV`Ti;d)g(e6Le_;0>FBYbr zMVWmIzaXPW`=dbDlJ-2wV;8~>u{+*UT`wmL-Ylz3Z>!>R4r3`tRLno#JaMn~HbUY3p7@U|uo$oS84^A`stap_^xUlR4)7CzU+i~%J zp9lpjocB``9f;L|M-p|uvs_D(0q}smmmZ=*9H0WrfVpNq#5{^NIK}abQ>T_lEsv68 z#y2@&^wUiqv9nbPF`ke7s%=e-D#6 zaT>E1@Q4c!V5xczyv5)1qIx?%=p+7;n9ViYZs^8lcKtMEz_xJXHvP;ynEZ%yVJ}4) zGTA9U!e+?YjWrflvo{ zw~Z}`OdHt`Mb^A_h7=v|EC=GxsN1|jXc$sWx{WiDgc!(4o{)a@RhAV2<#6!9mV@xq z!Ysvu6ZFd>f8QWA3FbeFr7;o&{Fo|?Tj)VDIj^~#x?gxyMa)Qz4WGcm<|eES#X_!n zMu8?~74>@W-=iWCbMNM$EWsse<(IbrXGG~4-$+|S6s|I7!14UqU(;nkA9wacVVLca zkPfTw+QU?dCZQzfvrzBV1iJifu=dA~` zH{JcTP-ob29}YYV1q_9k%WC41h|CVJZC|75jOvs0YC(JM=MXt(qD;%L$h;WCtOL(a z{rj97_ws39$nmk++9l9k1?QztCCGDOs-gLhRnjv{ow^5pT{`y?9#m;{dahJoD0R5Z z+Qeqry_r4FyezM=sM-dWQ>Rho8vQSqm9bPhC!L$IKKo8T z>hYHZK%!Ke$snM{&I0If<4qsx{+s5)eMk9pG8%{=m4HQ_@fTmj9@~ZcD(|#0l1r~i zD!d!-dmu5`>)bP(ih{#w4fYr`Y#qqRr(0yF>qv3@h zBe7k<;8&L>!)A)g&e4TrnTIl-ATVNA7kL{!Uzs*1r=zL{|JE7)Y{?|tX>Q9WPD**7 z+FJw>VOJOo;*>XMnn~`|UHF{CyyOoMy}u8gw2ptbEvfZ|I0+o7ic z9<^xw>Cla~p49w08g!pGy;T;c+5-9XWQ*`Q%D`psXh{;~Fh=*>|K?2vP4Unpn5_ik zRMavX)F`($F@qANA0aQKsASYOmhRTdiSpDX@rgie${*qR|hn07h*+e%FwVEFeQ@RBYinzy+1NKxUYj*SsrI?Pf+XgtBLk8KP?1q8S2O> z_Yeg<#oTT=QulH)Z;4#@bu2xsE9p!+JfwV-qFw+e?tOs9qpZLF8N)Cw>_4-=6A-J4 zer}hNThNJByPiZ=k%?w8HsL(5w1q1vLIVxhNv1*)0YkQ7hgwX7a_do+Rd};`XN0A) z3W=U|$5_&4bJ zxBOv zrN>I$`3TB2x1$;ALDW+F>Z@ee9FOfpYw-t-eV_RRx-;EXp)HIitU&$p_H(Y?+i#SS za!1}sMlAhl;Kt?f$lb^-TcJ=#_72p2j+`ezpq#Z@STOr~0M|-%2_qR`3a@|{Ynj#c zRBZ7#d2;UWhTQU7lx9dHNsH;A%x$aFW)vThlE_^T|6&yDIS8;^)F~OzoC3ZPp5d2&wep5XX}TQU@Z0?tr9#)NxV5fWUca-FhXR!k0VqM^FkMiS zJn1L=O=u-+zCG!W{>x3;G6Em1Ia$ z_X{&#siqjq5X_jaNyZK=y1V?EFFmy%7ho$$$*q(D96qR*${LVin^LP1J+Mui1^|M) zN-TVpf0yi#*k?gEU1;Pxx9fw1ow`als57lK8n;hbS5MbOS%N zgmmOs*bnOls`N z1M-kg${d$&%0H8fGIX^YaECg__z$KH;J&cKyqYb`X#rpa9yfuhUYP$9$Q#l1Ob0KJ z!j-7qMHbzlUHWO*7gs_jXqqLa;>E8U(@b5m+zFqFPE);E<_OuR^CRbS*#<&agmz3R zr`;#8D~vc!*h$S8q`0Fd8Oj@i<#YDtSyJzgzAvatIgTj8){sOGWH3QW%+2mC5aeo1 zKYuU+l0y_6*!=uRN$eIT$LtFDgYDw+HSl9^S8c_vFc9`N;bbAcww4%uw)e$V%NVkf z5jre^yNlkYO)YPnf=4sknqmUHmpgRVE}J*zmx~NbJ*DUoza^>1c^#7O;n4S;*FyfW zw41Q6#N)F1qf9P`9$1Ir@$i~#D~OA2^#QRnaBPj0S<1*4h)iBSae2{DpU49&Z=cul z%=C%&I36QA3J=5Y z%4KHPBT(7qc@*Ynvu$km7Jb$&3Oj%La2vhP2il#n<;qK|(dcN`y?;mCEvx$Cj>HFU z8F@oUQnodet(lgusF*>Q@>4g+2N1nAKvA{_b z9V#TklH+-OY+`2bN1c#%*;B3EN4<8rg=S2KK-7+`{Vwc`VcAJ>T+Dt$l(LUDT7FRt zTMs(5wUyzq&PqAN_xeG0_wP}yF`#HXW)1dDi+?)Op&xYj7~cF>?z7$FEQVwv>i+mi zmo>VsDF%BSzU4oG(j_IClvAD@(%pOHh8seG*OjHb=suo$IAwh3^q&yusvLBLZssd2 zqssQ+OUCD4O4qo2oDv3(8>zC9Ut2KnKi}p(k*2?pNol9%J0(cRl8X{hgqBtk(%Z4F zqJ9;-a+Nw(u6Ub0f(=>47eUpoQysH`ZnHdhBpWh<&(^gpt0o6%+|UcRK1k)e2YG7x zPiq%2yL+ab5EgUIvLZ+sM$_DMZHbbwuiitNXt$L)4d6@_5)axX&D|@}J^F0r&vtG{ zzp4UxXCfr8p~H>mfr&J;aW5S{ts5gG7dQr67gH_u$P?z8=AKp?t^bHgtf!WwBIqAf(GsC&D2;fhm$t?F7hoM_%=f+4oN*xxRLGH zk~7C-vgnB>+4t;gSTpEVE{1aNbLd5b%{Y?GkXECuYHB z8cONV$U_tL>QJ*DO4BTrb%;cJTR;eygHQ8i#LD$lDp9-g%pXQ&CUa}Pjp-m{of2L; zexU!)AI)J1PRz=of3aV%ZRB?&Nb4Uc+G+)Z^p!6=T%-n+EhzLaa@#I&J^P6N{UVTn zia-#K!#%-3bsyMriJz0Wckba+pAXu8gMg)0421B{PT-6~wYs46dCz$T;AC{p^W2Q_ zbo`F3M6pp4Et7L!zr>dzY$y@Frm*!;bpiqIgz+EbVL@A^{Ldvrd*v;!}3$L#A-DPD5>+i3ZsicRS_vaE!khFs)5>#^o(1^`b-wY{ECMsgUGkP203-OoT&Vx)BN|Vl$@zSrKf(jdLquOeAN_e1isA4API8GS1pgmPNZC4P1S>CH53wpSfQ+c z`i#u`HEjY<%ufM}P*MaqgBZuNmDmy}(4UadYM?|kfJD1C0R!duNR1kg)GR zIHZOfzd#k@ybw+r74G9BK{Uh`$AG47ntVnsyG{bW<&v}s%kxo?Or~^Bj)VRtVFPmT zxk8}NLTQ!3uzWDm$)`TR;>y0;b}Jq;od(H&3RMBu+bnJCM1o}0 zf8*;9m&BHgJPpVjrNL;loFCY|JKzCtVsSy*H+^m3)|y!KxL^#6UoybUPxt$7h9$Df zdbKtHg5y3WTa%_DM5nY)`b(p82yVrRRP?)JHzWG{)31{+xCn$FQ0W1+nKLdEfi?Td zqMiBmCOl{_b~_oglLg{VRn6uE_j zolSuVudZIFRHHhFMcY5aagVkD)`Yo!Dd94h;0biqAv+A^94~1}+yjP3l@&|DDJ2CH zVo@tzBE>+CSV0V&xA5z6lb9%uRHm2BNv;1>V&a$lv|MWV+>m9g1WY@xFFTbpyl(jN znCz@Ad+Y?BI!-(2ZmGR%fJ5yc;drx19>(=tDPK?eBv;&8M^3dmrc2n-<38^qjb)L* zf+kxT0sJB;x&@L$OfdZKdE*YxSyW0lwRW|qCwwzs^Txqe9iy}Nk%_|&vg~&n$VH@%I`;bx29!| zK6Y`>UkVG0CkHjysB0_3zTv0%+?xk_Vm>dIX z4o^0)$YqL8pgql9DH^Q8YA=fa^ZUU(*om*QO}hd^0eH8u!LxiVyS+*QrRapf{NVdq z>#wzD5t@BBzZ!FL;7 zv*u^i9pMP;8#r>A)8X{yFUJfESxMN{3295jQK5r8JZ@+31l#mzkVcIy1ZNQ!d}eT% z^qMh4NiBewt$Pa2q~4x=4eH}zjJ*hm3%4jMUjr6SqzY3ZB88^!f0TJYw%HvOQv;}a zZ@{@WNfWfapDbEIJTu6ufe)4i>JXd`cezHwtfsf+m)L_R*xd-V~A`kWe@i}*Uq-axyr@Rbw zudKeZT=0(0^}KjBIx$(A4QO_e8lO{Z*g$DGThl26Bouk_MKpjhngJ}s!NUx+o`Ur9 z4lB{UAn`8k4!Y1y1bQ1QzDlN-zQ)|$X8K0gjl=nw6x_gdc5D>w$n2wg33W3vnVvYV zXxKLszyoOwRXwjU5j4K>SiG#65?=G^sfK!fGKh-6dxl=p_X(pig@jw9qDLHhD_5T7 zuHNuq$q$~~bv8!B%>`f87!aMtAw58tS*2=B8`tW5?d_$1Rx?CjOonXV*!+;|TNZ{`EWXOpm24S7^v3#3Bh2v}s8aZJS`3x+2-1UH*W8w?jZg=&!SQ-36%xG$I^QQ=&|KIb%7I`B3^1z;zSrD?BPd>+i%&DsjXkOS_$|9*7gRH|w z78oldrbdZ2b^+p$jgup&PJ{36y%lk|1EWSoP8F&@N)aA*1~XutywfuGNX-vuJG-(z z5E>Al0<~o%7gekpMTwtQv|a=idINcP9Y#~^u=W(J$5k(bD7VUW#;Lq%BnPcj@SD=r z=xIW#017>#GCsY9i&@`%8!{U`HeYS59V6{I=gre_T!LA9tMeWM=x&hf#$xnrjccl54wn4N|O~)lFZK_sLHVddB#a9S4GS za@UbH$s*|lC4m8^2v1i>Y~rpRe+<%IX(K8dV9Yf75Qe0{_~rGBWY--ILM}}3e*4lr zWc|z5L}&}kV{DT>g6E4mqH-~$v}^lD9o!pTkYJ%qE1;rCWl6%QD$RnAPaj=Ip&eVU z->NYu`!8>=aA)eO-eiz~rq1y|p|sp|_=-uJQspBY&*Sx{;f{QIwB^0clyT+$TH3qb zp7^V^qw-Yh#JezaY#NI0HwhNf)WL=U`FTdWC?1;La63}OLJ`|KN3-bzJt_j?FunNF zs=l01S1-biuNBfUZgaF}ifll&Cx?nI2OrGGn@42j2w>6p4#EvGFuDJFFP6k&J}wEP zREi8PkPkghEZ|A3fPvi6z`N~0G}NhI4rQh7l>v|p-wp;!$ zr@9i)4Ue$$U#a&{jOQXTw?Wo%WUBcE^FUrTVqGsGr*z8A?_y)XtNvX5Ous3Hc#cCVbUKDWItXio_j-TNuf5Z-CJE%I7~I_r_5M%mJ9Ezo@yiBnqTMIU-nNAh2mvRH|h(bo+^AWb+n z*AT>ynX5@vADz}*VGy#-272*zyIQ!@4u#pWXq$uM_702Gx%VaVF*Oyq{)0U*y+95b zw9gWV)j8c~dn(G)_+Vc3zc<_oal<|7Z_L=N()Nr6nlosx?DOT*y>eXwKU@; z4qI)LnVm}oN-+b&I{ica_hF`ir>lZIKH@GXXdQC@*hD{z+btSa=cgeSYTRp@Niv=H zpVs@iE{1pfK5swtumxf`A!c#X@34#0G1 zOwVCtDjD3wMI?!uouB2M8&QHUJ|7p$%6t>1zgv?wha~7I_QM{GQKOYxAk6E5+DOdl z+i|vjlNqsO4(?f8=5T0R8&-3?__Qng7}|V#TN`<_DEacqV#i)yK_~&G6izO0YZ%9K zrts^eYJJiz+v5fCl3#a$z5-1c+0DX4`-swE5v~TFpAZJT@A#B8`e-l_4u8MSqPcrG zfTd_`z|dEQ`D4zH6^w3e2nvPyyQ!i|J@1AMYV0U)gX|xXV$d)s6oNUoIa1kDTVPIz zqC=zP;7g^vmsV3Z%aj_>=?7o4CM-V)gWBU}@@Bdz2lE<=zEQvO*$w3RSOgt^9@yK_ zbUiy*ZqC^p3S|v9|L8J+Shgqm4R>vVcTR6kdtk%vS%_12>P#!|Hf}-OnJ<+t{ngqn z+@9q=(|^8h$Uo_6dL;72Q`Tj!G!5{zOARZyXbTVfa~e`G(9~-szP%j16=y?dI+?#t z!_M?qj+_|(Hg&s3!4~A#GKPr+@QAalN%#Es_)BEoo>exw%aR!czo~E}Rc=ysbmrj1 zFmq1G@7^Hv9ea7T18kRvkWdw|{vd+}tx5-8?)muHhAa z9T{!@ud)S2aAv4&cx=>=;}I@ca6A)qOCnVoTW{IVqAg>cU$+G8^W>XFw)UIyU_0!} zV=byAzxkgNThmhX+?w3W+G=H0&w8Bll4p5bhqct(`wsSYJkM>1go@pM?=5yCjXK45 zkgx;Y;^q}I<~tfaaDTPH7kO+ zOJvCz`>4q6ntaOF@1XBeZRA6a&eh9K_By)ORY8;X!q+A#I8DkP@j ze0bk`w}pEZtWh{B^Ag|%I&>|rZ|95LZ3A0!icQ|e1G-wfsuH^BIn%O-s;!b`Q4MRu zPqHJb9U^6F*F6)KA;WnaSNu+*^@|NQ9(^815GmqRZSXTt zlE>HKrUCCJd%Q-jpn?Yu&U_754sxEV{eg7hc?yhTgS^-t?A#ROdQ^pguz)hkRXel| zmNI1;yA?6Q*sb(+?KZf)ACi_AR0>DT<{KJ7piBvX4(PzA*>)Z zi7Kk`a}^JGBr`WuYyU0nd~#fLW8I{Ta2gKP=APA0DIGyyJpjVEi-OHlm{j1SHjP~g zY@6k3Ui(XWI|1PNrSzAbhcjonLqQAszs+yB1{xn3UO;*}ZFbY5p;W~H>^8s;PwHQjB74Z!f)veAI{HB+>OBGC&a;-&DI<-cr_|-kM(H7V8A(!Aa^giJKp;i0(17f8XphN#`D5wzxTRk3$@v>!d4Ze}}25PRo%mw=#no~l9@tqaGT6v!#BtX!~)JRLQ&JVeG-Fo595_$ZoWT9KwAw#C= z|95u;BLn0AQ69m>z{>icwg@HyW>zM~|4je0JA#Fso$(xfKkDq}0OkP#|9 z=1bkQwY%SsubHb;8MBYRsjsK&vDr;Q$P@7phyu*vP=$3CsJeY4D`@baoFR%32pIvY zf}DXpf+jq;eFdtjDs4wc(dPtsWP&QlJTMnP8nSEf_CS^l5`_NF0E+YbiNI5WR1)I$ zL;?`NHve*F(1igS0*Jl7_Wl?Qk^bfc3=+?zih`s=Ll^}i^O8Nj42xk{P{U6{O>9EI zYVNlH6v2oBKzAxc1|cn?z^)1qL?nQb2&e@9zU~e10Pg@CbFlWVOfJqqQ@GbTxY@~b z;l`x|Sg-|tr$$%7PHgI6GBDTnB>-myFzMXf`{}(L@sW40s$f_45Hrz16im~$vJRmf zZs5u^p&sA>&>%t1U=f%v?0+60nD@Y0hnB+N6jy)&B7GTT7KaUlgoNgL1Ys~>=Y8f` z9=Q0k@go3(1)cx^JQf6*+H%tgs1PN|ufTns`e@({gdf1lVd5=Kz?uwf`VWL`jg5SB!-o{5k)cJ!5IN+T`(U&BcOI60{tBj za%Q3pKjB4w*{ArIVhE1R@Q%VIyvJ@)2bF^`_W6%bR;|5+Rlp(unR`4y0P&G9O&ZJ@ zti=jyCT(D^X{Kdz>?yE|Udt%7A;#fQVZ#P4H)Q-m$=EvlOJceFMSG_BSc{Qj2%$g? zr}vCXW`l!|AVbd#(|<4S0H{!eV&3G}!bC_v7%l~13JkN$i~0!W7LGa*i4HypA3+TT zKmmXO8J0HT2Vr`4xMdhqDa8_zFa?7w{NZz_0Ei{|2p;w#4fcWr0ZPCF5)k=;dvn|B zv;Y#0V2N$xqTyCM+@veuLC(C9iDiBQdf0;tsIW39NKI@a5K?f!5Crk*qH#fpuk+u2 znO%B^nV^Z1uJ2G3?)jNMJGpX&h{C@0!Fnk>0%cAjT@i8u$$vu=FwBY+;?D#EyT5yi z-?O%mMu?pZ{~fO&0I14XHN{1h?@$hA^4RDmwuW4ZDbUd&R=>gcnrFDbfiPfyYZ~AJ zB>wmo#-RjD;`L#0U%53fZ#?UNH`UlmJ%@&qRM7ve$cNlJclO3egIXY|z`_y$K|A*) z!syr$1pt!`F&F~*3)-LH4=-|Rq^6}R3){C>-UGs=gn>X7#K)k#&t3Av{8Byj>#u=} z3R1L~AHRD90SkkN$;%aiC?M$mE1-ht1`_-V4~Ud?j`KxIqo#V;`Nlqb!4-~U33^8! zNu>n<#%L~g4o|oUi1|S3aX3D;@~IxH3d(@O69XvBpKV2mLqTHF`&ASQ%Ahjm_DwoW zaEQsTD~LT`LfAz>AT3S&fG&M&*XiZMO_26^I;E2h01+CvqcaE`->TR3JB}?bT_{8U zlw3b~{&zPS8naE)v<^1!#u5dck&~Yc_@*608#{^I53!+sju*p)DAjXZmQFAJ>)Av1 zB_%9s$j58+Ua>{-KwAd3bEf@oPTbKt+;B4MB*nBw4z)AA+U<1ZY*`vmcBdZpCCiSM zq_R)l2!9^&p`zMvl|OG$8NQdYzuXQM*AV#%3E$G<5KwJ31djZ0D;C`C)gu)T)spG3 zV5d*iZ67)0Wka@q`C+#-Q8gu&adBELZ&!DQxx8pcp>gNhau3EQp{li1{hQOGxn^>L9*<<+dOI)rJ= zf|4S9Ng)@-yr~<=P3Hr(tA;+pYNwAAbGElZ zrLSV0{Lv`dp+{lT7bbW$UbIyNq%9RR6)rLtZKzU9h5*fz1HSZLiPVIn&p48Y!2|z* zgH;^fo=SlLU{cezP4~4tPpVYskB$!>9}!D`N%Qyn)EB?nt)ixjg^_Yn5H1QOc4LfI zO6K0_u)@&Ae;$)4@x_ITxn69<)GrJ9_@m*m*AOvhUfAl7f)8VLa##|ZEJ?&~@0Sux z&j*mx-L?n4N$V#*=aJ+&6ibP@(KZ|%6_G(3Ldk0a<_)huIKJ8LGjxrc2Dlg2+V(my z((5rFrrR!Q&Qizn$!qSsxkMh0FLcVUUBo(nald_>%JV(B$=9suO)aB6PC71pF6uVI zh0lkt?VhrlPm$(u>eKJl_~F_)-UI-xpL&7|RP~dHH>p(QBeWN8f=xZUs6~1GwyM~; ztL-h=ZX{9{%96LA>lN{pivMASKWB^OVy#eN+tdF(fL@&(SMJZ!I`FQF8~e+uzMt!V zeJWIbFS^O+QA4e>uKoOdyJ;Ap!+xfJxEe1$45L66eq6OH(HWgVY^cm(n}Z7mYkKnM zvcjzi5}M6DtW8zMn(>%uwe>ypJ6Bz7ke@mL!wxC!TTKDps`a-1LuaLiPh+^ejeN8o zPhf$fP`x3#SGjrULND7ef2n#gxIgdMoe-j`H13*A*4ri;e-{yQ2m`;5zM+04?#`qB zy~R6&ro>0ZFOY*9GXA{+_WW$SC|?#XBq8Qd2M^+?$ak=N^@M+^EqgJVee1m2S*x%;J}AJ$4DaZc~e zx6^L8EPoXWd(5-2VYWMi#Ziu}sE;m?hg@Q9Hte^0f{X30=3$sMmg zQw_n_LUk~!T62t&7WFFDJ%o%ICx)?;%T4KMJ=*vl&Gdjfi@(-k^W^*YCaOyMLajSeL_N^B`c3(@E#fzj3xrD6NP&1HB<(qd2 zf9T`Vis?OVkI0p+uls92?yU-#+6Wu!qI%k*G&xo?0Zd0J{R5_xA`rCPPd4~~KhXtK zNkSiRt>gRhRW6N3%=c|mXw2<{$B9R!D|jFBt|e2jakCVqDhmR`UW`btBaEweN}7CC@x1Or+GXL>Dx;g=;@TGMXSEwodqQMJCn|KHd%WjYu{2zFFUV9L|=N+A)}5i z!aohj)+bWD9v=+Ib;%Uc1^crNHd($-<@T{{h9{#SXVSB$v=@WlD}Qdw@@-@5R>FFkdr_;c)xI>|Z46RBQ>;p@hAC|S?eKbYA7 z3kyYVa?)1sWs1&%qvvOsuE>LU2>vy5ni*N69fB$7msK0aZr1k#8^u^?{MsnAfmu;) z9`59}iqXgi6m^!GO@m|g5ZSjeoI#l!U*Z8lo{GlZF7ld`<^c`&eCei7O0 zgWVj(Wv4t`6g{V+0==G=ArfjQjr@y@^Ts5XZ*v@%xu-tvWja(fg)ALL&lOP*grp?) z6e}JYXPf9qW@0*A$aMK)G?ykDCT(;B_8Ru7_g;bMfJxInzVsmWz@zvr<&E@;TxKgv zy~Qnjr*0xaV4}|TZsQ$juu*aovSF(>ENux+Z26969m}+}R%VI(7&!>2inmyldbhXS z0%P&};iCr!ynCF9Wp#+vQ=y8%ib#~TM{su0se<%7eRU%gS{{Vdp4@cb)|s|Ow>AxA z>$jrJ#Bb8lL{Y~rU!``7PV?MH>}cIWXLq`8IKQlIGLeEYuvU7tS(Bey3WO{N;twWT*Nxdga+_UP_No?^Ot)5Mtm;c{iS6FSDt6x8-Bsq(A z=t0K(US-$YCX=syW`#|!w<-a&Ev~j7I*~J$Bhq9mS_IH9Z-xpSOE^$inqJ+Jrm}b~RU}*=^(<1YNU7wxoWiFiV6klOA%UZuYd^ZNdg~uN_Hx zO;=?(#{lejYUt0=q@9je&NcR3);u4WnG%fUj{K3YVh9leVMVnvOI&aIVe zoM(!?63Y!Azn6Yfall@Ejr~8j*poz{^Ih_U0u9Rqs#j32Z%i7Ev&D0%SheoqTWwxYz;Q8C`Osb`xukZL{qmHZV^lLHmhMuW5_7=@-!z^`ol|Uav zWaWzZ`pgumD0>&YBt0!_rj!)d{T(9^8{HR1mfy$26kSNx0eU*l3^|u!-2;#PpRhP4 zhb40JO^ub3DBGxuTxgvXuwu%aB9?LD(?&U79x`Ticay*nT2U)p zXVyNJu7-5@+Ktz~jd--kM#^Bew`4(`u$_F)T?Cw!mX15So^1q?jro3D9p*$9g!eCn z#$`Y7F|nbjRJBF4acsQ^*J@+o6fgax9#iOG?skck{3gdYSrUB2Zm$ubYj<)5fs^zd zGN*N7Yj1+HLt+Ii7!7W_B~kUZBgBVlZ5dU_FP0cDFmXHVxAI0D4en<_;D6HF=_gmJ zXpGv->EG1KC0!m?9I`3ZvLtNoj@}sfQF5$Cd|H!<-clMJxSZq0R#)EPU66~FB4#=9 z^y=f9^{}UL2X>(RPloXJ!t zOo$g$Ib_XWMDY+q`UqEdz0OeRD{MBwCoQk5rM9i!ru%9xZJ=a*e2a4;`oW-S$jRI| znRl;{{qc?duC#&eV0;^RyQI4WM?Z2u47-@o)23iser2vKj`9qhi3exn*+Z1tbX~OF zllw|J|AeoxY-KsQrNvp@x%RlNrPeTScGPh=ty~GeR`2VHc*V!7gVMy;f8HAPdG0!x z%Kn{9FX#xPfOR1asBQqJ+1NPzlYx7tZRcr}=WKOziME_vuwBi>mWPYq+C`1Q=$omW z?$)W78Y0C`rfQ-OvG=U5sMHcAERAJQGHXRBflPa(jNOv`Ld!9js+Xg&_f}v(%e2lk z`N~0VCZ_f~DfUP|tK>d)TgtAVthResHa--ZC0xiPp|E#e#+z1hk!5B zlj8E{G{b^!UN&;iLc2_Qd*L|usf$JG%dhj(8{z+w#{P+21a?MNP&_>Uk-r!T7}*&a z{xkjSRb^q|{Ll11r7oK%D=DXcR{ z!LUjOWDdj)fi7)g%@0#b;OG2?Kn={H1F< zd7)Ssa$PB~5d)~y90fLt7+jFnniK}e^_2dQ0Wk&}Io}nW1q!aBSj^nW8b$;Om<3|A zfdUXA%3OjV1~05q4BOk^3C=+fMTCD8j+W3jRFQAh6Vzt|q#GL0*>Pbe@jMKnv-2x< zPiDtWsKmdFnfYPN1p*=a6qC7TvoOTbZ1oImOfn=X4#t09AZpTsw+Y>4(2SqV9wCK| zf&Am*=n?wDmdnExLgTe)O=O+cUP6rO-*l;GW^kgx-+W!S}o*-bT)ba@xGQsqE z#2`X)Fo*H*z$bC$d3Y3~Z_(v9TTroCsof6wiP(-g-7^0%F5#{3X`PUXQj0LgA6j2zGuTerp za+z@ZDK3q){;}=#wAx6Xi@Ti>LcgNsQB*i@ii?hb&`9hpj_0Twb2v8fzH>ER-=~&O z!Kdj8JBoTN)r<;8cO$<$nxr1i0c9;UZ~sDQ_L5&9-&v)S|HH!xJVwt4bI(mZ7FSJG_SGtk|N$Ghtn+Suohox=Uh^^ z+d6AH{ibbVDcQ~3^y(t<*``bU?fL7y+tkTkdeSDreb(*=xMmZ1OR2=Ggk<5$GWDxrZ; zYo77Zq-W>bhctP@tdplm*q}OpI7S#=jI(!aHq;jnGrdzSMSaFp2qPK zR8~630JGFodAuDgEDk54Id1leBbmXHTWVN&a=x*W-?G*-ZVg|8<3>wgtiCV8Pu?6Jzr%%+R0Ae7RNy#>C4gG zwa;C9Boz++UECe~CbO4B*jxIS%?42yS+B}EiMs-2BL;3giTl~jA5wf~mSIq6qwSPKCk&v56C z$FhMCj}!eaHDAq-)Y~gP=8K2A>TOKhNp3V5y=*dAEN`OF+c!v~sB)~yd0$A1sk6{! z8w?7kE9=PW<{EyD zT{};w>oudRrA5mmT3bakr6o)J_I`XuoB8fLhb2?wyR@wJ zE8uwz6#cZt#pVSI*)qe2x2y3mioZxU#&o#a4Y9RdlbYz{AAW1yF0JLQb!%>+SY3rQ z+~o9MzsV@FWE7kx$Ng>ixJq8l-w@oqUJuZJy8?!#^Dc&zv> zA_&q{H?e=JKOm#+-7?Afi!p3am}5paYt>%nYSaxhMMlAUe+Qb|zv%q9`8uh=`#5s+ z-M%%ns<{BWWAqjO^yJ0kBp1HM-R9G68s&z{Zm#(e?u2`g-gi9*BO@I_-D#|}(B`)k z0@wX0cDrTzn=o0*nH0)C7J{nM`u16rE*br!D37@rHSi`|+dK>lKi1aQM}_mbC&Ki@ zYV$c}G0j{RR#(r4jgciYOXZo6xzK-Pq}{dR7Z{H6K=l6#hOGZbF#H$!*#8p+nFyFz znc3L>bNpY)kd2*#3fJu%JoRSnH4Dq+D z=m^B=;K)D~T&t5aJpfS01_y`7!o@|&;4kLT3gpuW3=j&?ov;l66&ivC#Zpj^FhUF* z0W=6;zd|8t-xl;=kl=JnFHYcpFmW?~$O^d{1T|-7^)gI|h89r3jK73Rax;1c+Sb@( zw>Vo>RlUsLv8g7&6zQ64+@5V4n?O?nsQ{pCq-=j0lE76gp$%Ms0H*@j%;3}j$f^I3 zDWLx?CakUjj8|2kS6VhO3L;x^aCUP8`o)e)4lPNgf!>P=ZYW^^D4Pa~UtXB|`c_7U z2s~&t1EjDPy6(Lc!1WKKmi*Tyy(pJ*Zur#${)4;+2hzFmL-)zQc9uT|;Qv=pxVld+ z)*lssVMBmmM(FAa4-d~~#jXZ{jl7QaU$I{Qjm6eR7ZC3sh#uex8O8HCH3`vT7 z2<)vEq&Evlp{W@lP$!@_$Rzv6)FoI65;pLH@D~(}6zGAwbg*{|uts2ye_}1Y{Rg$O ztfB(Kfu#{t@DBlVJm?al5tyShX!=iakRLED<_{v$;CIj-A}s>G#1neQ?hqTvQA0&H}{K7GMfW3nQAP0dk6)Y3VUtRD6j zgblX8ZG#sT$A*S4ZH9-uG5^m5>*4bJ$=24gdjk zfVsti&~Nwl-jd_i%*R$Nsi3^L#w6yxiK%|nGjnUuV86fbZJF)BfCzQibF-(nq5e`9 z*&GWwHX))Qs!A+UP2@ZdiK6?GkVq4(!e(%2U;c@rutD-0548)nke(TpeCf2-w zXjN?q(b)X!-{_lphG4ipkO-{737W|L%bWae$-vLngyQfvcgfNJq$I`t`rFJ!G}VCv z>gode1o~(EQ9%0vr%(RawE(=bH&roB-s$<^Cw@%JVi_A4UqCZ~-8(o2P7mle)3d;t ztMz8GX z*ajHndm6Z+@jDAb_Yz;mXHJy!3onP?jeX>L zk71~h+mCT5nKN4u-q^1N68vdz^REpee6o`H84AZYVGj62SYyy8ev^*^=o5kSx3%>b zCDieeJ&L0cZw#ScS!ZSSX&%*_Xa`q%`^Fb7D9R+hNtZ$&0ye{)eRU8W z%)$OsD}V)DEB_)`_514ZnbkhX4>q^XoQR(Pg%I~4EXXhQB>!ve#qH%~ZBoYJZ0OHx z_fJ|CARzZTu&WJi{w#~Xvm#T_Om`_D_>;zQ@I}7<@B8!_KIqxc7KDFPYO>42li_gy zU0MqE1OPw#>23Y#oXVt5N`mQh4iBw+5n+j`E&SNgn3RRBs+dxzIt9PF5u0V;_WHi`ii9O7m4LhKJAr z%|YeSx)r@bI~Sl;WciSF)_ci!A7?&fQ26DaeBNxni*R)$ zd3mp{j|8z@I@bBdG&9-nI@CV}(#As8?(^$fq}1Qfed~Q&61hdl3MQj3_;k;^2LGzFqaGOvBU0U_Y{f@!B4%PBOy36?270A3LT0B*nXTYW^X7nOF|jc0Kbpqou=$x-Bh` ze5AcSF{hgj3k$Q+?=$qIE)fS1J!xY|jMX{km>1a-vu2Geq}3*7@2hQ&e1Kpd(?vhg z%qV;zZS?|GhpV9D)H6ZhL@m~2=_|N(yhU0{VU|^S${#^uJEPOfi7GHoUC6Oph#-Dw zB`cqfI`zxy*1!xM73zK%DdTD^@3T_zp+T3GtNTc_TuP-Iv|*4EHXD<$dc?=chEG*S zMEI$FM0To|m76p8?tvQTtRyI#^HN+UUNpzftXdUVsqud(N*+Ab>Eva|7=7Z^Cb{YG z?G2=@aVf$IA8z`Q7Meq&?pRq?QT`v`aYWGz=O)hbr-Fw=Sgfjcxdxr z%gkr?OGnJwJ5_z9?y%Pa$kL=)tmvOAfL9Xh@h7026%e@QQ_yvsQsUu)I?7AxU9G41 zBlxEaU~YKHLX*_-cwG9haEA+HI_&KeK0+_!tfpmQoPgdP4u|HS=YCL%L|YwAF`caJ z_~^Yw)fYNMIm?Ff4fR6vnkr11?Ix5?NJJ=`st^+$dF+8IfrYmiOlte_e0U!)lhW@& z1=-gzu=48Q%M$KJyrrHB^Q(#wyINTsx!AXTrz+^(S(`ooxyhb8V)DOTK`(l>l&0lK zqK?}oMGVW4Ma0e=*8qB-ku^FlkhmrUR?$Pqc@ccl zPlCx7wMs1DD6x}p9J=B>d$v&gMEQpj8!4MjCNpwvyBeRY%cv=#NzSyg_6C8~}3 zkULREl-DvopOv{)!YA3VzSXP3Z;il&Ai1@`+d$SWIq4T4fUxB<4ldBFEuWrX9@5FM zNgCZ-?7^~r9$Hcx9g_3b*xYEp>hsg(plyq26wa?#IMpg#%NNdXT z{+@%yx_z)mKPijmA*ztYCpchX!_A%apq@geUzD610e6-weXw*V5Av@{xZ;*Vj6f*a z@V$?k9Gh~-Wq>tz@uTlLSlrv3ov7lwF$TG61 zf)n^{GhBPX$a^DE(2A7Bxcz+lW01@7Cw%668S{*~N2X($-4&djSeJS>PE(gXM9Nz1 zRR#_Jn&U)W+t>hi(CmUE!QNBVG9<^k8@M5%k8Wb>vj8bjI?F1(ev=(8q&FD)%}|SS zzy%X2Pw4aUdexn44FzI}bMb;b8k|tG)^s8w@L2JnzDN_OM7Lv;54IAS8rGeKX~NdV zMEgupN?nuxKB_$D)L5nXJGfK^P3yyhD>Ht(4O^MyxQ2e}=jOb;NyjhJ5(2g!F{GJ0 zjn@6LZ~ZB)mmr^g{`2ZNjWf-h&udiFhvu^I`py&by@`TwiJJKM$nfbkFJ&@TuYe8p z7~Fv0j{3sj?P_y;^L(M9^4fVnqz{v3HKF;%I%UoxQ(O7faMoVZuIJ7elHFRM&Q<3b z7iOYzPWUyAkbk-AFj_owH8NV$QsdopYO*;l0{kgpPIU`K?vFW%k~8KBTfgLW;A(AY z3n9tC!fG~EY65E#hIbMBz1f935T-0XgxAJ4&l-ZgjoU$l2Ct!TmD(A*oqujm8au9@ zv!l2u=6y&q z&TD|~HXUiJ`@JVbR<>4U>dE_3{ULt;=$%A=lOgGmt~M6cYLvVSJG)Q~7JcR9)jZz| zN$Hm~fV{zz?u$+bRRgLL%5&N>foS-D{QN!|+^9DhKNY6raSt|aDp{S-XAHaha_F8^ zI3XWXyl~$Sj;%v5shb%(8Z|HDJ7WQfuE81Ci_N&?l@W{T_wkl`D(xzWSEJWT9)DLp zRgHaxRqnXoFOR<*_ zg;DFbx;Lwx`Xto0QZ?=q*wiGR1c8QQGGp}T(I~TwKN;zh5Tme7*x+aaPa3oIUa~OB*qQWsl74qT8H)VE5yHv?fm9G@ig z3o4V20e>B#M{*W$aKBB&bQof6?N+7qawqymS6_&~a9@`gTali_)Tvoc_#v1bMQOv| zNEu9(tJh7^e6guhvFf?)O@^@?r;&1>=FA5nKU+Qy2?IkpkC!SYps4C1$!jz(C1WfmbZ956 zd2gGt=!d`WVqTFK0JR*+v8JTICJC^_b@^B4m*Drw+XrXVF|G7!?%4=w@2P9OSsYPP zb(Q&x5P0%OG&7PkZl#@E{j>avDJYTUl-5mSijl{sA%<+P!VtOBRPO({4}4JxrR0W( zQu|K(Hghzb=jN{0^O=~=u}btj+?_KAocJonWfC?oSGoc4#Oxzbq-PlVo!s~sH-DCJ zOMPn#JVZ^$a?!T$i_)`KG%*9+e-zx*SA*>epsM2Hi}NHm%Rq{5FE@MfhO%Kmbsk5~ z$-mSlW72;%SG{=05^?~9azOi2wh|l;MBZY4>O5K{V9_0p8td+!*L76O^~-&eP0EbI z3oW8Etp%IL)cKvOrJpQsPuhk(gR}(hbSzKGx+YCA>W0zskzi6It6&t~3^3U@x%K#x zwwy%LohUO|>E@&qg1u5e1dUojlN#p@&D9OU>vCymlOS-8DK_(b!SzC;`KOG>oP(@H zyedYSc+)*{P{FmNZ09q`j3Qy85BQD1))_uZ$<6437^~hQqLT4ZLKpyIPpFCn`N}YH z1Wbj0;|cvdJvosH@nSQ|2H#yx^Ec`>k{9H#r`xKMmjpQnB@p?XoHZV!iNAn`+7wee zWQ8qc$B8>ZuPISc$th0~O74;%1Vu|!L@@-drU#`u#ig1v&zxQZL-KlxhM5<3cZhCr z^ObYj*dI7#GGk&Vj$qiFj#f9w<{Ww9)G<;8RB`%PP+_#*#@6aLAlD}jmiO?cCi{YN zwyoPFt{t(Hi&Dh|(?bn~S_c(2cnFk*g`JU7_lz}nZ(7fiEPMx75NdANTr~*w3=N7Z zV*K3K==Jr~L5b@;3T`L>1>T2%xb>GpbKV|qaSxWDJ_Zd;6%kxWo5F)OO>TsyCU#F} zlH`U$HOae|Uk;zp^4R!6p@YALs<3cp=;D|7hx9axC%o{D1g3+ocJy=qGCxXNA>>3y#f<*4aAA-mOarSnVr7i%Djw z8&8bFs12{P+umrQsxoayb>lJn0zdJUX1)Kr+H}y^iptXto;r3FEy0tkBlYHNC|Hg+ zd*X@k6m$eJ`9eu$AYe8+F>F}*_n()jsv)ML{Le`+Qk?sOllc7XLM5AAgdc#=gJ!(D zvc>m$e(ipk?~b%b2h>QT*NQJdzS`oG?X@(2PK2y#!7V`s#^))nRR>^h?(d(w!kAgn z7h^>kMC;y5+o81^?emsuw+p{6NibJe$mpows}*T`CRn9bA&of=SdqJE7FB7;wKoxh z!~G%3JbJ}Ys{N=F0@Ef;xsxE(gbJ<{)CXit2&ewFM0}BWaXNCO^l02hKA1WvM%nHP zI9eHIb^d(iM7XfOPgE(OJtq_Sd%7Jr-VzM!QiLihKFk@p5~^vlkm70@yRj+@vLanY z4r6ZgTdhl(di`<#LGfVl~~le?lEhGP+SDLz&N771k*n`ynp zt}{~o#7N^-d^nAS_I!SR)ZcgnRHWvW<1v> zLcdSZahU5PXoki=1p2b@6|*%m^68YDRpd0s4`!$NsA8t$_4`9|qCgXIi$YQ_K^ZC8* z8)rI_S)%Ftx0(3@i^QMwIVI7zY)Q&VC&3?APq_}+*hT6`m12$+w`wMbIdXWF%@2N@ zw0BC_kFb4ZeZo@Aw92FXM33Wbi?7P?Ptk@iRQy0Z<;EBVDznLL(i>`9>T*<_Vg$vG z@t}nxhdx|gBnE|LMc@0KzEnW5a@fW1>lv$u#RC-2Nw7&aW!t=>bWTc$YwS^c$ZL5L z-jSLI4uhFJ3{!_@9p`h)XJtgM@~49(KH=|7a?0z+xR_2p*ki|?MC}@Be)koJ)Ofqo z%adXyy1qPrdK!-Qmcr#p@|_4}Fb5O1H*yw0jPsh*cQC=?{L{2%3z?xKP{KCkVnRdv zs`}4ckC6;0zS70PmoCoDWSGV;ix1bL`@T2`Lj@(c@f-ZULVOz}kC&XrO;xEQ_P4h-7d-q>5 zAT)F{27iCiA(Ontw{JSokYC461%647T)Q;vT<1m8V7`eJp!XN+cbn{JT z8>`5nQOAKMHS&#`ABN6I`ZaBDOUTEkVh=nutEc9bclJ)KU7C(!oAsc*oLAtYdpGIW z#}!CY9nXDl(Vhj$wIazCM))!&qpT71N%uU_aBe_6pXG|jd%B!0HGsXI78}awKO$bDq@*zxMX*)t4Py3JTTs%~thhBUpA!z%^E5rGX-rf3IqvvIgz}l| z$I43@zJ)f3adkE!b%k1Z@I2_{yy`G=^hCaKYaSycu-GK>!;3MS$2?K!M2Hbuheb@0 zK=B`Z^}SafBFLC8YtlyNr>b?AcWS+Isnrk3CyXswN^(cT56X4=nStDPX8>i4#^CCi zS}kslRguUAZs{qPxyx%L6`;PJyaa}J**ZelV*8xnQliiTXKvZzJ_4!^ldmEL7vMy9H=G#9NO$~bT}bB@*}NGXIGa<0>8^=2@GP2>9AY`=u;705 zRP*v?7~IHrUPw)klX!jxt94%3=PCo??-FvqM|K8#a0{qsHpaQfd_Oh~*HrwnfP2wg zdMFm4kI_#?-Uu}@!aF@1=2X{&bso#IcD5{6 zheNlGk+P$ex5*Z%1wM&MTZ~2SJC9=VP89SYkn)0=Tqt_5iCUz2ESc<{(!|NDt`d zN%OQ>-vJxhaIN^Sv7_6t%$0Lh?t!Ssn?`O5kW5|Dx6#=~UP!@v?sM(ZI9Pjs(tY;amME;SgT;Xb zHyl>UnstFqG#vmhv|)cUvCETxL8dA9bu#<*;r4%QK8iAR7*G0g&ps>4JEx9L57ie| z=yYM#EShyWx_EeK^MB)wTfij7%UGC()bFMl8Poteq_Hg68aWsq+iZ&54wu99iy!3z zf2vjKv`xbvB0y#Ifl~RFoTyALvm7NUv#&D;`vj)d*twxGQM)TRaw-vAqVK1a&ql(w z$53tg*G)R!fni-|_cF~i5P~x+aEd)|$EZ;wDH5^&F+>*5yhu7e5#>xGik4P^tOS(V zfJ}0>*{FBSgPgYpZpnGu?|%deMnUSOOC)1P1aZX)j!9dyqirz9ZzU($1Mc*og1mIs z5OTUit*8Ca_cDGErHe^v-90U!NbgA7wm#S%cA*)!!LGQ(f6o{q+^~gIu_qqpPqOdq z$yhA!qdrR~eUZe*>dYZ5xhOLIIUZO$++unZv`rS4S+#M&99lEZ)U$$A!Fw}1xROzJ zsSRL3n{HsuMeuXPmhF?n8_u_QIz}%ERZ?=+pN7CCs)X~5;!>LDBy5DCbT79>x%7+0OFI~SVXdzdu>G{e_OI+toe=?OE-Bd)g{ z3(5S(WEMIxI1ujXu^HA_+El(>k4afM?Wk)K9YYg;h_6dMF&BdQ2U(%HHPm$^k9Hy{ zv45ih7;*fK4`Vo%gy&Vdo3EXB=N7vk6$C>|IsfgJ<;n*|Yh$hf^+~FX5f2x3@5y&7 z=O$oTbRMsA;&C3vnh=i~S%e?8IBe&3d;ji_Vz6&=4x(uZvUn!;I91TI{>paL8RDhc z3rlsNWy&H$wZsfBDIRz9l#Y?xI@TA%YEI$t;Ip&-pXXW2&mKX@#CO)`*gCq zg~T|%IARpmK*I<8(pOck_#56UOyHeUcWGJ#*cs(8%x?8WqRpP|65~Q^ZzQYSREd|1y4^}68x0Fi}#Of~Vk82)K zT`S5(?TD;^Ze-+r;5MgdqrCp?j(mu~@e4z6;fZm6c=vEr)N>G7f^yQr(yaY>$CAk& z@?{ZPLMv>6x}@m1_lPFukr>GTaMR_Z*tS!I@c<1u6{xPNky;#_aJ7}-ac75VTp9SCJ)`^sJ43zb1Y z1Wl-btv~3MB?Y>~ANL)Swmyf@+>-?SFkGWnJ@b^vzer9f?n>3bTBFu}3b4XBQB=M% z1VtU_>~|#z^TV{I&Jtuj9kgu%%;2An)65H`+VrJ^dleZQUfG!E#erJ$f6}j7tY#x~ zTqBxi0)QFImGXe6+oR6NSoq(IpD0ji&=XEy0)uYw-YN-Nd^6FHyjr`4MPw6zS&i$0 zW~T0Lu5ALDL9?J^U_W;(n<2Jgc_^<;-7xD9HkC?J(gW4zF{=IT3OG)X9!()872z=s zwlb5cj);Eie@ICOSPb55P0P7w^39|>yQTZX04OP4gAN-`D|CFk;bBCiW0VgTS?|Yn zZ7n(c=F9*imsiinuEaX2;J@sDJL6LU9brFWauhMESV~)qTuAUmQ!RAlDi(}Ll4JT@ zAhgfF`4}Oiz!Ei-Vm&`s-9xu!bG5+nbVC<`%e^SstgxCG?T=`(z@xM znlih4k}N7CtU;8Z-*@=)lE(OKJ&`Tj}775+!9CJ zk`o2kO^=>V760wS40@jdX>Zri(V+pv zLeqQj44J^+K9(U2#|Eux?l)wjlbyE8JNJIy<%FB=x>H;JId^igF4ekdh0$TEX^oP+ z`Q{H592O4&lSQ(xG_y((AJIQl9D8;_AVorrhAqf5<^ymsrm!ZXXwSRYqio`wI9n8b zWBoDWp5LN;2>&7~Uaf#0UM}VkdB5*QUzE+?Z|i23>W8W3AdAfqh`PN zY?S}DB*GCtA^zNzPqSiON#riQXywl#xX{$vB!TI=stx5vZSyub#W3J}+ulf@(N`7L zIlj*3*brzTk8!Pv1s3H|1!J#RcQtl-Yx|?SdiIYO%PYCG-K+)5%{imRZ z?jP{>$U6DISIK{~lFk~~34@a4=%b@t*;~JW9eMCglD-Gpr2fJSYS)5h8T$Qw9Ogf{ z&_}_HdNoR9G9-c)Cwf1}JhVG3*n;)3*Rt*=&(AMdY(eA8T>@iK`BE`xvnPVHKsxI=UjUPX_RE?cz&NuvryINWz^rUE`Y? zUodId&ef7HTK{m$+yQI3I5(ZHh~2$b#obPm=M6KI(o)o5%0bfMv+gZ$`k<*tb$As> zqEBH0W6aCBTQ+)2A#TY|5wSg|<^Wl{R>5kUVpnHhFMFoaP37JcKT2iASTM}obN1tc;6@eVm5bk zoo8Y|pu;7(uO6RU+9HK&^UsQ#j z5+*J}BMtjQ$mdk5(_#7aXhYdoT*h#!jd8(}&m$pHR&Cgf{KvB*dJ)OEODNA^sb<@x zCs3IznP+@kr)CLFl~mo##=Ew_Jg&Mds_yq~jwK^bP=aBZR zK1DE{aMUd?=DxP)J>+UP*U>X{3TDjXur#FuADI=KUQS`3&=(fg%CPCOFY?Ud60`u< z2_mL6pj68})c>e`esGv}g%73nvszLU2<@y^xz`cf5QVR{iyvqY_IZs#b4=rIi$uXe zb-$qZ+JI%F-n9(%@f7;304sYHLb?t(6^@thUa zqX#0%T3U323XJHe55?Yxl3X9zfsO~2b+D!nGc|LpaD@!sC{r>sM z<@h`V5WpVM|II;j!3I}wA{N_6`a{SLFS<7 zL>v(Nk|I-ZgJ3epjk~12epUljSM&Iv&CC#Q_$ZfsCu!1G;&&@`8!Y9#_n1|k4(oNE z5K$@fIT=7TAD0(q-;#$o*qvFq*A1AOlh?SMnpSrA@rtnNa-y*jPkYX%n<@)5-fY-qE$6w6#Qrf9v6`P3BEqMz zME>lwpT{HbYUSxKr_qVLXgg1PQ+u!}X&XZ=Z5<9I?f>4m)+ipI&vV}E=edWcxasl` zhf{Y;(nRld{k&Yal$I#t1#23IuOCf<(;ja=GxiSS_1~UbB{uocTZLt*#FTpvBr+EK z-RLov25Rn!t%ah?Z{cnD=lKp|!U~(Wap{r{*a6WR+0BEt z=S44)n>>wnR^)3mP_%8&g)YIW79an2lOE;8RX5IGO*u~g+5_-3aLLh#KFwEd3q*e9 z2oFh`(iZ;ebYjB1(S}7g>{7!-8K{2D3q zkV5pW-?Qlqqf+kJa*nDtBkhUG2x90M57hvF8h42lUVmT{sNNpVXcx7d4^sZ_0s>8y zhX;FzgSJKvYL2$=tW&_iG`B|Gp*EhnLxjGY$n(>6?(*8}pnf&n5$Np~KlH?b{G-?v%)1EzFkijevwp{bIXAnaDP9IB?S%QjrSFh8Z((FJbg z1!qeg(&yvJWUP~9NXfysz!_k2QZ;=3?-V^uTg)l)oT-JRcYlwf=Bh7Nj`{io717GE z#7WYE&}>RfUu*O*f>s1i-NYLnpnrLZcij?M{L^7nwPh(jW~*S4I&28;;+Y;C@MW^@ zlr-VOarZNRW{gcNfpd>&_{r4(!-0W!Bt1Ot%wY5r_^nyqbP?aBqk0&#bpiNBGev0l zL!6f5mrOhED!yvMDwyvfKVmrBt}gdp8C$ytNxuA$k7qC1RY~r|OX!OuNua4>lFrse zJ1f<%h-c~wA^NU}yYOCv15bf#+H}qAs9e7tF7#w5;Oc~0obR~df*uGdConHeagQg8 z-%7sv8KWzEh|bkCU2WH?#~%r*d0ywM|bC#0O2^9i)8t@|9PTLB9gV>f>sE3>57 z{NWCa8d#*wlTKvQ}I>j!jo+kL+uXRf}nP?{;xP=%B-jD3Zk?egsRZKcUs+z(QI0je|yaT4?o!2KellJ}X%uI>j3?Y`p zMiOp!0TBphpNv=8-`a3PC3*{C|~N5O&K^;lfN``SLR%#;IKyS$xk@8(%;wL!jXYKx2fEx z)6>xiv$3-1zLTNO`cV;GK*>MP{%T7ED|uHVljOs;py zXhX}!iUN0uMh`;2F)M9$aV0~ETzhy+!)~!BKLl`)O)@jI5=sOK@*&0)Cut`umXEI!#?LF ze_bx%u$3gp?PrxblxWAW5!BeT6Yse!lV6FaHZP$WrCY6aks#zEuF*N#psEZRsGC?3 z6O5>62#l`wtSw;S#P{Qt5f8o0y>Nzp-#_&JNUCcgXM*8<*e*Q8I%Yy^V?Pl(xCBN>HamKabWB6jX!0L5M*>$u=@2)xe~Df>7jK$bp|J@ zQer;kJP5pHFZenv5P0D2Gst{h&$KSw5H6gsg@0R}9C~c1LS>sEx1TJ35Co4lF+zh! z+rmMY{B2Tf*_VSSbM6GAM&W@?MV@fUB#5Xy=|t$+N}X}~`H7q{)hIwg@ggNLf``mQ zufez8FYh*WBe(GXo4m6)Cfg~KMzx|6UsRHo;joKOTCCBZ+ybChzLL-^_fj*z@#y2K zj3fca0U64eA`D+=I^G@S%qFzxwmZhU4>c734Wd?qMrxe?P*YzJ>aH)vx#JgkJ#Y#k z|MVSCmk_MmUWXXJfJvq&#lUh==)Qn5^=T~{mtfU5`CFsKsk2a@rX63Dq2-$I4nXI= zA_4WvxSz(?HTm7%ke6kmOI%3{YaGtck*tB71+_hGWJX`=s}lD@I`+2Iy(f{#qXR9j zw`A7mqcB$g);yTcsd-fnP|BV5%r3S|fprf$gX<}qQSz{?e#%I6+!IP*7Weyw`BVJI zNb=#Dd{s}gc0?Zkkgr67qG(66pJ~;ja?aj8QGy=3)^#1e6Rj$f zmje(#V0y@p;Z@P1jecs@jprhnGe|Bdl#hp;8!%qwvA=*D=a5T%{#xbDazSZ!Yl2jw z__|AGifEfBHx#dZXke;mW)SQ&cVq14SevU}cT^fjR$rD{EoK^mxECkw7?Vz|sr7N) zH6$%YoNSO^wL=oK&3^s?$#|c&PQNu$W=LB11QoZFaD6-jBB}SU(F7U=vdlQ|!^sNg zGb!5n{wM^gUjGf7J@EJ-8IX}rFFbN6N_>`T@5yj%y>CZh-yu>ZSjwx7O0YDiW1Dn0 zCa?YGJ@V3!kM(&%6dqqLlWI#=;_*)XBlR+h6QevZ8TwieOE*No85(CFa&x{PXh;B5 z)YyD?$PkFeD^42KO^WAE>SL@;nf4RZ+B5}GiX2q<>U|#|`fD5v#)Eg$T=iYan%gR| zAWfWAv%Rl_pDa_(0Hz}Ajw#H?A@d9(V^$Mx%p#-@cNU!t6M-uwJY_5-?hO6#8Bj=N zGPBgA^bLtfeusJX$ZbfXo}2%zPMGoVdEZ(=A7{YtRGK*=lga>W98{I>9OFwpb0vFx zisnA4aDhD**8PE{)%mWXaqDV&RRW_U>00x;7|&IU!0^9uRJ%6V+F8EJY~Wyb~p~i^JA?RYvTC!RQM^m zeM=pYmh`FZ;@x?LwiQ#YkAu^ax0L%$TJYwBr%NuBS&pu~BxE4y+?KbecjcGo24#nz znIIUy7YkYPJtcl8M44@111w}`RTm*!c3Zf<<_x?ij+Nfq8{1ak-FrAri+qaP5n1=C z#;R$FI+ETx;aI9BR8dUm^C^D3tEb7XH!>9*GF<)isI3@S;K9uCzCS)~$M-i246hy} z&pIR3-yRG_W|aD2JN+@|jDIZFvS`QryY3tUQBSsMVPoQ>QnaCa<;{dL>(@778{R}g zathi9uH2w|@zR3;4m={?-HRAA3Rz3aMPm@TMEK<;TA==Urd!QO^Y#lo=j;EuTG>_7 zs2Xq8yUu4!AV{zMH)_-1C*`Cjv-uKzU`0J(iK1INJ8D;2E>QFmv`?=p>+&cv=1JFl z+0&{av6wVu26)`X7LUX|qxH)+QoP$nMuzxem7@$_CQ~Z!hKeCB3LVW1qIrd=Y~t&Q z!nMl9(Kr{b29ZGPlZRI^O5v&JUqMJub)RE1p`DjHW6O=ZNTkS7Qzqzm=nvu(E0kxX{_1)@UO1_qouTw?qu>$bhZ#++)+Ft2^Xn?PO^k$w zqW@%ieb4iN?i^b{?t;PhrUPyA7?7zDG*tKzGg=+T`|)zYbfOXLEU|Kg$KA+qq`K?i zRh(lY+Lq(}Lt%R*&l}OXty&(v)&~r1`L|oUVMponK)nugWGpx9Xk}A-1`E=skSUdW zYn3!^V{{Es5IjE-jxwG@Ox`Um*gkYOKxliglmtK*IDXCad`ctk7@Mtuz#VH*Zcy@d zJi1fjO$*!T&lWJD_}*o_AtTy$GfxwQYPYOdvIzMOO#e7>I@wxCoeeofU2NVPId{EN z`?&9(my^(b$D|>oK8mrV#JYde!-wtAw7dD+f}gz*+pnc1l?H?DGoi@31ODrsjVTG&cPom1f4V*n0$_S8nBRXZtpk5c~R ze_&yDPlG&S#issZ6^am+pI5O~5Vy*|wdEdRl*Hg6)7|=ZSzzYfk0}y;(75KTNYpga z9h4V}XhA5+R1f_;FO6IEFr2BM$6z!s4>aO<7A;;DHf0#8sAPLu2U&~eGv<$R!5jq% z(#9}yZPbGT-uheuEd*?_5$}?~H&L|aok#j4BJN(=8s3b$9o{liwI%ST#v?YXYCA_q zsVub5D`&WPN@7xTQzOP!Hji=H!WBi7f_Sy%nW5Wt?>KRX8%LMUKu~O97sTZ`*D_Kz z@T#-5=c?gjiC&IeSqVo&wFvXeFGR$F6ark)IJzm zS#*Ab-vl=`do~-ylz!u%(|)01rSU8=&HuVjo0s=w{-)(4RZtTdBocg7gHR?a_$0E$ z9SGr~c?Tr$5g+ZFFCPFGVpc?Z70Z$>hUC%EwyRmL?Sco^Tt_0y2F-je47&yQ{KUwz zskB|N({0GA&)Agnll@5MTz-BnBUD{>dwSuviP)&D4`}9eT{bnez>bdx0@2hXLkvEm zAC{LA%M5}SSVfFDb`GjhfAgvRJ+@Rxvf8Y`Y z3j6j@UD{!B;S)mT$@eSOF)7~V(T6=TL+*uYt%I3h)exkUU?#!gl?^_7`h5()U_>{w zJ-r`>l*`|n|5@>&J&}H-R5LW&O0Dr$B=MrO>L0*Ba*S@;i`_giAT&?x?yzCwyggn^^+8=n$(@M1#UrGSI+@_ie9MdFdervLHfYA?DI2ekpE^2H^pn@jfn z*BLtucR6@uYcQ^n{j3Kcbzi^H-#I5~r((HFLht9G7$s3&v9^tGL)>XAT|YLN!<7fH z8R9M_+Mvf6taAp9I8*tV_Q4GCs`AUmOr;?jf>{b^w%gmyWZm1=)m6`w^&psvKEf(c z`A8QFXG{L;mNDI3!AJY0C2whY!hxPVaD|s0PlnT<@*w6|}Og)&?*f7B|NQ=oG9}LF0Ak5z(+N8DHFl z?nlbPs#xMfK52iBwzvaV`&sy~ZO`KnCbRT4-af&~g#*`Wvubl9_sg`)#-=80b=bs3 zn%p(P$nC2aKR_>tL92Xlwa7#So0w63gT!`2rJHF0c6>c6tWNw@e5GzozE`s?J|z7` z>8DD2Ht%jl^S7`knyT-#5T)VWEk8#y?y|qo^XrYrCi~U!-8mB{NA% z%N`^K*r$akNWs84!r-!()AtU}K?+=5qhc!pZUE=6AhwfQU zNx4y*nR|#BwEH8AG=V66<2H3H?l3h~RgKZ=^d2-&@8#&!>@a`U_sCC1jBs2CLwyX3 z)##FEB!jjESjG25n5Q%+X3j?I_ob@6$7c&YgA7a`Q%HO ztZsZ~$Ntd=!cG%G%?pAJ)PtKieAZauJG1$%Dg-SE;(hH@giVAr+0Q8%-K zk%CMmgrl2PH)(1#g0S$4A`cW6DV{mtdJiWlXz`t&t>hM|qq)b4%5DFCPml{;KLj2^ z$H*m(Y zho)|ir)A=QV!UmiKBbY(!E|K3Z8xqE+D`(9_lY0KtW2T&yfwtuC90MhXI_N8Sp0p$ zMsk-AC=eeQWHCQh`2hur`-;JlD-`~dtQxD6!Ka_)uv%ZBzb&M}&bU2Te64|FYfNC0 z+C#8)6ohkTf*PoB=u9FC2F9RBvR;szr(xqpqDZ_Dv4+mz3fQSB?1KXN3{seJJ}@O5 z${>WpjP8L#y&k{RM4_>;@mdD3WsW~EkVk*kZ3E8b7tZaJi;A?_iS)97nvuZ`N2WQP z;;OSaelU|D{uVl8k>ZG;NDNoLB*{=uf%CbYe8X$DP<@4bsd3GY#Z9Sp3^b*3!&|X} zeF}tHtb5MM3$>`#fKHB-gU~RWW&lm{Ulh5@*t_nE@_Q^kM;OwRr81nDe^Exg0X~F( zh{W&mEk=SLP@9_>-BXSGsk#{ANSe;M@`Di`U5;kYTy6IbvT`>epR$co5F%bZSfE47 zprx`|d0FxvS5>hNF(eEacPSA9RaoG&CYzy4?=<@gIZ3Tr`^6V!+L~vNS{(DiBbv=gl)|0`i%Xf3q`mOY7bmPm(!e!@Hj_h zWdCLl@Gb_eq`w%$(^-gimnWWG)ln$2hhCISzbckO(oFGdc2K8u4k~K%LK~rAhSJs{}MQ>e}FoI72N0PUhbs z^2_KCf;&FM3(+4u@+SU=_L=^CXt>EB?2@#!lYXw?v;gI4rAK+oqZaU;MASqoYVIO> zoIX4J*`UJ6qyK&JsEdQNU57I5AFPt^*2b{eHLAnzO0rG0Yiid?*O&d87)BoK(l%l5 z2c0_Qsi(y*mM(Ya@Sz-f1;OaSx$ePSmS7Ye%JvoQwgMh3i*Vk>Cl2cf{ZYTevhwON zdHjQEL zQKx)2KF~iMSvVnP+v-75GNu4?$Iqh4c+JQ<%qMKkFYOOyb)NID${QF+%D!z7#b)E& z!$b%Kn`pPLWJMV&`x1=c`%{$mGRX!@>?@0t=J! z>Xkqv1IlfBAV?p_U571Bh7Z=~nH+%w)JGPcMRYa{HK3z!yiQ3By*D)>$Hp$iSJhm1 z=PW;o2t%#^z+Q5Sw84-RS#}yZoVVzT2fp^0pi$ z|4o{PrQzg&MH}4oc}=n6ZN(n0dng~~7Jm`|FS-aU2h}i?qD?UESmgZ(uHj)KhT^_% zfoyDCU~PTMZr{1lzH_M%=cK*ICw5%#gnF}}^oi1wYp@4y(CDlc^x~Wkq}W5NRByMI z3yQqBcBCIb7R+-8c4&9n19dFj1ifmKEmfFHi@9biH|;!J&LF;BUM;{AE+B5>{=}}7 z=w=C+qD3~eMy(ht+@o}Y2_8@tA@p`yv1|o1?VWj;Zh^Q{qzT}ldsxM=D~4qv2ds+q6ZhnMS;;zMNNQ7~H- zV`bs!mG*8Zi%`LyMz?ldCfRzGmA`!GK-^ZV+3@-{toCVF8+1jEwd;qNi9SsUt(a|-XvdHOfx_crDS=N{A{6pJQ1>ro~DIQ z5>Mr6%H{+Z`L+%a*3fm+An2>Og&md>=2BBRZk6YKlslBtPxeCO8ENq*U6D)KF;;u+ zcn@Flv1Q&OR1E}pe+pflUE>u2W!XGcC>bkc+5l~8Na;^Kvx=i#zzHmVHFZp(X+5#v z+R3$9+x0=WdoXEPRF3iV|Jt{%UiDfqqa~({FFd-ti99yP{|Mmi{CpDSd7F)67wf(} zAx#Tx3^p3wyrh^=ao2TZ;!$OjPY=S;u>4k)G?8YL32%f3nfInbv{Kt79J&95Z@@O> zAOO>~`M3uCEY%YZG>zyBq~*lClK*RQ8B(^ZhDUjw@e2(+6o!SfnyIEHT( z!l>&Xn2>gHMe~gz6_&}H84Wn!OGYj(*DN;mhDVck4DEC)PHfpy;X&2k#E7X1bTaL5 z-%P2;cI(>PRZXzV-IWOX0Ix)f9B7v1ZE#J>Xb44`5AN_^v@P~=V~KqD%8sh52UQ*( zj0yYPA$BUKomi9;Y#|aXvR5&={TE55So$Q%8#%tnzAJRhaP{FxQTl0@8u|m&=3<{m z=;J4{AdhKaCK_e&1F@IjjCUD>0KQ*&SLli5r^K7glONB?9KWMU0|-@#V}-&}!0Gtu zRVq6F3GL{S-#!&W6=xaB{~kAu6phj zJV}4(OI@yE3^HGSU=-#>uarqXbKy>=uSbjgq(i~xBk8m}0!K8gR(HnRo!$35RM5kf z-@Fd|x=U%VE1EmonEt}#I*+Q9va z)@P(?GqHYlE|)&4IWB1)k{W7aO`5S|rXO=oyb&Bv?(PJXjFH=&hSL1DB%-4K2?m!a z6%OO^eN`HkO}=}eX9lSzjtaTI|GK#kOj1AM~0Pc!8X^bECU7fR(x;rqxJAXecQHb2%1_ z6B)ns$yy(6@bkk%-!Nr3DWf^B5cVkyV~kziPb;aO`8L`Ldy-C$)_}`{cj;PAkf;Ff znPvZAms=?W%>COqIZuV!s9(8~KprOQG{llxcUYYB;63rXuh9G6h*j($n>?3K@G7F0 z{_^dF%L3Fi7~5q?Pocp!>XiO(#B5ZnW;qwq!_p4dcY7eo?^*Wtrb6KD2e}QVQ_a)X ze2ud+2zuk}DU0>eNu_q7CzvdVl#8a!`>WI7R)}k z(p~e}iSE~HvTncXHmU1x>n+5LmB`B$HA&#g2PxPTF6vevU_|7ZM6d}-v_Im(J7fm% zvIGC87v-^SKs4PAujm*E*XP%%IN(&Dhq8n$_UvU*^^{qst=ZW@>(S51v`-V|vAJa@ z2aXfSVN^&N)C(^7>mmIOeCrs%=_Exhm6}s+inC!BLP+U+kADjo37cJ! z5-dsMUdOD+-inRg!$xn~kP24h6m#VWAglhAT(fbCy->5SA|D6Ay%~ich1ic5+=rUO zGmzK-9=)V@}Qj^5DYbPd8UjJpI4|C@Qi%@#BRJGJTz(Ho=yL42Wmo^`MuIe z1!Rf}PKxuN6JP>Si{G*WXr@hMNo~*bHahLcp~TgOw39~rvI9D{@zH7kHzXZhOo(4T7=M%{2%NJtZ~GtGH%9% zkn+4{+qH&3QzL`lZ#AfsseD`C-TY(D+LzTmi~-274UE5TxbU2Rvh58SIA<0KviVo+ zmGaZ45070h;GhYcpPWIJ&2C) zb)hqgQ@1WypB0ASxhRqv5MPi*iQ29gb~LMmREk^#8qXP&I^sXX@gL6-^j8}$;l?v6 z`2PZ0I_wGe5@lfdyIG&4?&CFDxjf@EXnK^Bl%6oEs9GnW{H3yni-S^lD2=M+EUh0G zrPzufv9}xFIUV6c&-KVJ=Xv?cK6LN|yexS1^kk!~MbqyivonrZe+q5O|19bcUasty zD4bg9ZInX=CTJnX=Yg`p$5=zmS}CKW{YE^%HACGpzo8ZM9iaoT&1q9CGuAw| zM!rl(=bOZL`mK}Mx_sTpW6D)=OwVSITS0hM^{&EoFu`AC0k@vFvE;y*Z$thA+qzus z-n6WW!N^!!3>ANt!H94nmellFqE^Y0nrCJgp;<}yjlMiXKNWNqXoAoNRmCy^>m+5p`s@~ssa+Xr~1N})sJ|dru zKOF1iXcnKsa(6HN=d3)}I{}f5?#sr=Z2f0WIj_jy)Xya(7IdJNvU( zIba|hT9hnLMBG&4Gg#ArAdhV~=a>R(xM|?Q9^wJc=nud|FOmudGLSBe)GfDbHdybn z1KWz-VlguCs}kP0BM_6HEcJ|V-YDyQM*;vI3w22zG1QHbIo=aD?L^G@QA=6qc8#c5 zDoXtLA)NSNi5v~Sxkm65VpY%Hv3IkZW7I)2O+S!A%KV6~Jtr)nSs)$({;Pi|tHh;k zQnO>rVi~yYda%%!9=ov!&rbWYS{uq^Of&xxBr@+1#}CxHp3c>eo@)%$eAP*273&R$ zLA}{Wqmx-70IFtg1nLHfb^6KE9Eu|wHe5Mds*##$15$1+FKx~=imORar!RTl4jh&@ zVTPQ;N{CNmF$`Np`D-+YFHdAJ`$7_+cHwYSgsubuuUelBm?8=?`IHVrJ`*rN(8FSJ z^-{}96(*)5aeJA=gV>&^cBu}H?UuFKDzF|Y%|-@9ymhMJSuMh%{b^O^JZ1@`tu8OZ zLZxPYj%a9Bz!Sh>+hO6D{uUdv9O%y`{{g0&A*{_dz)4Rreb)Ppq&K+ z6|1t!o7&}H=t%E^2*%G`qPx@9Xl`yZ#~zXE{%CXfpYOT8Hfa5kEGJD{8(ZIerIJ+` zZIVDbjG0forC|;FvCgbW?@uEV>k~?1jXU|-0Y$*z&`g?TWzXup{H9xR5!aW&Bv+J} zyuW==1O7*N+Yz^G)u3A8ILY=Cba)5@zJUhhzije6P$lljBoMc;`||Vq0Ug%FzyUvW zUD+880QN3pcWb&sc8Gb_K=$ zNbiiev_aKsU8jR&hTXag9YAzTrh4FUJdxXDBB(lvzH{T>H1x!mHL3 zJJiNG-g@>s%j+V0YmYx+NV|S^!sv>!;Ro(6WB|$kR>39qi9ESY`X?;!N+X7j7h!hF z_jHN6o}hwl;(l@t4JUirOzl*2IpcF|`aXDsUGQmKakR z)nybEUy40s^+jG@-Dm1_l`W{m{;mrA_L*Ut5&#|XU(NLx9s6kYq(8?RsqsF{iq7j3!vl!Gbt$f+lW&UGo|Av z3Ny%Pv@S$^!}S*V#cM1hH?#udLc?5&rhjmo6|Xa4zz`;zbNdHlPR0ESv(dTnw5+Pt z2i6_NF#DLzX=SxTslijb?Ibup=HO5o++{&T4rXH-93iHjFe5=-L>RFQLyZ0VZzCvJ zVGj-Z^&X7Nj@#tgLVxdJ=p6^h5P*E7986EzTHDsw_1wm*=1r_Y#eNMSBwp=lZw_dv zqR^77Xtt8deFHFuenX1ezCL`U%>{wcypo>U|}jA?PA~1Cc$5i)S^pqz8C@ zX}5O;H>3j8t$r6*@@6(Ns*`d0q!)DpN{BPmFmhSc^xqdS<*&obC~!ri-_TFOwt$J3 zUHXDvIG_fMu!NGPG@AEYXq5;EgkW!k0Y9KhnTsAG6<|6wIi4JlHc*P`lBG+l1suPg zyG=~9l!tMHY>aHFgX{Nl%Ha=8TqS0N^lCzsyD}G?G8L*x8R8Pcae~(-TE%+4b>2U~ ze$|geGMs<35AXU|dK9Y?UI$rdBbx0zCYQTXF>}|?%GSNGNY*XQRTkN)&YrfkoL08k z3II57!LD9wTepH5Jm(CpCE!wtEit;a+PeOj``FqC z2IEH(fYKE0McwTzyD7@}CNX5ljvaEWIrbv$qOFm$HnZumy>U{Z}lwdJP@sZ^- z#cOB$_?zz5=t>^aio)^|*4BULGOF7YncseSVilt~Gu_8={jQjlO(FOf&94wSPR9xV zAvQu=t1_iC4Ek{_s`7sN1mcPHp~&2^EL=R?fCbe|{a4|)NO%8DeXHODn#t!$GsoXo ztnJme+gGb$uKW>-!xL{6NiB%dT1AjvuhNY;Ju7qR4N!=+n`a@f7%}&n<(iE5q+tu3 z6@-tUhNmNl)GWZ$-@(^QSJ`!ePD&F0b>%5rX68V7HqcjxAC{UZubxo}oR|FfAS+4@q+)d2jKddaJA_hRe~j5`y_40H23Ep>x}{cS*G!UcLc@RCX@*I7N{gIT8fU9L34w>lKH*cgt&gLT9l-XjbI$niX77k1r zY?!F$3TEAU79XH(MK|?#UB0~>@{D8a>fmU(@1EVTu}#`O+bRYfxrWiI_7|i}yn$vp zsF}{*QYK|D-m$xR2{g8bB)P`-JI*e6w67dlu+6$^50dfj=(tAi2ng#P5L(GEMR>qB zgqxU}&9L13$ML)AJOw~2oX3&AzA2i1m7LfgIWCInF1x@J01tn!Tetkv#jd|_B~jrk zw({N-`()U9eG8=R)T{mo#f^8NuKvNnT}NuY(91lZO3}plNpYv&!2Jq+n{C9ijQw)X zC`iI0|MJjbavS_wUCndmqD=$d&K;nd;ui(W=(LBeq7<=R<>T~taG`DlMVnUFtZFV< z9GqvyC_jm5VbYhiw!n==E{|hFayZ1vzY9yaWv;MC)(b}YLpfidQsMDgh&@CxxR^iX z7e7H5THPOOQGeJ6qx(1Bxu2?g{BN7RW&xZP8u_vs~ zMP7zmws=Fv-b~rS|xms3^RKkm5T1yD80KK%B^b)+SS(N>~aluvN@WMK-L>6@>9 zn?n(IG{&{U{KVZ`XC_Fo(WR6KV;W93MsSdC--;~8&fSc*lYOjW$Ty~X{lwMGl&G6; zU84xcdhP|Kc!AR!)5OQpO$dbLU=s(Re!%d0`%52FSurqz^qSB}5L|ZpBC6q9|1OXo z4b7KJxx~tSpQgMjon%M5u0e1p25Jf1DsVj0-y&caxmDk`<#ziyaw~y1o{=c-Bw09f zbd;rccSi{Em4H@+(o|ZgPc7^zI5=<@XgOV1yL}y^8Mx}rf8*smr@~x&xm2Lnel|+w7D==>9%4tqE?%y(I@k~SmnsAsm?E}tJ~aM23^J=aVVTg}sTH2iKb zUwq9{C}p-JVhJiP^43aAFW+#@3vj8bHdwpHcCTOj5F>qa3iO!lC6w0{xA&hKm;3+2Mg$ZzxL!T z{@>oKk2b1o@Z@Jsq#7~#TN|q3uZSgfxmj0j1Nv%?2-+5wEvsZ}JUY zLKbiO@${v{&1VnO_OpwLSOQ(BH_cOg@KlSC;%d~O*_s=yD1n@lxl%7>$NP$zu&-d> zGd=?o!d^~Ju`yWakwy_uzTnxlf}z4;Q*2e!AO|s?E0MtGUvHKxMO4ma%vI<@@$$e^ z#m2EZ0CC7|l+n4+*=i4nRuXszI5=v2VHvm;Wc2xappT|Y;)-e7NBl5t>)={K@?|oB zNu$+b5$SpQaFrUFGLgHv0CHZhY4>H<|iWC^K2aCK$CnvVEi2LbZI$?NZu-#i_FR zHieF|K^S{Q4FeVWvmrBdbCz#~CT!)pAxMm2|Gxrz zAk;{6!_Kjjo*u{`S&f}3k^x;;gOB$&8^V%18Th;Y^+TBBcbC*ene_6z}UZJgeI1d5*}@*x(`f2>!MBl-mDkGdST38+$x5Hn`n27F2p;{yB1I*#8!0to$bX7<^sk z#3kg0Man&+1$z$c4vdU5puB*7fAOJh^L?Ax7;P@V;Vv{T_AP2+zo3hnRPM^-F_Z;2 z1TxA^lH*Loz$QKWLe}aIwn0Wjm8{K%X4!=%Pwmdtt|N^WOguINJOflF;tOEf1PTFG zg8U0J4p4rbW&K)OY}bJ`)9hHa$npQ8eUKHmz)aTHm0#}(tR`%jq+>(YX#WD)7USYN z*T{-O3T*F2_l#b(E<0JAR%At>r0m54!Aas|{a`GnA!Fy)asSkfxMi!9<=SlHA+_)4 zXkulQ`Xf*EGFE^(hv~e8jp~Ac)_%V=*RA=5_uZezO%4Zj*Z*}dkIk^fHG#>AV@r62 z#Vv+77QT+W?hD(Qjw@IOrFj%@<=L_`>R!7joYPfx&%J|803imb4OhHifth^+Z>vvX z0DT{1tZv;WE6WOSaStxZLBQ8@cpn39hQX_L=`yx_DUvb1H&so_L(W2!wq6lZ+j;(~ z)BL#SJe)W2zwxk8ylxyCojV_A`9WX0L=hNiEQYp0w@~(^EhX2Hly1jET#oUS)HVFm zxLtGfhi2O#h;JmRGjKvSMdf2FB$3}&AEA`L)o@-2;5~y_1_uSh8+b4N?4MP1&Fwc# z+@p+VQEv`}V-Dz8{i_l13IWnBjmzwmuoI3v4p$odTd866Qgc(g1frV^LDThXkqN!_ z9mEL3kyB=DEB#LnBfmIHf*0nwvh|v=r2A`tOlu9F0k!L`g4wF=1@O}NHibm%ax7BM z8u^8$SWL~*y|uV84@#1yafY|HiAyX8rkH8mqF5gN`?0wNYXHQ4#MUDq5ju3%ac62) z>*l86aYo)%p2*<=-!~e~#9+3)k`X4>WBZKxA}rp%CP>!ZWMSo|xZ+M3_`LET$f1re z>_Klqm;+ISdC(^rNO?4_X5NL%PyeHyqWT#&%PcrmukF@-9br;^et0`a%uP33Q!K=Ge*I z$Ip=|3n{(CiOSVHO!2Nv}d*FO~)fpWJ{z`Qb1sfd1yR51^7-fGj zf3xLW6jr~NrRb}ZUQ@WicoWQE(1_YhhN$D+hqMo8$tC6A=Q{)vGZ*tC3{9WaJS^z2 zyMi{#Mv8jzmn>e6lX{3u*b{{p?&5wDE!LykG`^Dy@O|Lo? zxRQ;2O6~y0dxHmVXDK`FH1xTD@0CT%rgWl&6>Z8PJ@ihRN=SUNxusSf3Yn5a$08To za*-v02Hp2EsH4c|ur6=d-sn)x?wDxYFUcX@WUs(?r^KdHxn6~>lvOFNC4t+1u)fujQ{!)hp23qSthYdgZDtzA=*iSh>yOr? z8nJ%xs=grp+Dx;4@>Azg?S#VkXW! zRJOL+DyWZ^wR|wZ${^=zj{JtAcUZk&zJj5qkSV!n^2LXn`X0s^IYK>dmDjCqXUrF_ z0>(^1n4Ic(D4GGUilyW4y;&KrMetSfl2q7n6mcNBE`%foA%K1EAU~Wfw>*hSZb30^ zl&>jIfRzlW1?TYfEfyQcB$IL(X+WePoxBFOgBY(Sw(h!f1+leh_t^CaI-Tm zCa2$d%IunN$b0UZz!rOY3}{T))97(;8mwtexU{)7;O9=6b+kOD0n`+dKCRE+$iPIO zf-2?qSbe-(+0yJ+GQ~QXJ98w|_THsi#ZlN+SP0QZ8FdhHaer!GeO|v{))&vP!P?d_ zfo0dDxjmC6n}s3}4t85CqXlZ_mE1}C;-Z~EUscI<3xSMM)AEKk@Ec_L?!kGgk5UIT zS--_gBR>A9x+tva$hgYs8#Z(+EQEt>d))H?fG=1M z1m#(@5i^z3DACL(jU!jAD1UgPirg@q75MS+Le?EPv>DdCI>na0foEwyIT^H{_XJCY z<{8M?06gc&8DHXf&?F59r?bphIk;Cv_5K0_PG}bXFF6w1|BxdwFtIWJ*M`K1&&I^Y z@ZZz_btADeF);sst(h^dpvuYDE35=KLWg+c<D>z}=K-`s;E)n;R4@B->WDhT$> zc?f;^%<`M^x?180v!2Kort<*+? zZU{(F-LUKff92UPR1cuS_!Itab^*gKxA=F?$iL|s*YrVj|LtS@x64lVB-h!u+=tx1 z=Qo5;kFkFQ6X-Rt*UFETPJ~ikRX7~?!v6>)U_WL@IEEO~z8tj0PcIh#OtUX{j-Mad z&5Pi?xxf2e@K-#Y33E6ukmKh@Vb3jd(?&H^2nA7AR-PSG(|NzI7rCaw++z21&uy*P+Pm;LekI4Rw(#4c3p6upFseTfI@-*e+d-g8DJCg zt2ZE_jOhvfjm sIHA^;E%b}CfE|XDR9p>!INmfRz5%T0_w%(civyWI*5>9e*_E+ z*yhlUfxY108DFf>jjxto9zWtKU~^h`D?Wn!z1vwnwbVAaApE`9+~3k)4nsf}8(=08 z*xWv?A8=)Pes_Q#k^t|*gEm)GL_{E{?GMbe&s~cr{`$VjH~0$9Eil03x2lazn-8^N zTR$!T$J_TkpdU9{oS_Kegh6i?cWI z)32yIzrBAKq3Bc(#zakw{J{@dI^S=)iWLRO$>n3WoDTVG6 zObc>u9rYTzSpXl>4=BT(KX7mUZJ?|B$ar-$Eg)XCtk;xv`gEo(Q&B@I}D&z5=hUR?av%Uk4u9-xk?|I`i zOr^X3NS12^=I()yG!bI~RmqpUueCvi`WeT{7|FSV6n}wZe0$ zmr4T@GGlvww+3aE_(S0#fNq0*f-v7alVGU>Y&nADh-(vewNyEv3}~0K?O<;B?Bwt%toWfLySyQC9=-r`)V5~x)b36P7F?0D zHIE)6qs)?7SH}vwz((LRT|Mu*a(PqBCo&xLV6eq)c>EqXr-dEm7gr?^_D`E#^tm1` zY_(C&fERf*3I9gc&SM>nJ9f*38}pjTR&S8{>|=VAN?tiqozGETwro8uUeI6TJb8|d zcZTbp7chs6&nns0%t=XGT+C~L`Rs}w(9z@esXii-#Jc;q!VS2wL-K_3-T4G^Zc;gm z$yz|OUNi8jWWmGY+KNMM!V66)C$(B1LEu5@D=bvMDJ(X={2(=Jo+p}hZobvX7(z6U z3BQNOF7au2mvIqcj_Y;qOP99qA&hU}P$1V2RmqcLNHzUY)t_{D`Z@H^#g(4e>8>Bc zV?v*!&gZM9Ltw-kMcxZ3X+<`e5Og(*^WeECL9#0j9X^AE`ESlaJy&geCy(X`3HzJsr#>VhecYbOEpnz z8LY_rXJ+5jAyf0}x(nV-u+6>w+jz^gZ_lq3btspr1cn#@hiLx!@T18{_grrP4v&#kj}XHhp!NL3v=vxUbXHd#>?Ay?WKeM8not20Kogzj*#*aR~@L+ z`k?yG_HAevOaL){)8ZDYj*i1K2XWCiRDu+XK*E(e(Ft8va4G#V>`GetfJrU`-NRGW z3d?tDCd|q^Z!3^C2i^M)gR8An-YO#FwPEKUq`RO1ni#Ur+?EJs=(o_Hb_))S*U`-F zP7(_=Z@H-|+9b}~nLI%14e2|tGq#ig`l*HPo+*4ivZpKtG;Ax$_yS&EZ6d%r;YBkm zgICRgjZT$eMIn_kW5t2IjS}-rH4FcgN=Rz^V8&iQebxQnSR-7@5F6H!8sU5xf`&o2 zI!Xu`w%GFpA(Umt56{dJXrSk*xM;)p#Dw5)LKK|_%#D>e*p53KFWHG6SEP`j6vgiG zWYpVNggBPhR=PvYOoV5L1IWwv(M;rzrbt;6%YNEM8gn3D z1o~%2-P+SIv(aSgx5C<`PY*}cK%s@aU3n0);a@@2?r%i6IS9~cjt9x(t~MlbNi|dX z6_ekG6=3cHC38PdCX51^xRa{461?2s)=6bhwDKe)aV2CkKW-F!|X#@IUp(>B`AgONX*Ph)#g*i zPgUGJ>WeCmzZLJnU!CYxPNDY_*88>@6|PKp@T|{qcy|=yjJQDtIE9qmPxg9NhbbwV zN>o{WAVwq5vL&QR9Wpryc#=P=Kp+i{Q^`=uaWL2RkGS2t7lOcs-_S={9NS{6^}Dip zoF<2w-3{N*oxukh6Y*-6YMD2Vo+9#PkoQ#HVGqehQHAZ^83W)hW!9-J4d;Ab3C0Wh zc(zI9r#`2tMK7#b$UqvLY@|559wov~TTb_`&k9F8jjNE?Bexp(N@#I?F zb_+OmyohB-Of?|Oo1A?tiD{PQsl=C47CaG8x{D(njSpJ@yil&`R8bi~stRsKhi+rVBn#%?hAM=;g+SN_Z=PC)*t!ZS>^WTKln8m~^_ zHp&0vTiXB__)p0>>OnhRSKph@(=3z%vjG2kk#v6b9+bEy$~J75i|QlEg;d~qBH4VD z-j#qFjOV$jrBV;jni1`lK+LV>f@tKxGZRwyX;k|MOWm)04xv+?=SDIXA}IceO{l$r)LVe4lstd|1Q%by>`ikWze3`hk!6J zfj+SiK6kYJYtDQl6I-nend)?|Q+Zr$ztY8+iZ?7p<>-(BNNQflAk5Bkxx5ipjCAs? z?>d#)F(kK%DW#h}XDNOxoJINeKa&oI*O7<7@T3`CG>gq@Y|tsU65k(ETk0IT0wl+~ z7$II*$8_%%cAnl0Z%|-`yylbi=@J9xOY65%s924^pdxOO5WFdPzrg#Sj0-*r{+!1qoj9w?R zX@XMq7lvs4kYK6An2*T8e62jGwJO1M!KC1$ipnsk-;ZGayQuXqI0~bqnN`MLXP{-dS*yf z`?cZd!^#dLs3kp9!V_}uSJU~G(FWdlDXwsF6Hz(a+DKk~fyP4KFB+fiz))YOAiX?( z<4Q2tA2g7=j3);b|8Y+WEyLqabz4xQ1`857_=%QAsL_VhrgLccMkckJ&q?6yxp-w1 zNd5&zCY(?FsK6<|H!3L+SxLKk1Ta+shu+xrOul)qmG z5%nEO6Z`&u18W!}MO8}f%We1(i6&)>`P~;1+~>K*=esDrJY2FEA6wU5KeeQ2i-{Yu zZVMu6P#B!tcB|VUH{}^)U(eX2^~&_IOo4qbl>XMb+2bzTGHv#><2J;ha3IH!He#Tk z^QuE8k?CM6?(+7EW~43TwdcEY0?sU_^NgVNzW;RVt_%K_EFV)KF#3 z?fT??`0n8d2nuns15dByKG~e~;{uFI^Ek;_dk@~-_+t&yCnK&F^80=!w!6ZP2GX3L zMkWpZ3C(q>?AyNlOhx~>j5ljRJhA>X%yX(QgnQ#?)-8Wt2-_2r&*{JxrGLz7NHg6>K`f|#=E+VAI_ASHs&5AXgEN4?9i6%k zeCh+3$ll3!U;_nT?Rk?X=&qxCuYp&s-jw^BxsbItAoIjkt9&ZSE8xZNQl!0#o@ zQZXf0NkLpOT{GD3aHVV_{4igzDKX`~%gr<8E^3%(UuENj|Ft!#7T5Og(J%DtiiIt^FRb+;$!a`WQZ$(4WCjk4I~*i~L2lZt$&L&YJ1&pvpRuTC(61lLTM zDThafSDyzisiWmOEPQ6Ya))BM;KW4gg0JPmBt&i~JHLW-oth-7nc@?6kfMh1K)(Lu zFPeeS8Zl%F+`V?)SqzVb4@@iJHZqb*^}*Od$eUA|F;^joF7QLRWZ6Gmne`so?Cf+$y zLiIZ_{hLM@emT6gf%0fsdrHR0Q8ahYubWja6)~;s`tw&n@5eEvKVQ7`bMDw``sC~E zMC6M8CfnX=t}+|PSpH*AZEMctj}oD)rdaU5z}d~r&4Dg85wQaxZ)9A3q^_;*UCQy~ z8QJab`i=dC1PJ@1FfZf?fjeXKIcp56gUjvv4b;K{DC!sxcYK^^Nh-r}Nlj$Ra4XQI ze*hy~f#!gN=}nC0g7~@L?ZR`t`1-GW%{vBO)MWLJ^gflfh%4x8RcRbC=cavi$2K|O zxq-E7-)od-r_W+Qn)_uLmQ}@dPG?j1=6>M|UN45r6a=7dqM0C3?^&FonMNgH{qaK0 zPP9zeo|0_re#{0u45xBi3L2%QE3K2!7M&<3=}Uw66^?2Zj%#|in~BS**@jLGoyp3i zJB{L#!lLLA?P01^3s;3Q`=CD}O%b>=cAa<{C3;#ZaGwgu+G4Pio-h}Wb{8?wwTkaw zicB<@5^>)R22Mdu&F3FPz_0x?c7Z2d0lE`m)4Pd9?YvrwDkRJ#vZ&safF^a-5XeaVBs^xLE+rB>aDutNXMU=5Y+_}Z7(G<<}#}f z4Nz98kW_-wC$bgBqs3*ieORsJyb;B_@f7$u+e%1@2UJPp!Adv@3F`2;a}Vh+mlxYZ zQ?2JMsaau(M9ZOOE7Hn!A!fShAQw%wLuWq|Qej(WyuHTp*iPKWBDR6nYwG0f0kyKI z5Y)FECf+!Y1(MgCCsKi(FnE1G0G|8oOfOsX&2v*@1@9x)ji`Vo9Q^a#l>!dx7#!8k zbQ+^&u(YAfUv;oIe9kHm_IjFG_aW>AowW>?*M*D?XS16ph}C|T_Q}GkK~YBkV#LGe zT-quNs+}W#qB){>AAxcvP&3&L7+3X4lI?IsKSjhhdzR{q0m+Q(gDRTr_Nt+NP-@Up ziLTXv^NX(b2aeQ8*X-fW-3L#JrSI5BE+V!Wri@Afon>o7`39N?YF}x%#VddNG-N4A z)cpm@lC4^w3OSr;AzyxqWu3f_7$*o zG)vZI=9pu+W`=8KW~P{#nHgecW@cuLnVDi{jNuw%j@gcXfB)`Vt+Y?tm1ag$HPzjv zQcF{Fbf!u_OqL`@f5S&3RiF4*O(xbchc9lLooqg36vv0S)>SCxoncJg#NhPJKpUC* zWz_^*9FI^#PAG-9S3>V-iS#dG6_l@U6Abj-F~(3aXw>#K|91hJ~Q| zo6eh^c}lGb;yfoy?bV(?e;Y>?<+Qs}>?dDez!mJ~)qDKZ!QZ;%?KEuz@umxLSVrtr z+-V&4s*fs6xxA-6Z{DvVS7|I(?@GIfquH@UGz6nXUpWZNV=KaR6`tmN!`ipSkd+61 zHo2Kb8<>=*6P=5#iA}_0qDOCb*l6%|)?=HFrPjE}WpiRcrfw2Iv28EAI))E!9nap> zL|t|_aM&2R+zg+2$nq^ZXSAZ4eZ7Z|_7a-IV-RVu$Yn1uE*}D$63v4};&0CnQunt$ zR~uEzXP+QmmTPl(Ur13{9vks%k1I5xEdRyu2Jb|0{EGO%@P@)EKB58;zfnD4*N!$E z8xYo82^*L+{Q1Va(pUF&v(h3Gamdpx_ElwqJ=awPjHcuc#aO;^Vww&^JiV?1$pa=% z4(=Kb-lRk1>RT3vfrd;cS1%Zuq-MBAk

}%Y9T_Mn_+E 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 literal 0 HcmV?d00001 From e33ea8d55c0616498eaa8a98c5852340ad1c5af6 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 14 Dec 2020 18:09:38 +0100 Subject: [PATCH 086/142] Finished documentation --- Makefile | 9 +++-- README.md | 7 +++- src/catala/catala_surface/surface.mld | 3 ++ src/catala/default_calculus/ast.ml | 8 ++++ src/catala/default_calculus/dcalc.mld | 41 +++++++++++++++++++- src/catala/default_calculus/interpreter.ml | 28 ++++++++----- src/catala/default_calculus/typing.ml | 16 ++++++++ src/catala/index.mld | 9 ++++- src/catala/literate_programming/dune | 4 ++ src/catala/literate_programming/html.ml | 12 +++++- src/catala/literate_programming/latex.ml | 11 ++++++ src/catala/literate_programming/literate.mld | 9 +++++ src/catala/scope_language/ast.ml | 2 + src/catala/scope_language/scopelang.mld | 6 ++- src/catala/utils/dune | 4 ++ src/catala/utils/errors.ml | 7 ++++ src/catala/utils/uid.mli | 10 +++++ src/catala/utils/utils.mld | 38 ++++++++++++++++++ 18 files changed, 206 insertions(+), 18 deletions(-) create mode 100644 src/catala/literate_programming/literate.mld create mode 100644 src/catala/utils/utils.mld diff --git a/Makefile b/Makefile index 3347bf4d..8aadc270 100644 --- a/Makefile +++ b/Makefile @@ -44,10 +44,11 @@ build: $(MAKE) format dune build -doc: build +doc: dune build @doc + ln -sf $(PWD)/_build/default/_doc/_html/index.html doc/odoc.html -install: build +install: dune build @install ########################################## @@ -175,5 +176,5 @@ inspect: # Special targets ########################################## .PHONY: inspect clean all literate_examples english allocations_familiales pygments \ - install build format install-dependencies install-dependencies-ocaml \ - catala.html + install build doc format install-dependencies install-dependencies-ocaml \ + catala.html diff --git a/README.md b/README.md index 02661c79..fe8333aa 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,12 @@ See [the dedicated readme](doc/formalization/README.md). ### Compiler documentation -See [the dedicated readme](src/README.md). +The compiler documentation is auto-generated from its source code using +`dune` and `odoc`. Use + + make doc + +to generate the documentation, then open the `doc/odoc.html` file in any browser. ## License diff --git a/src/catala/catala_surface/surface.mld b/src/catala/catala_surface/surface.mld index 394f656e..4cdf7de1 100644 --- a/src/catala/catala_surface/surface.mld +++ b/src/catala/catala_surface/surface.mld @@ -8,6 +8,9 @@ The module describing the abstract syntax tree is: {!modules: Surface.Ast} +This representation can also be weaved into literate programming outputs +using the {{:literate.html} literate programming modules}. + {1 Lexing } Relevant modules: diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 36c83bd2..5080a7dc 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -15,6 +15,10 @@ module Pos = Utils.Pos module Uid = Utils.Uid +(** Abstract syntax tree for the default calculus *) + +(** {1 Abstract syntax tree} *) + type typ_lit = TBool | TUnit | TInt | TRat | TMoney | TDate | TDuration type typ = @@ -68,6 +72,8 @@ type unop = type operator = Binop of binop | Unop of unop +(** The expressions use the {{:https://lepigre.fr/ocaml-bindlib/} Bindlib} library, based on + higher-order abstract syntax*) type expr = | EVar of expr Bindlib.var Pos.marked | ETuple of (expr Pos.marked * Uid.MarkedString.info option) list @@ -86,6 +92,8 @@ type expr = | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked +(** {1 Variable helpers} *) + module Var = struct type t = expr Bindlib.var diff --git a/src/catala/default_calculus/dcalc.mld b/src/catala/default_calculus/dcalc.mld index 9c7bf6da..8fba41c9 100644 --- a/src/catala/default_calculus/dcalc.mld +++ b/src/catala/default_calculus/dcalc.mld @@ -1 +1,40 @@ -{0 Default calculus} \ No newline at end of file +{0 Default calculus} + +This representation is the fourth in the compilation chain +(see {{: index.html#architecture} Architecture}). Its main difference +with the previous {{: desugared.html} desugared representation} is that scopes +have been lowered into regular functions, and enums and structs have been +lowered to sum and product types. + +The module describing the abstract syntax tree is: + +{!modules: Dcalc.Ast} + +Printing helpers can be found in {!module: Dcalc.Print}. + +This intermediate representation corresponds to the default calculus +presented in the {{: https://github.com/CatalaLang/catala/raw/master/doc/formalization/formalization.pdf} +Catala formalization}. + +{1 Typing } + +Related modules: + +{!modules: Dcalc.Typing} + +This representation is where the typing is performed. Indeed, {!module: Dcalc.Typing} +implements the classical {{: https://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system} W algorithm} +corresponding to a Hindley-Milner type system, without type constraints. + +{1 Interpreter} + +Related modules: + +{!modules: Dcalc.Interpreter} + +Since this representation is currently the last of the compilation chain, +an {!module: Dcalc.Interpreter} module is provided to match the execution +semantics of the default calculus. + +Later, translations to a regular lambda calculus and/or a simple imperative +language are bound to be added. \ No newline at end of file diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 3d4420bc..3ecc5afc 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -12,14 +12,30 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Reference interpreter for the default calculus *) + module Pos = Utils.Pos module Errors = Utils.Errors module Cli = Utils.Cli module A = Ast +(** {1 Helpers} *) + let is_empty_error (e : A.expr Pos.marked) : bool = match Pos.unmark e with ELit LEmptyError -> true | _ -> false +let empty_thunked_term : Ast.expr Pos.marked = + let silent = Ast.Var.make ("_", Pos.no_pos) in + Bindlib.unbox + (Ast.make_abs + (Array.of_list [ silent ]) + (Bindlib.box (Ast.ELit Ast.LEmptyError, Pos.no_pos)) + Pos.no_pos + [ (Ast.TLit Ast.TUnit, Pos.no_pos) ] + Pos.no_pos) + +(** {1 Evaluation} *) + let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked list) : A.expr Pos.marked = Pos.same_pos_as @@ -289,16 +305,10 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = term was well-typed)" (Pos.get_position e') ) -let empty_thunked_term : Ast.expr Pos.marked = - let silent = Ast.Var.make ("_", Pos.no_pos) in - Bindlib.unbox - (Ast.make_abs - (Array.of_list [ silent ]) - (Bindlib.box (Ast.ELit Ast.LEmptyError, Pos.no_pos)) - Pos.no_pos - [ (Ast.TLit Ast.TUnit, Pos.no_pos) ] - Pos.no_pos) +(** {1 API} *) +(** Interpret a program. This function expects an expression typed as a function whose argument are + all thunked. The function is executed by providing for each argument a thunked empty default. *) let interpret_program (e : Ast.expr Pos.marked) : (Ast.Var.t * Ast.expr Pos.marked) list = match Pos.unmark (evaluate_expr e) with | Ast.EAbs (_, binder, taus) -> ( diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 2a58f21f..9640a43a 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -20,6 +20,10 @@ module Errors = Utils.Errors module A = Ast module Cli = Utils.Cli +(** {1 Types and unification} *) + +(** We do not reuse {!type: Dcalc.Ast.typ} because we have to include a new [TAny] variant. Indeed, + error terms can have any type and this has to be captured by the type sytem. *) type typ = | TLit of A.typ_lit | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem @@ -42,6 +46,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) ts | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 +(** Raises an error if unification cannot be performed *) let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) let t1_repr = UnionFind.get (UnionFind.find t1) in @@ -76,6 +81,9 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); ] +(** Operators have a single type, instead of being polymorphic with constraints. 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 Pos.marked) : typ Pos.marked UnionFind.elem = let pos = Pos.get_position op in let bt = UnionFind.make (TLit TBool, pos) in @@ -134,8 +142,11 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = | TAny -> A.TLit A.TUnit) (UnionFind.get (UnionFind.find ty)) +(** {1 Double-directed typing} *) + type env = typ Pos.marked A.VarMap.t +(** Infers the most permissive type from an expression *) let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem = match Pos.unmark e with @@ -244,6 +255,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); UnionFind.make (Pos.same_pos_as (TLit TUnit) e') +(** Checks whether the expression can be typed with the provided type *) and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = match Pos.unmark e with @@ -372,9 +384,13 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e')) +(** {1 API} *) + +(* Infer the type of an expression *) let infer_type (e : A.expr Pos.marked) : A.typ Pos.marked = let ty = typecheck_expr_bottom_up A.VarMap.empty e in typ_to_ast ty +(** Typechecks an expression given an expected type *) let check_type (e : A.expr Pos.marked) (tau : A.typ Pos.marked) = typecheck_expr_top_down A.VarMap.empty e (UnionFind.make (Pos.map_under_mark ast_to_typ tau)) diff --git a/src/catala/index.mld b/src/catala/index.mld index 25a82ab9..38401fb8 100644 --- a/src/catala/index.mld +++ b/src/catala/index.mld @@ -61,6 +61,13 @@ More documentation can be found on each intermediate representations here. {li {{: dcalc.html} The default calculus}} } +The main compilation chain is defined in: + +{!modules: Catala.Driver} + Last, two more modules contain additional features for the compiler: -{!modules: Utils Literate } \ No newline at end of file +{ul +{li {{: literate.html} Literate programming}} +{li {{: utils.html} Compiler utilities}} +} \ No newline at end of file diff --git a/src/catala/literate_programming/dune b/src/catala/literate_programming/dune index 8925f858..7a7de45b 100644 --- a/src/catala/literate_programming/dune +++ b/src/catala/literate_programming/dune @@ -2,3 +2,7 @@ (name literate) (public_name catala.literate) (libraries re utils surface)) + +(documentation + (package catala) + (mld_files literate)) diff --git a/src/catala/literate_programming/html.ml b/src/catala/literate_programming/html.ml index 68b28c83..61bad4fd 100644 --- a/src/catala/literate_programming/html.ml +++ b/src/catala/literate_programming/html.ml @@ -23,17 +23,24 @@ module P = Printf module R = Re.Pcre module C = Cli +(** {1 Helpers} *) + +(** Converts double lines into HTML newlines. *) let pre_html (s : string) = let s = String.trim s in let doublenewline = R.regexp "\n\n" in let s = R.substitute ~rex:doublenewline ~subst:(fun _ -> "
\n") s in s +(** Raise an error if pygments cannot be found *) let raise_failed_pygments (command : string) (error_code : int) : 'a = Errors.raise_error (Printf.sprintf "Weaving to HTML failed: pygmentize command \"%s\" returned with error code %d" command error_code) +(** Usage: [wrap_html source_files custom_pygments language fmt wrapped] + + Prints an HTML complete page structure around the [wrapped] content. *) let wrap_html (source_files : string list) (custom_pygments : string option) (language : Cli.backend_lang) (fmt : Format.formatter) (wrapped : Format.formatter -> unit) : unit = @@ -91,6 +98,7 @@ let wrap_html (source_files : string list) (custom_pygments : string option) source_files)); wrapped fmt +(** Performs syntax highlighting on a piece of code by using Pygments and the special Catala lexer. *) let pygmentize_code (c : string Pos.marked) (language : C.backend_lang) (custom_pygments : string option) : string = C.debug_print (Printf.sprintf "Pygmenting the code chunk %s" (Pos.to_string (Pos.get_position c))); @@ -125,7 +133,7 @@ let pygmentize_code (c : string Pos.marked) (language : C.backend_lang) close_in oc; output -type program_state = InsideArticle | OutsideArticle +(** {1 Weaving} *) let law_article_item_to_html (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (i : A.law_article_item) : unit = @@ -189,6 +197,8 @@ let program_item_to_html (custom_pygments : string option) (language : C.backend (fmt : Format.formatter) (i : A.program_item) : unit = match i with A.LawStructure s -> law_structure_to_html custom_pygments language fmt s +(** {1 API} *) + let ast_to_html (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (program : A.program) : unit = Format.pp_print_list diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index 416dc8a8..d1252eab 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -22,6 +22,9 @@ module A = Surface.Ast module R = Re.Pcre module C = Cli +(** {1 Helpers} *) + +(** Espaces various LaTeX-sensitive characters *) let pre_latexify (s : string) = let percent = R.regexp "%" in let s = R.substitute ~rex:percent ~subst:(fun _ -> "\\%") s in @@ -33,6 +36,9 @@ let pre_latexify (s : string) = let s = R.substitute ~rex:underscore ~subst:(fun _ -> "\\_") s in s +(** Usage: [wrap_latex source_files custom_pygments language fmt wrapped] + + Prints an LaTeX complete documùent structure around the [wrapped] content. *) let wrap_latex (source_files : string list) (custom_pygments : string option) (language : C.backend_lang) (fmt : Format.formatter) (wrapped : Format.formatter -> unit) = Format.fprintf fmt @@ -107,6 +113,7 @@ let wrap_latex (source_files : string list) (custom_pygments : string option) wrapped fmt; Format.fprintf fmt "\n\n\\end{document}" +(** Replaces math operators by their nice unicode counterparts *) let math_syms_replace (c : string) : string = let date = "\\d\\d/\\d\\d/\\d\\d\\d\\d" in let syms = R.regexp (date ^ "|!=|<=|>=|--|->|\\*|/") in @@ -122,6 +129,8 @@ let math_syms_replace (c : string) : string = in R.substitute ~rex:syms ~subst:syms2cmd c +(** {1 Weaving} *) + let law_article_item_to_latex (language : C.backend_lang) (fmt : Format.formatter) (i : A.law_article_item) : unit = match i with @@ -187,6 +196,8 @@ let program_item_to_latex (language : C.backend_lang) (fmt : Format.formatter) ( : unit = match i with A.LawStructure law_s -> law_structure_to_latex language fmt law_s +(** {1 API} *) + let ast_to_latex (language : C.backend_lang) (fmt : Format.formatter) (program : A.program) : unit = Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "\n\n") diff --git a/src/catala/literate_programming/literate.mld b/src/catala/literate_programming/literate.mld new file mode 100644 index 00000000..f76aff78 --- /dev/null +++ b/src/catala/literate_programming/literate.mld @@ -0,0 +1,9 @@ +{0 Literate programming} + +Related modules: + +{!modules: Literate.Html Literate.Latex} + +These module take the {{:surface.html} surface representation} of the Catala +program and process it into different literate programming outputs, like +an HTML page or a LaTeX document. \ No newline at end of file diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index b219f074..1d8b69bd 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -81,6 +81,8 @@ type typ = | TEnum of EnumName.t | TArrow of typ Pos.marked * typ Pos.marked +(** The expressions use the {{:https://lepigre.fr/ocaml-bindlib/} Bindlib} library, based on + higher-order abstract syntax*) type expr = | ELocation of location | EVar of expr Bindlib.var Pos.marked diff --git a/src/catala/scope_language/scopelang.mld b/src/catala/scope_language/scopelang.mld index addaf813..e5fc89bf 100644 --- a/src/catala/scope_language/scopelang.mld +++ b/src/catala/scope_language/scopelang.mld @@ -1,6 +1,6 @@ {0 The scope language } -This representation is the second in the compilation chain +This representation is the third in the compilation chain (see {{: index.html#architecture} Architecture}). Its main difference with the previous {{: desugared.html} desugared representation} is that inside a scope, the definitions are ordered according to their computational @@ -13,6 +13,10 @@ The module describing the abstract syntax tree is: Printing helpers can be found in {!module: Scopelang.Print}. +This intermediate representation corresponds to the scope language +presented in the {{: https://github.com/CatalaLang/catala/raw/master/doc/formalization/formalization.pdf} +Catala formalization}. + {1 Translation to the default calculus} Related modules: diff --git a/src/catala/utils/dune b/src/catala/utils/dune index ee8dc89b..6c2f8ca2 100644 --- a/src/catala/utils/dune +++ b/src/catala/utils/dune @@ -2,3 +2,7 @@ (name utils) (public_name catala.utils) (libraries cmdliner dune-build-info ANSITerminal)) + +(documentation + (package catala) + (mld_files utils)) diff --git a/src/catala/utils/errors.ml b/src/catala/utils/errors.ml index 7f4e5407..5bb220f6 100644 --- a/src/catala/utils/errors.ml +++ b/src/catala/utils/errors.ml @@ -14,7 +14,12 @@ (** Error formatting and helper functions *) +(** {1 Error exception and printing} *) + exception StructuredError of (string * (string option * Pos.t) list) +(** The payload of the expression is a main error message, with a list of secondary positions + related to the error, each carrying an optional secondary message to describe what is pointed by + the position. *) let print_structured_error (msg : string) (pos : (string option * Pos.t) list) : string = Printf.sprintf "%s%s%s" msg @@ -27,6 +32,8 @@ let print_structured_error (msg : string) (pos : (string option * Pos.t) list) : (Pos.retrieve_loc_text pos)) pos)) +(** {1 Error exception and printing} *) + let raise_spanned_error (msg : string) ?(span_msg : string option) (span : Pos.t) : 'a = raise (StructuredError (msg, [ (span_msg, span) ])) diff --git a/src/catala/utils/uid.mli b/src/catala/utils/uid.mli index 7c9c8242..f8ec123c 100644 --- a/src/catala/utils/uid.mli +++ b/src/catala/utils/uid.mli @@ -12,6 +12,9 @@ or implied. See the License for the specific language governing permissions and limitations under the License. *) +(** Global identifiers factories using a generative functor *) + +(** The information carried in global identifiers *) module type Info = sig type info @@ -19,7 +22,11 @@ module type Info = sig end module MarkedString : Info with type info = string Pos.marked +(** The only kind of information carried in Catala identifiers is the original string of the + identifier annotated with the position where it is declared or used. *) +(** Identifiers have abstract types, but are comparable so they can be used as keys in maps or sets. + Their underlying information can be retrieved at any time. *) module type Id = sig type t @@ -36,4 +43,7 @@ module type Id = sig val hash : t -> int 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 diff --git a/src/catala/utils/utils.mld b/src/catala/utils/utils.mld new file mode 100644 index 00000000..ba7a92a1 --- /dev/null +++ b/src/catala/utils/utils.mld @@ -0,0 +1,38 @@ +{0 Compiler utilities} + +{1 Unique identifiers} + +Related modules: + +{!modules: Utils.Uid} + +In {{: desugared.html} the desugared representation} or in the +{{: scopelang.html} the scope language}, a number of things are named using +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 +a fresh sort of global identifiers. + +{1 Source code positions} + +Related modules: + +{!modules: Utils.Pos} + +This module is used throughout the compiler to annotate the abstract syntax +trees with information about the position of the element in the original source +code. These annotations are critical to produce readable error messages. + +{1 Error messages} + +Related modules: + +{!modules: Utils.Errors} + +Error handling is critical in a compiler. The Catala compiler uses an architecture +of error messages inspired by the Rust compiler, where error messages all +correspond to the same exception. This exception carries messages and positions +that are displayed in the end in a nicely-formatted error message. + +Hence, all error thrown by the compiler should use {!module: Utils.Errors} \ No newline at end of file From 4b7e17f999bc090c58efda805de3168b66b0abe8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 17 Dec 2020 20:09:33 +0100 Subject: [PATCH 087/142] Rewrote tutorial but struct access bug --- examples/tutorial/tutorial_en.catala_en | 186 +++++++++++-------- src/catala/catala_surface/desugaring.ml | 4 +- src/catala/catala_surface/name_resolution.ml | 2 +- src/catala/literate_programming/latex.ml | 4 +- 4 files changed, 111 insertions(+), 85 deletions(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index 0f075d90..023421c7 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -3,38 +3,50 @@ Welcome to this tutorial, whose objective is to guide you through the features of the Catala language and trach you how to annotate a legislative text using the language. This document is addressed primarily to developers or people that -have a programming background. It will use terms and jargon that might be -unintelligible for lawyers in general. +have a programming background, though tech-savvy lawyers will probably figure +things out. @@Literate programming@@+ To begin writing a Catala program, you must start from the text of the legislative source that will justify the code that you will write. Concretely, that means copy-pasting the text of the law into a Catala source file and -formatting it according so that Catala can understand it. +formatting it according so that Catala can understand it. Catala source files +have the ".catala_en" extension. If you were to write a Catala program for a +French law, you would use the ".catala_fr" extension. You can write any kind of plain text in Catala, and it will be printed as is -in PDF or HTML output. Keep in mind however that one line in the source file -corresponds to a paragraph in the output. Catala allows you to declare section -or subsection headers as it is done here, but the fundamental division unit is -the article. Let's analyse a fictional example that defines an income tax. +in PDF or HTML output. You can split your text into short lines, those +will appear as a single paragraph in the output. If you want to create a +new paragrah, you have to leave a blank line in the source. + +Catala allows you to declare section or subsection headers as it is done +here, with the "at" symbol repeated twice. You can define heading of lower +importance by adding increasing numbers of "+" after the title of the heading. + +The fundamental division unit is the article, introduced by a single "at". +Let's analyse a fictional example that defines an income tax. @Article 1@ The income tax for an individual is defined as a fixed percentage of the individual's income over a year. + /* -# This is a placeholder comment, the code for that article should go here +# Welcome to the code mode of Catala. This is a comment, because the line is +# prefixed by #. +# We will soon learn what to write here in order to translate the meaning +# of the article into Catala code. */ -We will now proceed to encode the algorithmic content of this article using -the Catala language. To do that, we will intertwine short snippets of code -between the sentences of the legislative text. Each snippet of code should -be as short as possible and as close as possible to the actual sentence that -justifies the code. +To do that, we will intertwine short snippets of code between the sentences of +the legislative text. Each snippet of code should be as short as possible and +as close as possible to the actual sentence that justifies the code. This style +is called litterate programming, a programming paradigm invented by the famous +computer scientist Donald Knuth in the 70s. @@Defining a fictional income tax@@+ -The content of article 1 uses a lot of implicit context : there exists an +The content of article 1 uses a lot of implicit context: there exists an individual with an income, as well as an income tax that the individual has to pay each year. Even if this implicit context is not verbatim in the law, we have to explicit it for programming purposes. Concretely, we need a @@ -42,23 +54,28 @@ we have to explicit it for programming purposes. Concretely, we need a inside the law. Let's start our metadata section by declaring the type information for the -individual and the income tax computation: -@@Begin metadata@@ -/* -declaration structure Individual: - data income content money +individual: -declaration structure Article1: - data fixed_percentage content decimal - data income_tax content money +@@Begin metadata@@ +/* +declaration structure Individual: + # The name of the structure "Individual", must start with an + # uppercase letter: this is the CamlCase convention. + data income content money + # In this line, "income" is the name of the structure field and + # "money" is the type of what is stored in that field. + # Available types include: integer, decimal, money, date, duration, + # and any other structure or enumeration that you declare + data age content integer + # "income" and "age" start by a lowercase letter, they follow the + # snake_case convention */ @@End metadata@@ -Each of this declaration is a structure, containing one or more data fields. -Structures are useful to group together data that goes together. Usually, you +This structre contains two data fields, "income" and "age". Structures are +useful to group together data that goes together. Usually, you get one structure per concrete object on which the law applies (like the -individual), but also one structure for each article that defines quantities -(like the article 1). It is up to you to decide how to group the data together, +individual). It is up to you to decide how to group the data together, but you should aim to optimize code readability. Sometimes, the law gives an enumeration of different situations. These @@ -66,31 +83,41 @@ enumerations are modeled in Catala using an enumeration type, like: @@Begin metadata@@ /* declaration enumeration TaxCredit: +# The name "TaxCredit" is also written in CamlCase -- NoTaxCredit --- ChildrenTaxCredit content integer # the integer corresponds - # to the number of children +# This line says that "TaxCredit" can be a "NoTaxCredit" situation +-- ChildrenTaxCredit content integer +# This line says that alternatively, "TaxCredit" can be a +# "ChildrenTaxCredit" situation. This situation carries a content +# of type integer corresponding to the number of children concerned +# by the tax credit. This means that if you're in the "ChildrenTaxCredit" +# situation, you will also have access to this number of children */ @@End metadata@@ +In computer science terms, such an enumeration is called a "sum type" or simply +an enum. The combination of structures and enumerations allow the Catala +programmer to declare all possible shapes of data, as they are equivalent to +the powerful notion of "algebraic datatypes". + We've defined and typed the data that the program will manipulate. Now we have to define the logical context in which these data will evolve. This is done in -Catala using "scopes". Scopes also have to be declared in metadata, so here we -go: +Catala using "scopes". Scopes are close to functions in terms of traditional +programming. Scopes also have to be declared in metadata, so here we go: @@Begin metadata@@ /* declaration scope IncomeTaxComputation: + # Scope names use CamlCase context individual content Individual - context article1 content Article1 + # This line declares a context element of the scope, which is aking to + # a function parameter in computer science term. This is the piece of + # data on which the scope will operate + context fixed_percentage content decimal + context income_tax content money */ @@End metadata@@ -This scope declaration says that whenever we're in the scope -"IncomeTaxComputation", then we have access to two elements in context, -namely the individual's data and the data defined by article 1. We will be -able to refer to the lowercase variables in our code, either to use them or to -define them or one of their part. - We now have everything to annotate the contents of article 1, which is copied over below. @@ -99,21 +126,37 @@ The income tax for an individual is defined as a fixed percentage of the individual's income over a year. /* scope IncomeTaxComputation: - definition article1.income_tax equals - invidual.income * article1.fixed_percentage + definition income_tax equals + invidual.income *$ fixed_percentage */ In the code, we are defining inside our scope the amount of the income tax according to the formula described in the article. When defining formulaes, -you have access to all the usual arithmetic operators. But what is the value -of that fixed percentage? Often, precise values are defined elsewhere in the +you have access to all the usual arithmetic operators: addition "+", +substraction "-", multiplication "*" and division (slash). + +However, in the Catala code, you can see that we use "*$" to multiply the +individual income by the fixed percentage. The $ suffix indicates that we +are performing a multiplication on an amount of money. Indeed, in Catala, +you have to keep track of what you are dealing with: is it money ? Is it +an integer? Using just "+" or "*" can be ambiguous in terms of rounding, +since money is usually rounded at the cent. So to disambiguate, we suffix these +operations with something that indicates the type of what we manipulate. +The suffixes are "$" for money "." for decimals, "at" (like in email adresses) +for dates and the hat symbol for durations. If you forget the suffix, the Catala type +checker will display an error message that will help you put it where it +belongs. + +But inside article 1, one question remains unknown: what is the value of +of the fixed percentage? Often, precise values are defined elsewhere in the legislative source. Here, let's suppose we have: @Article 2@ The fixed percentage mentionned at article 1 is equal to 20 %. /* scope IncomeTaxComputation: - definition article1.fixed_percentage equals 20 % + definition fixed_percentage equals 20 % + # Writing 20% is just an abbreviation for 0.20 */ You can see here that Catala allows definitions to be scattered throughout @@ -128,19 +171,20 @@ suppose the third article says: @Article 3@ If the individual is in charge of 2 or more children, then the fixed percentage mentionned at article 1 is equal to 15 %. /* -# How to redefine article1.fixed_percentage? +# How to redefine fixed_percentage? */ This article actually gives another definition for the fixed percentage, which - was already defined in article 2. However, article 3 defines the percentage - conditionnally to the individual having more than 2 children. Catala allows - you precisely to redefine a variable under a condition: +was already defined in article 2. However, article 3 defines the percentage +conditionnally to the individual having more than 2 children. Catala allows +you precisely to redefine a variable under a condition: /* scope IncomeTaxComputation: - definition article1.fixed_percentage under condition - individual.number_of_children >= 2 + definition fixed_percentage under condition + number_of_children >= 2 consequence equals 15 % + # Writing 15% is just an abbreviation for 0.15 */ When the Catala program will execute, the right definition will be dynamically @@ -176,10 +220,10 @@ of income in each bracket multiplied by the rate of each bracket. /* scope TwoBracketsTaxComputation : definition tax of income equals - if income <= breakpoint then - income * rate1 + if income <=$ breakpoint then + income *$ rate1 else ( - breakpoint * rate1 + (income - breakpoint) * rate2 + breakpoint *$ rate1 +$ (income -$ breakpoint) *$ rate2 ) */ @@ -191,46 +235,28 @@ want to use it in our main tax computation scope. @Article 5@ For individuals whose income is greater than $100,000, the income tax of article 1 is computed with a two-brackets system. /* -declaration scope IncomeTaxComputation: - # The scope inclusion has to be added in the scope declaration +declaration scope NewIncomeTaxComputation: context two_brackets_for_rich scope TwoBracketsTaxComputation + # This line says that we add the item two_brackets_for_rich to the context. + # However, the "scope" keyword tells that this item is not a piece of data + # but rather a subscope that we can use to compute things. + context individual content Individual + context income_tax content money scope IncomeTaxComputation : - - definition article1.income_tax under condition - individual.income >= $100,000 + definition income_tax under condition + individual.income >=$ $100,000 consequence equals two_brackets_for_rich.tax of individual.income */ -Scope inclusion also comes with a syntactic sugar for quickly and conditionnaly -connecting context quantities : - -@@Begin metadata@@ -/* -declaration scope ExemptedOfTax: - context article1 content Article1 -*/ -@@End metadata@@ - @Article 6@ Individuals earning less than $10,000 are exempted of the income tax mentionned at article 1. /* -scope ExemptedOfTax : - definition article1.income_tax equals $0 - -declaration scope IncomeTaxComputation: - # The scope inclusion has to be added in the scope declaration - context tax_exempt scope ExemptedOfTax - -scope IncomeTaxComputation: - definition article1.income_tax under condition +scope NewIncomeTaxComputation: + definition income_tax under condition individual.income <= $10,000 - consequence equals - tax_exempt.article1.income_tax + consequence equals $0 */ -This snippet of code actually brings the definition of article1.income_tax of -ExemptedOfTax into the IncomeTaxComputation scope, prefixing it with the -"income under $10,000" condition. diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 67cf28ec..6430de74 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -137,8 +137,8 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti match Desugared.Ast.IdentMap.find_opt x scope_ctxt.var_idmap with | Some uid -> Bindlib.box (Scopelang.Ast.ELocation (ScopeVar (uid, pos)), pos) | None -> - Name_resolution.raise_unknown_identifier "for a\n local or scope-wide variable" - (x, pos) ) + Name_resolution.raise_unknown_identifier "for a local or scope-wide variable" (x, pos) + ) | Some uid -> Scopelang.Ast.make_var (uid, pos) (* the whole box thing is to accomodate for this case *) ) diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 1f6a8f14..5a642c25 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -71,7 +71,7 @@ let raise_unsupported_feature (msg : string) (pos : Pos.t) = previously *) let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = Errors.raise_spanned_error - (Printf.sprintf "%s: unknown identifier %s" (Pos.unmark ident) msg) + (Printf.sprintf "\"%s\": unknown identifier %s" (Pos.unmark ident) msg) (Pos.get_position ident) (** Gets the type associated to an uid *) diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index d1252eab..dce1051a 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -141,7 +141,7 @@ let law_article_item_to_latex (language : C.backend_lang) (fmt : Format.formatte /*%s*/\n\ \\end{minted}" (pre_latexify (Filename.basename (Pos.get_file (Pos.get_position c)))) - (Pos.get_start_line (Pos.get_position c)) + (Pos.get_start_line (Pos.get_position c) - 1) (match language with `Fr -> "catala_fr" | `En -> "catala_en") (math_syms_replace (Pos.unmark c)) @@ -186,7 +186,7 @@ let rec law_structure_to_latex (language : C.backend_lang) (fmt : Format.formatt \\end{minted}\n\ \\end{tcolorbox}" metadata_title metadata_title - (Pos.get_start_line (Pos.get_position c)) + (Pos.get_start_line (Pos.get_position c) - 1) (pre_latexify (Filename.basename (Pos.get_file (Pos.get_position c)))) (match language with `Fr -> "catala_fr" | `En -> "catala_en") (math_syms_replace (Pos.unmark c)) From f1b1ef799230b713174904ba0f16bc0eb8388dba Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 17 Dec 2020 20:13:19 +0100 Subject: [PATCH 088/142] Update test result --- tests/test_scope/cyclic_scopes.catala.A.out | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_scope/cyclic_scopes.catala.A.out b/tests/test_scope/cyclic_scopes.catala.A.out index 8c73feb4..eb2480a2 100644 --- a/tests/test_scope/cyclic_scopes.catala.A.out +++ b/tests/test_scope/cyclic_scopes.catala.A.out @@ -1,4 +1,4 @@ -[ERROR] B: unknown identifier for a scope +[ERROR] "B": unknown identifier for a scope [ERROR] [ERROR] --> test_scope/cyclic_scopes.catala [ERROR] | From 05b8a229b0f1f55a3d10095e92ab266f99ee7485 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 17 Dec 2020 20:54:38 +0100 Subject: [PATCH 089/142] Better assertion failed message --- examples/tutorial/tutorial_en.catala_en | 97 +++++++++++++++++----- src/catala/default_calculus/interpreter.ml | 11 ++- src/catala/literate_programming/latex.ml | 1 - 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index 023421c7..f04c4864 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -66,9 +66,9 @@ declaration structure Individual: # "money" is the type of what is stored in that field. # Available types include: integer, decimal, money, date, duration, # and any other structure or enumeration that you declare - data age content integer - # "income" and "age" start by a lowercase letter, they follow the - # snake_case convention + data number_of_children content integer + # "income" and "number_of_children" start by a lowercase letter, + # they follow the snake_case convention */ @@End metadata@@ @@ -127,7 +127,7 @@ individual's income over a year. /* scope IncomeTaxComputation: definition income_tax equals - invidual.income *$ fixed_percentage + individual.income *$ fixed_percentage */ In the code, we are defining inside our scope the amount of the income tax @@ -163,7 +163,7 @@ You can see here that Catala allows definitions to be scattered throughout the annotation of the legislative text, so that each definition is as close as possible to its location in the text. -@@Conditional definitions@@ +@@Conditional definitions@@+ So far so good, but now the legislative text introduces some trickyness. Let us suppose the third article says: @@ -182,7 +182,7 @@ you precisely to redefine a variable under a condition: /* scope IncomeTaxComputation: definition fixed_percentage under condition - number_of_children >= 2 + individual.number_of_children >= 2 consequence equals 15 % # Writing 15% is just an abbreviation for 0.15 */ @@ -194,7 +194,7 @@ However, if it is not the case, Catala will let you define a precedence on the conditions, which has to be justified by the law. -@@Functions@@ +@@Functions@@+ Catala lets you define functions anywhere in your data. Here's what it looks like in the metadata definition when we want to define a two-brackets tax @@ -219,35 +219,39 @@ of income in each bracket multiplied by the rate of each bracket. /* scope TwoBracketsTaxComputation : - definition tax of income equals - if income <=$ breakpoint then - income *$ rate1 + definition tax_formula of income equals + if income <=$ brackets.breakpoint then + income *$ brackets.rate1 else ( - breakpoint *$ rate1 +$ (income -$ breakpoint) *$ rate2 + brackets.breakpoint *$ brackets.rate1 +$ + (income -$ brackets.breakpoint) *$ brackets.rate2 ) */ -@@Scope inclusion@@ +@@Scope inclusion@@+ Now that we've defined our helper scope for computing a two-brackets tax, we want to use it in our main tax computation scope. @Article 5@ For individuals whose income is greater than $100,000, the income -tax of article 1 is computed with a two-brackets system. +tax of article 1 is 40% of the income above $100,000. Below $100,000, the +income tax is 20% of the income. /* declaration scope NewIncomeTaxComputation: - context two_brackets_for_rich scope TwoBracketsTaxComputation + context two_brackets scope TwoBracketsTaxComputation # This line says that we add the item two_brackets_for_rich to the context. # However, the "scope" keyword tells that this item is not a piece of data # but rather a subscope that we can use to compute things. context individual content Individual context income_tax content money -scope IncomeTaxComputation : - definition income_tax under condition - individual.income >=$ $100,000 - consequence equals - two_brackets_for_rich.tax of individual.income +scope NewIncomeTaxComputation : + definition two_brackets.brackets equals TwoBrackets { + -- breakpoint: $100,000 + -- rate1: 20% + -- rate2: 40% + } + definition income_tax equals two_brackets.tax_formula of individual.income */ @Article 6@ @@ -256,7 +260,60 @@ at article 1. /* scope NewIncomeTaxComputation: definition income_tax under condition - individual.income <= $10,000 + individual.income <=$ $10,000 consequence equals $0 */ +That's it! We've defined a two-brackets tax computation simply by annotating +legislative article by snippets of Catala code. However, attentive readers +may have caught something weird in articles 5 and 6. What happens when the +income of the individual is between $10,000 and $100,000 ? + +The law leaves it unspecified ; our dummy articles are clearly badly drafted. +But Catala can help you find this sort of errors via simple testing or +even formal verification. Let's start with the testing. + +@@Testing Catala programs@@+ + +Testing Catala programs can be done directly into Catala. Indeed, writing test +cases for each Catala scope that you define is a good practice called +"unit testing" in the software engineering community. A test case is defined +as another scope: + +@Testing NewIncomeTaxComputation@ +/* +declaration scope Test1: + context tax_computation scope NewIncomeTaxComputation + +scope Test1: + definition + tax_computation.individual + # We define the argument to the subscope + equals + # The four lines below define a whole structure by giving a value to + # each of its fields + Individual { + -- income: $230,000 + -- number_of_children: 0 + } + + # Next, we retrieve the income tax value compute it by the subscope and + # assert that it is equal to the expected value : + # ($230,000-$100,00)*40%+$100,000*20% = $72,000 + assertion tax_computation.income_tax = $72,000 +*/ + +This test should pass. Let us now consider a failing test case: +/* +declaration scope Test2: + context tax_computation scope NewIncomeTaxComputation + +scope Test2: + definition tax_computation.individual equals Individual { + -- income: $4,000 + -- number_of_children: 0 + } + + assertion tax_computation.income_tax = $0 +*/ + diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 3ecc5afc..441240d1 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -298,7 +298,16 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = | EAssert e' -> ( match Pos.unmark (evaluate_expr e') with | ELit (LBool true) -> Pos.same_pos_as (Ast.ELit LUnit) e' - | ELit (LBool false) -> Errors.raise_spanned_error "Assertion failed" (Pos.get_position e') + | ELit (LBool false) -> ( + match Pos.unmark e' with + | EApp ((Ast.EOp (Binop op), pos_op), [ e1; e2 ]) -> + Errors.raise_spanned_error + (Format.asprintf "Assertion failed: %a %a %a" Print.format_expr e1 + Print.format_binop (op, pos_op) Print.format_expr e2) + (Pos.get_position e') + | _ -> + Errors.raise_spanned_error (Format.asprintf "Assertion failed") (Pos.get_position e') + ) | _ -> Errors.raise_spanned_error "Expected a boolean literal for the result of this assertion (should not happen if the \ diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index dce1051a..bf3a7e66 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -63,7 +63,6 @@ let wrap_latex (source_files : string list) (custom_pygments : string option) \\newunicodechar{→}{$\\rightarrow$}\n\ \\newunicodechar{≠}{$\\neq$}\n\n\ \\fvset{\n\ - commandchars=\\\\\\{\\},\n\ numbers=left,\n\ frame=lines,\n\ framesep=3mm,\n\ From 81c464ea7e0b576d0d6760c86ae37381bb902b6b Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 18 Dec 2020 13:13:51 +0100 Subject: [PATCH 090/142] Added labels and exceptions to surface syntax --- catala.opam | 2 +- dune-project | 2 +- examples/Makefile.common | 5 +- examples/tutorial/tutorial_en.catala_en | 49 ++- src/catala/catala_surface/ast.ml | 4 + src/catala/catala_surface/desugaring.ml | 42 ++- src/catala/catala_surface/lexer.ml | 8 + src/catala/catala_surface/lexer_en.ml | 8 + src/catala/catala_surface/lexer_fr.ml | 6 + src/catala/catala_surface/name_resolution.ml | 88 +++++ src/catala/catala_surface/parser.messages | 306 +++++++++--------- src/catala/catala_surface/parser.mly | 25 +- src/catala/catala_surface/parser_errors.ml | 118 +++---- .../en/atom/grammars/catala_en.cson | 2 +- syntax_highlighting/en/catala_en.iro | 2 +- syntax_highlighting/en/pygments/catala_en.py | 2 +- .../en/vscode/syntaxes/catalavs.xml | 2 +- .../fr/atom/grammars/catala_fr.cson | 2 +- syntax_highlighting/fr/catala_fr.iro | 2 +- syntax_highlighting/fr/pygments/catala_fr.py | 2 +- .../fr/vscode/syntaxes/catalavs.xml | 2 +- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 2 +- .../nv/vscode/syntaxes/catalavs.xml | 2 +- 25 files changed, 442 insertions(+), 245 deletions(-) diff --git a/catala.opam b/catala.opam index 1bdedd02..5c92c447 100644 --- a/catala.opam +++ b/catala.opam @@ -1,6 +1,6 @@ # This file is generated by dune, edit dune-project instead opam-version: "2.0" -version: "0.1.1" +version: "0.2.0" synopsis: "Low-level language for tax code specification" description: """ The Catala language is designed to be a low-level target for diff --git a/dune-project b/dune-project index c6665207..0536991d 100644 --- a/dune-project +++ b/dune-project @@ -1,6 +1,6 @@ (lang dune 2.2) (name catala) -(version 0.1.1) +(version 0.2.0) (generate_opam_files true) (formatting) diff --git a/examples/Makefile.common b/examples/Makefile.common index e33e4571..09001348 100644 --- a/examples/Makefile.common +++ b/examples/Makefile.common @@ -63,7 +63,10 @@ endif clean: $(LATEXMK) -f -C $(SRC:.catala_$(CATALA_LANG)=.tex) - rm -rf $(SRC:.catala_$(CATALA_LANG)=.tex) $(SRC:.catala_$(CATALA_LANG)=.d) _minted-$(SRC:.catala_$(CATALA_LANG)=) + rm -rf $(SRC:.catala_$(CATALA_LANG)=.tex) \ + $(SRC:.catala_$(CATALA_LANG)=.d) \ + _minted-$(SRC:.catala_$(CATALA_LANG)=) \ + $(SRC:.catala_$(CATALA_LANG)=.html) include $(wildcard $(SRC:.catala_$(CATALA_LANG)=.d)) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index f04c4864..ce7b87de 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -259,7 +259,7 @@ Individuals earning less than $10,000 are exempted of the income tax mentionned at article 1. /* scope NewIncomeTaxComputation: - definition income_tax under condition + definition income_tax under condition individual.income <=$ $10,000 consequence equals $0 */ @@ -317,3 +317,50 @@ scope Test2: assertion tax_computation.income_tax = $0 */ +This test case should compute a $0 income tax because of Article 6. But instead, +execution will yield an error saying that there is a conflict between rules. + +Indeed, the definition of the income tax in article 6 conflicts with the +definition of income tax in article 5. But actually, article 6 is just an +exception of article 5. In the law, it is implicit that if article 6 is +applicable, then it takes precedence over article 5. + +This implicit precedence has to be explicitely declared in Catala. Here is a +fixed version of the NewIncomeTaxComputation scope: + +/* +declaration scope NewIncomeTaxComputationFixed: + context two_brackets scope TwoBracketsTaxComputation + context individual content Individual + context income_tax content money + +scope NewIncomeTaxComputationFixed : + definition two_brackets.brackets equals TwoBrackets { + -- breakpoint: $100,000 + -- rate1: 20% + -- rate2: 40% + } + + label article_5 + definition income_tax equals two_brackets.tax_formula of individual.income + + exception article_5 + definition income_tax under condition + individual.income <=$ $10,000 + consequence equals $0 +*/ + +And the test that should now work: + +/* +declaration scope Test3: + context tax_computation scope NewIncomeTaxComputationFixed + +scope Test3: + definition tax_computation.individual equals Individual { + -- income: $4,000 + -- number_of_children: 0 + } + + assertion tax_computation.income_tax = $0 +*/ \ No newline at end of file diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 74d2e97d..131b2cbe 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -141,6 +141,8 @@ and expression = (** Dotted is for both struct field projection and sub-scope variables *) type rule = { + rule_label : ident Pos.marked option; + rule_exception_to : ident Pos.marked option; rule_parameter : ident Pos.marked option; rule_condition : expression Pos.marked option; rule_name : qident Pos.marked; @@ -148,6 +150,8 @@ type rule = { } type definition = { + definition_label : ident Pos.marked option; + definition_exception_to : ident Pos.marked option; definition_name : qident Pos.marked; definition_parameter : ident Pos.marked option; definition_condition : expression Pos.marked option; diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 6430de74..7c740e23 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -361,18 +361,19 @@ let merge_conditions (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option (** Translates a surface definition into condition into a desugared {!type: Desugared.Ast.rule} *) let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.ScopeName.t) - (def_key : Desugared.Ast.ScopeDef.t) (param_uid : Scopelang.Ast.Var.t Pos.marked option) + (def_key : Desugared.Ast.ScopeDef.t Pos.marked) + (param_uid : Scopelang.Ast.Var.t Pos.marked option) (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) - (just : Ast.expression Pos.marked option) (cons : Ast.expression Pos.marked) : - Desugared.Ast.rule = + (parent_rule : Desugared.Ast.RuleName.t option) (just : Ast.expression Pos.marked option) + (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = let just = match just with Some just -> Some (translate_expr scope ctxt just) | None -> None in - let just = merge_conditions precond just (Pos.get_position cons) in + let just = merge_conditions precond just (Pos.get_position def_key) in let cons = translate_expr scope ctxt cons in { just; cons; parameter = - (let def_key_typ = Name_resolution.get_def_typ ctxt def_key in + (let def_key_typ = Name_resolution.get_def_typ ctxt (Pos.unmark def_key) in match (Pos.unmark def_key_typ, param_uid) with | Scopelang.Ast.TArrow (t_in, _), Some param_uid -> Some (Pos.unmark param_uid, t_in) | Scopelang.Ast.TArrow _, None -> @@ -384,8 +385,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop "this definition has a parameter but its type is not a function" (Pos.get_position (Bindlib.unbox cons)) | _ -> None); - parent_rule = - None (* for now we don't have a priority mechanism in the syntax but it will happen soon *); + parent_rule; } (** Wrapper around {!val: process_default} that performs some name disambiguation *) @@ -426,15 +426,29 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) | None -> (Desugared.Ast.RuleMap.empty, Name_resolution.get_def_typ ctxt def_key) in let rule_name = - Desugared.Ast.RuleName.fresh - (Pos.map_under_mark - (fun qident -> String.concat "." (List.map (fun i -> Pos.unmark i) qident)) - def.definition_name) + match def.Ast.definition_label with + | None -> None + | Some label -> Some (Desugared.Ast.IdentMap.find (Pos.unmark label) scope_ctxt.label_idmap) + in + let rule_name = + match rule_name with + | Some x -> x + | None -> + Desugared.Ast.RuleName.fresh + (Pos.map_under_mark + (fun qident -> String.concat "." (List.map (fun i -> Pos.unmark i) qident)) + def.definition_name) + in + let parent_rule = + match def.Ast.definition_exception_to with + | None -> None + | Some label -> Some (Desugared.Ast.IdentMap.find (Pos.unmark label) scope_ctxt.label_idmap) in let x_def = Desugared.Ast.RuleMap.add rule_name - (process_default new_ctxt scope_uid def_key param_uid precond def.definition_condition - def.definition_expr) + (process_default new_ctxt scope_uid + (def_key, Pos.get_position def.definition_name) + param_uid precond parent_rule def.definition_condition def.definition_expr) x_def in { @@ -454,6 +468,8 @@ let process_rule (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) let consequence_expr = Ast.Literal (Ast.Bool (Pos.unmark rule.rule_consequence)) in let def = { + Ast.definition_label = rule.rule_label; + Ast.definition_exception_to = rule.rule_exception_to; Ast.definition_name = rule.rule_name; Ast.definition_parameter = rule.rule_parameter; Ast.definition_condition = rule.rule_condition; diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 5c40eddc..8f297440 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -87,6 +87,8 @@ let token_list : (string * token) list = ("sum", SUM); ("ok", FILLED); ("def", DEFINITION); + ("label", LABEL); + ("exception", EXCEPTION); ("equals", DEFINED_AS); ("match", MATCH); ("with", WITH); @@ -199,6 +201,12 @@ let rec lex_code (lexbuf : lexbuf) : token = | "def" -> update_acc lexbuf; DEFINITION + | "label" -> + update_acc lexbuf; + LABEL + | "exception" -> + update_acc lexbuf; + EXCEPTION | ":=" -> update_acc lexbuf; DEFINED_AS diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index bb092b31..5bed98d7 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -44,6 +44,8 @@ let token_list_en : (string * token) list = ("sum", SUM); ("fulfilled", FILLED); ("definition", DEFINITION); + ("label", LABEL); + ("exception", EXCEPTION); ("equals", DEFINED_AS); ("match", MATCH); ("with pattern", WITH); @@ -156,6 +158,12 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "definition" -> L.update_acc lexbuf; DEFINITION + | "label" -> + L.update_acc lexbuf; + LABEL + | "exception" -> + L.update_acc lexbuf; + EXCEPTION | "equals" -> L.update_acc lexbuf; DEFINED_AS diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 76760c9e..f132c356 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -158,6 +158,12 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = (* 0xE9 is é *) L.update_acc lexbuf; DEFINITION + | 0xE9, "tiquette" -> + L.update_acc lexbuf; + LABEL + | "exception" -> + L.update_acc lexbuf; + EXCEPTION | 0xE9, "gal ", 0x00E0 -> (* 0xE9 is é *) L.update_acc lexbuf; diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 5a642c25..4ed47408 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -26,6 +26,7 @@ type typ = Scopelang.Ast.typ type scope_context = { var_idmap : Scopelang.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; (** Scope variables *) + label_idmap : Desugared.Ast.RuleName.t Desugared.Ast.IdentMap.t; sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Desugared.Ast.IdentMap.t; (** Sub-scopes variables *) sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; @@ -249,6 +250,7 @@ let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context = Scopelang.Ast.ScopeMap.add scope_uid { var_idmap = Desugared.Ast.IdentMap.empty; + label_idmap = Desugared.Ast.IdentMap.empty; sub_scopes_idmap = Desugared.Ast.IdentMap.empty; sub_scopes = Scopelang.Ast.SubScopeMap.empty; } @@ -383,6 +385,87 @@ let process_program_item (ctxt : context) (item : Ast.program_item) (process_item : context -> Ast.code_item Pos.marked -> context) : context = match item with Ast.LawStructure s -> process_law_structure ctxt s process_item +(** {1 Scope uses pass} *) + +let process_rule (ctxt : context) (s_name : Scopelang.Ast.ScopeName.t) (r : Ast.rule) : context = + match r.Ast.rule_label with + | None -> ctxt + | Some label -> + let rule_name = + Desugared.Ast.RuleName.fresh + (Pos.map_under_mark + (fun qident -> String.concat "." (List.map (fun i -> Pos.unmark i) qident)) + r.rule_name) + in + { + ctxt with + scopes = + Scopelang.Ast.ScopeMap.update s_name + (fun s_ctxt -> + match s_ctxt with + | None -> assert false (* should not happen *) + | Some s_ctxt -> + Some + { + s_ctxt with + label_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark label) rule_name s_ctxt.label_idmap; + }) + ctxt.scopes; + } + +let process_definition (ctxt : context) (s_name : Scopelang.Ast.ScopeName.t) (d : Ast.definition) : + context = + match d.Ast.definition_label with + | None -> ctxt + | Some label -> + let definition_name = + Desugared.Ast.RuleName.fresh + (Pos.map_under_mark + (fun qident -> String.concat "." (List.map (fun i -> Pos.unmark i) qident)) + d.definition_name) + in + { + ctxt with + scopes = + Scopelang.Ast.ScopeMap.update s_name + (fun s_ctxt -> + match s_ctxt with + | None -> assert false (* should not happen *) + | Some s_ctxt -> + Some + { + s_ctxt with + label_idmap = + Desugared.Ast.IdentMap.add (Pos.unmark label) definition_name + s_ctxt.label_idmap; + }) + ctxt.scopes; + } + +let process_scope_use_item (s_name : Scopelang.Ast.ScopeName.t) (ctxt : context) + (sitem : Ast.scope_use_item Pos.marked) : context = + match Pos.unmark sitem with + | Rule r -> process_rule ctxt s_name r + | Definition d -> process_definition ctxt s_name d + | _ -> ctxt + +let process_scope_use (ctxt : context) (suse : Ast.scope_use) : context = + let s_name = + try Desugared.Ast.IdentMap.find (Pos.unmark suse.Ast.scope_use_name) ctxt.scope_idmap + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "\"%s\": this scope has not been declared anywhere, is it a typo?" + (Pos.unmark suse.Ast.scope_use_name)) + (Pos.get_position suse.Ast.scope_use_name) + in + List.fold_left (process_scope_use_item s_name) ctxt suse.Ast.scope_use_items + +let process_use_item (ctxt : context) (item : Ast.code_item Pos.marked) : context = + match Pos.unmark item with + | ScopeDecl _ | StructDecl _ | EnumDecl _ -> ctxt + | ScopeUse suse -> process_scope_use ctxt suse + (** {1 API} *) (** Derive the context from metadata, in one pass over the declarations *) @@ -406,4 +489,9 @@ let form_context (prgm : Ast.program) : context = (fun ctxt item -> process_program_item ctxt item process_decl_item) empty_ctxt prgm.program_items in + let ctxt = + List.fold_left + (fun ctxt item -> process_program_item ctxt item process_use_item) + ctxt prgm.program_items + in ctxt diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index be509fe3..417ef673 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 314. +## Ends in an error in state: 322. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -36,7 +36,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 308. +## Ends in an error in state: 316. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -49,7 +49,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 303. +## Ends in an error in state: 311. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -61,7 +61,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 302. +## Ends in an error in state: 310. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -73,7 +73,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 301. +## Ends in an error in state: 309. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -85,7 +85,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 300. +## Ends in an error in state: 308. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -97,7 +97,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 307. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -109,7 +109,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 306. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -121,7 +121,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 293. +## Ends in an error in state: 301. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -133,7 +133,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 291. +## Ends in an error in state: 299. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -145,7 +145,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 290. +## Ends in an error in state: 298. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -157,7 +157,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 295. +## Ends in an error in state: 303. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -170,7 +170,7 @@ expected the next context item, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 288. +## Ends in an error in state: 296. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -182,7 +182,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 287. +## Ends in an error in state: 295. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -196,7 +196,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 294. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -210,7 +210,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 293. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -222,7 +222,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 284. +## Ends in an error in state: 292. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -234,7 +234,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 283. +## Ends in an error in state: 291. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -246,7 +246,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 270. +## Ends in an error in state: 278. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -258,7 +258,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR ## -## Ends in an error in state: 267. +## Ends in an error in state: 275. ## ## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -270,7 +270,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 278. +## Ends in an error in state: 286. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 274. +## Ends in an error in state: 282. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -294,7 +294,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 281. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -306,7 +306,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 280. +## Ends in an error in state: 288. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -318,7 +318,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 255. +## Ends in an error in state: 263. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -330,7 +330,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 254. +## Ends in an error in state: 262. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -342,7 +342,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 261. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +354,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 252. +## Ends in an error in state: 260. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -366,7 +366,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 251. +## Ends in an error in state: 259. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -378,7 +378,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 258. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -390,7 +390,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 249. +## Ends in an error in state: 257. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -404,7 +404,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 246. +## Ends in an error in state: 228. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -423,18 +423,18 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## In state 83, spurious reduction of production compare_expression -> sum_expression ## In state 143, spurious reduction of production logical_expression -> compare_expression ## In state 158, spurious reduction of production expression -> logical_expression -## In state 243, spurious reduction of production assertion_base -> expression -## In state 244, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 245, spurious reduction of production scope_item -> ASSERTION assertion +## In state 222, spurious reduction of production assertion_base -> expression +## In state 223, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 227, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 240. +## Ends in an error in state: 219. ## -## assertion -> FIXED qident BY . ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> FIXED qident BY . ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## FIXED qident BY @@ -444,9 +444,9 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 239. +## Ends in an error in state: 218. ## -## assertion -> FIXED qident . BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> FIXED qident . BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## FIXED qident @@ -455,17 +455,17 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 238. +## Ends in an error in state: 217. ## -## assertion -> FIXED . qident BY ident [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> FIXED . qident BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## FIXED @@ -475,9 +475,9 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 242. +## Ends in an error in state: 221. ## -## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## option(condition_consequence) @@ -487,7 +487,7 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 211. +## Ends in an error in state: 225. ## ## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -505,14 +505,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## In state 83, spurious reduction of production compare_expression -> sum_expression ## In state 143, spurious reduction of production logical_expression -> compare_expression ## In state 158, spurious reduction of production expression -> logical_expression -## In state 204, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 216, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 203. +## Ends in an error in state: 215. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -524,9 +524,9 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 231. +## Ends in an error in state: 205. ## -## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## VARIES qident @@ -535,17 +535,17 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 233. +## Ends in an error in state: 207. ## -## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## VARIES qident WITH_V base_expression @@ -562,9 +562,9 @@ expected an indication about the variation sense of the variable, or a new scope source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 232. +## Ends in an error in state: 206. ## -## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## VARIES qident WITH_V @@ -574,9 +574,9 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 230. +## Ends in an error in state: 203. ## -## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## VARIES @@ -586,9 +586,9 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 229. +## Ends in an error in state: 202. ## -## scope_item -> ASSERTION . assertion [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## scope_item -> ASSERTION . assertion [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## ASSERTION @@ -598,74 +598,74 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 226. +## Ends in an error in state: 250. ## -## definition -> qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## qident option(definition_parameters) option(condition_consequence) DEFINED_AS +## option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS ## expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 224. +## Ends in an error in state: 248. ## -## definition -> qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## qident option(definition_parameters) +## option(label) option(exception_to) DEFINITION qident option(definition_parameters) ## expected a expression for defining this function, introduced by the defined as keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 225. +## Ends in an error in state: 249. ## -## definition -> qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## qident option(definition_parameters) option(condition_consequence) +## option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) ## expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 223. +## Ends in an error in state: 247. ## -## definition -> qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## definition -> option(label) option(exception_to) DEFINITION qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## qident +## option(label) option(exception_to) DEFINITION qident ## ## WARNING: This example involves spurious reductions. ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 222. +## Ends in an error in state: 246. ## -## scope_item -> DEFINITION . definition [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## definition -> option(label) option(exception_to) DEFINITION . qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## DEFINITION +## option(label) option(exception_to) DEFINITION ## expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 220. +## Ends in an error in state: 213. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -677,9 +677,9 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 208. +## Ends in an error in state: 239. ## -## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: ## option(NOT) @@ -689,19 +689,19 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 202. +## Ends in an error in state: 235. ## -## rule -> rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## rule -> option(label) option(exception_to) RULE rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## rule_expr +## option(label) option(exception_to) RULE rule_expr ## expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 242. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -713,19 +713,19 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 205. +## Ends in an error in state: 236. ## -## rule -> rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## rule -> option(label) option(exception_to) RULE rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## rule_expr option(condition_consequence) +## option(label) option(exception_to) RULE rule_expr option(condition_consequence) ## expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 214. +## Ends in an error in state: 241. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -736,15 +736,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 201, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 212. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -757,12 +757,12 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 200. +## Ends in an error in state: 234. ## -## scope_item -> RULE . rule [ SCOPE RULE END_CODE DEFINITION DECLARATION ASSERTION ] +## rule -> option(label) option(exception_to) RULE . rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## ## The known suffix of the stack is as follows: -## RULE +## option(label) option(exception_to) RULE ## expected the name of the variable subject to the rule @@ -784,7 +784,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## Ends in an error in state: 53. ## ## aggregate_func -> CARDINAL . [ FOR ] -## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CARDINAL @@ -796,9 +796,9 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 151. ## -## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT small_expression @@ -810,7 +810,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 150. ## -## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT @@ -822,7 +822,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 75. ## -## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## constructor @@ -834,7 +834,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 166. ## -## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## exists_prefix @@ -912,7 +912,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 159. ## -## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## forall_prefix @@ -990,7 +990,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 174. ## -## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression @@ -1014,7 +1014,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 177. ## -## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN expression ELSE @@ -1026,7 +1026,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 176. ## -## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN expression @@ -1050,7 +1050,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 175. ## -## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN @@ -1062,7 +1062,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 46. ## -## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF @@ -1074,7 +1074,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 66. ## -## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## num_literal @@ -1086,7 +1086,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 179. ## -## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN expression @@ -1110,7 +1110,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 44. ## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN @@ -1122,7 +1122,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 181. ## -## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH primitive_expression @@ -1140,7 +1140,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 184. ## -## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## ALT match_arm @@ -1164,7 +1164,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 187. ## -## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## constructor_binding COLON @@ -1188,7 +1188,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 186. ## -## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## constructor_binding @@ -1225,7 +1225,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 183. ## -## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## ALT @@ -1237,7 +1237,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 182. ## -## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH primitive_expression WITH @@ -1249,7 +1249,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 43. ## -## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH @@ -1261,7 +1261,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 54. ## -## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_unop @@ -1273,7 +1273,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 140. ## -## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## logical_unop @@ -1285,7 +1285,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 136. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression OF @@ -1297,7 +1297,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 135. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression @@ -1315,7 +1315,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 133. ## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN @@ -1327,7 +1327,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 132. ## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident @@ -1339,7 +1339,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 131. ## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR @@ -1351,7 +1351,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 130. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func @@ -1363,7 +1363,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 60. ## -## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression ARROW @@ -1401,7 +1401,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 58. ## -## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression DOT @@ -1413,7 +1413,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 156. ## -## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression IN @@ -1425,8 +1425,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 120. ## -## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression @@ -1445,7 +1445,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 127. ## -## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression mult_op @@ -1457,7 +1457,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 106. ## -## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_expression compare_op @@ -1469,7 +1469,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 65. ## -## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression OF @@ -1481,7 +1481,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 146. ## -## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## compare_expression logical_op @@ -1493,7 +1493,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 118. ## -## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## mult_expression sum_op @@ -1505,10 +1505,10 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 62. ## -## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression @@ -1526,7 +1526,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 63. ## -## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression WITH @@ -1538,9 +1538,9 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 57. ## -## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression @@ -1552,7 +1552,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 32. ## -## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV date_int @@ -1564,7 +1564,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 31. ## -## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV @@ -1576,7 +1576,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 30. ## -## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int @@ -1588,7 +1588,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 29. ## -## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV @@ -1600,7 +1600,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 28. ## -## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int @@ -1612,7 +1612,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 26. ## -## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL @@ -1658,7 +1658,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 324. +## Ends in an error in state: 332. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1670,7 +1670,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 329. +## Ends in an error in state: 337. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1682,7 +1682,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 323. +## Ends in an error in state: 331. ## ## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1694,7 +1694,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 318. +## Ends in an error in state: 326. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 412752a3..acd797d1 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -62,6 +62,7 @@ %token CONTEXT ENUM ELSE DATE SUM %token BEGIN_METADATA END_METADATA MONEY DECIMAL %token UNDER_CONDITION CONSEQUENCE LBRACKET RBRACKET +%token LABEL EXCEPTION %type source_file_or_master @@ -371,11 +372,16 @@ rule_consequence: } rule: -| name_and_param = rule_expr cond = option(condition_consequence) +| label = option(label) + except = option(exception_to) + RULE + name_and_param = rule_expr cond = option(condition_consequence) consequence = rule_consequence { let (name, param_applied) = name_and_param in let cons : bool Pos.marked = consequence in ({ + rule_label = label; + rule_exception_to = except; rule_parameter = param_applied; rule_condition = cond; rule_name = name; @@ -386,10 +392,21 @@ rule: definition_parameters: | OF i = ident { i } +label: +| LABEL i = ident { i } + +exception_to: +| EXCEPTION i = ident { i } + definition: -| name = qident param = option(definition_parameters) +| label = option(label) + except = option(exception_to) + DEFINITION + name = qident param = option(definition_parameters) cond = option(condition_consequence) DEFINED_AS e = expression { ({ + definition_label = label; + definition_exception_to = except; definition_name = name; definition_parameter = param; definition_condition = cond; @@ -417,10 +434,10 @@ assertion: } scope_item: -| RULE r = rule { +| r = rule { let (r, _) = r in (Rule r, $sloc) } -| DEFINITION d = definition { +| d = definition { let (d, _) = d in (Definition d, $sloc) } | ASSERTION contents = assertion { diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index dd067584..82d68328 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -11,10 +11,10 @@ let message s = | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 318 -> "expected some text, another heading or a law article\n" - | 323 -> "expected a code block, a metadata block, more law text or a heading\n" - | 329 -> "expected a code block, a metadata block, more law text or a heading\n" - | 324 -> "expected a declaration or a scope use\n" + | 326 -> "expected some text, another heading or a law article\n" + | 331 -> "expected a code block, a metadata block, more law text or a heading\n" + | 337 -> "expected a code block, a metadata block, more law text or a heading\n" + | 332 -> "expected a declaration or a scope use\n" | 22 -> "expected the name of the scope you want to use\n" | 24 -> "expected a scope use precondition or a colon\n" | 25 -> "expected an expression which will act as the condition\n" @@ -91,66 +91,66 @@ let message s = operator to form a bigger expression\n" | 53 -> "expected the keyword following cardinal to compute the number of elements in a set\n" | 199 -> "expected a scope use item: a rule, definition or assertion\n" - | 200 -> "expected the name of the variable subject to the rule\n" - | 219 -> + | 234 -> "expected the name of the variable subject to the rule\n" + | 212 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 214 -> "expected a condition or a consequence for this rule\n" - | 205 -> "expected filled or not filled for a rule consequence\n" - | 215 -> "expected the name of the parameter for this dependent variable \n" - | 202 -> "expected the expression of the rule\n" - | 208 -> "expected the filled keyword the this rule \n" - | 220 -> "expected a struct field or a sub-scope context item after the dot\n" - | 222 -> "expected the name of the variable you want to define\n" - | 223 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 225 -> "expected an expression for the consequence of this definition under condition\n" - | 224 -> + | 241 -> "expected a condition or a consequence for this rule\n" + | 236 -> "expected filled or not filled for a rule consequence\n" + | 242 -> "expected the name of the parameter for this dependent variable \n" + | 235 -> "expected the expression of the rule\n" + | 239 -> "expected the filled keyword the this rule \n" + | 213 -> "expected a struct field or a sub-scope context item after the dot\n" + | 246 -> "expected the name of the variable you want to define\n" + | 247 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 249 -> "expected an expression for the consequence of this definition under condition\n" + | 248 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 226 -> "expected an expression for the definition\n" - | 229 -> "expected an expression that shoud be asserted during execution\n" - | 230 -> "expecting the name of the varying variable\n" - | 232 -> "the variable varies with an expression that was expected here\n" - | 233 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 231 -> "expected an indication about what this variable varies with\n" - | 203 -> "expected an expression for this condition\n" - | 211 -> "expected a consequence for this definition under condition\n" - | 242 -> "expected an expression for this definition under condition\n" - | 238 -> "expected the name of the variable that should be fixed\n" - | 239 -> "expected the legislative text by which the value of the variable is fixed\n" - | 240 -> "expected the legislative text by which the value of the variable is fixed\n" - | 246 -> "expected a new scope use item \n" - | 249 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 250 -> "expected the struct name\n" - | 251 -> "expected a colon\n" - | 252 -> "expected struct data or condition\n" - | 253 -> "expected the name of this struct data \n" - | 254 -> "expected the type of this struct data, introduced by the content keyword\n" - | 255 -> "expected the type of this struct data\n" - | 280 -> "expected the name of this struct condition\n" - | 273 -> "expected a new struct data, or another declaration or scope use\n" - | 274 -> "expected the type of the parameter of this struct data function\n" + | 250 -> "expected an expression for the definition\n" + | 202 -> "expected an expression that shoud be asserted during execution\n" + | 203 -> "expecting the name of the varying variable\n" + | 206 -> "the variable varies with an expression that was expected here\n" + | 207 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 205 -> "expected an indication about what this variable varies with\n" + | 215 -> "expected an expression for this condition\n" + | 225 -> "expected a consequence for this definition under condition\n" + | 221 -> "expected an expression for this definition under condition\n" + | 217 -> "expected the name of the variable that should be fixed\n" + | 218 -> "expected the legislative text by which the value of the variable is fixed\n" + | 219 -> "expected the legislative text by which the value of the variable is fixed\n" + | 228 -> "expected a new scope use item \n" + | 257 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 258 -> "expected the struct name\n" + | 259 -> "expected a colon\n" + | 260 -> "expected struct data or condition\n" + | 261 -> "expected the name of this struct data \n" + | 262 -> "expected the type of this struct data, introduced by the content keyword\n" + | 263 -> "expected the type of this struct data\n" + | 288 -> "expected the name of this struct condition\n" + | 281 -> "expected a new struct data, or another declaration or scope use\n" + | 282 -> "expected the type of the parameter of this struct data function\n" + | 286 -> "expected a new struct data, or another declaration or scope use\n" + | 275 -> "expected a new struct data, or another declaration or scope use\n" | 278 -> "expected a new struct data, or another declaration or scope use\n" - | 267 -> "expected a new struct data, or another declaration or scope use\n" - | 270 -> "expected a new struct data, or another declaration or scope use\n" - | 283 -> "expected the name of the scope you are declaring\n" - | 284 -> "expected a colon followed by the list of context items of this scope\n" - | 285 -> "expected a context item introduced by \"context\"\n" - | 286 -> "expected the name of this new context item\n" - | 287 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 288 -> "expected the name of the subscope for this context item\n" - | 295 -> "expected the next context item, or another declaration or scope use\n" - | 290 -> "expected the type of this context item\n" - | 291 -> "expected the next context item or a dependency declaration for this item\n" - | 293 -> "expected the next context item or a dependency declaration for this item\n" - | 298 -> "expected the name of your enum\n" - | 299 -> "expected a colon\n" - | 300 -> "expected an enum case\n" - | 301 -> "expected the name of an enum case \n" - | 302 -> "expected a payload for your enum case, or another case or declaration \n" - | 303 -> "expected a content type\n" - | 308 -> "expected another enum case, or a new declaration or scope use\n" + | 291 -> "expected the name of the scope you are declaring\n" + | 292 -> "expected a colon followed by the list of context items of this scope\n" + | 293 -> "expected a context item introduced by \"context\"\n" + | 294 -> "expected the name of this new context item\n" + | 295 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 296 -> "expected the name of the subscope for this context item\n" + | 303 -> "expected the next context item, or another declaration or scope use\n" + | 298 -> "expected the type of this context item\n" + | 299 -> "expected the next context item or a dependency declaration for this item\n" + | 301 -> "expected the next context item or a dependency declaration for this item\n" + | 306 -> "expected the name of your enum\n" + | 307 -> "expected a colon\n" + | 308 -> "expected an enum case\n" + | 309 -> "expected the name of an enum case \n" + | 310 -> "expected a payload for your enum case, or another case or declaration \n" + | 311 -> "expected a content type\n" + | 316 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" | 20 -> "expected a declaration or a scope use\n" - | 314 -> + | 322 -> "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" | _ -> raise Not_found diff --git a/syntax_highlighting/en/atom/grammars/catala_en.cson b/syntax_highlighting/en/atom/grammars/catala_en.cson index 603d61cc..7172279c 100644 --- a/syntax_highlighting/en/atom/grammars/catala_en.cson +++ b/syntax_highlighting/en/atom/grammars/catala_en.cson @@ -100,7 +100,7 @@ 'name' : 'keyword.control.catala_en' } { - 'match' : '\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition)\\b' + 'match' : '\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition|label|exception)\\b' 'name' : 'keyword.other.catala_en' } { diff --git a/syntax_highlighting/en/catala_en.iro b/syntax_highlighting/en/catala_en.iro index 243c083d..39d58e32 100644 --- a/syntax_highlighting/en/catala_en.iro +++ b/syntax_highlighting/en/catala_en.iro @@ -213,7 +213,7 @@ code : context { } : pattern { - regex \= \b(scope|depends\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition)\b + regex \= \b(scope|depends\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition|label|exception)\b styles [] = .keyword_rule ; } diff --git a/syntax_highlighting/en/pygments/catala_en.py b/syntax_highlighting/en/pygments/catala_en.py index 6a4e537e..d9beca5a 100644 --- a/syntax_highlighting/en/pygments/catala_en.py +++ b/syntax_highlighting/en/pygments/catala_en.py @@ -27,7 +27,7 @@ class CatalaEnLexer(RegexLexer): (u'(context)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(match|with\\s+pattern|fixed|by|decreasing|increasing|varies|with|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b', bygroups(Keyword.Reserved)), - (u'\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition)\\b', bygroups(Keyword.Declaration)), + (u'\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition|label|exception)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), diff --git a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml index d6a8d374..12a41eae 100644 --- a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml @@ -161,7 +161,7 @@ match - \b(scope|depends\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition)\b + \b(scope|depends\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition|label|exception)\b name keyword.other.catala_en diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index d23bf6c1..89be92a2 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -100,7 +100,7 @@ 'name' : 'keyword.control.catala_fr' } { - 'match' : '\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|dépend\\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\\s+condition|condition|donnée|conséquence|rempli|égal\\s+à|assertion|définition)\\b' + 'match' : '\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|dépend\\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\\s+condition|condition|donnée|conséquence|rempli|égal\\s+à|assertion|définition|étiquette|exception)\\b' 'name' : 'keyword.other.catala_fr' } { diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index 546910c1..9008c4e2 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -213,7 +213,7 @@ code : context { } : pattern { - regex \= \b(champ\s+d'application|si\s+et\s+seulement\s+si|dépend\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\s+condition|condition|donnée|conséquence|rempli|égal\s+à|assertion|définition)\b + regex \= \b(champ\s+d'application|si\s+et\s+seulement\s+si|dépend\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\s+condition|condition|donnée|conséquence|rempli|égal\s+à|assertion|définition|étiquette|exception)\b styles [] = .keyword_rule ; } diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 21047bf2..847df392 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -27,7 +27,7 @@ class CatalaFrLexer(RegexLexer): (u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(selon|sous\\s+forme|fix\xe9|par|d\xe9croissante|croissante|varie|avec|on\\s+a|dans|tel\\s+que|existe|pour|tout|de|si|alors|sinon)\\b', bygroups(Keyword.Reserved)), - (u'\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|d\xe9pend\\s+de|d\xe9claration|inclus|collection|contenu|optionnel|structure|\xe9num\xe9ration|contexte|r\xe8gle|sous\\s+condition|condition|donn\xe9e|cons\xe9quence|rempli|\xe9gal\\s+\xe0|assertion|d\xe9finition)\\b', bygroups(Keyword.Declaration)), + (u'\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|d\xe9pend\\s+de|d\xe9claration|inclus|collection|contenu|optionnel|structure|\xe9num\xe9ration|contexte|r\xe8gle|sous\\s+condition|condition|donn\xe9e|cons\xe9quence|rempli|\xe9gal\\s+\xe0|assertion|d\xe9finition|\xe9tiquette|exception)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(vrai|faux)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index b9af454c..5f5f12f5 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -161,7 +161,7 @@ match - \b(champ\s+d'application|si\s+et\s+seulement\s+si|dépend\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\s+condition|condition|donnée|conséquence|rempli|égal\s+à|assertion|définition)\b + \b(champ\s+d'application|si\s+et\s+seulement\s+si|dépend\s+de|déclaration|inclus|collection|contenu|optionnel|structure|énumération|contexte|règle|sous\s+condition|condition|donnée|conséquence|rempli|égal\s+à|assertion|définition|étiquette|exception)\b name keyword.other.catala_fr diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index 943a3a30..c8f99b2d 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -100,7 +100,7 @@ 'name' : 'keyword.control.catala_nv' } { - 'match' : '\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b' + 'match' : '\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def|label|exception)\\b' 'name' : 'keyword.other.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index 2dd58f73..8e3cfd80 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -213,7 +213,7 @@ code : context { } : pattern { - regex \= \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\b + regex \= \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def|label|exception)\b styles [] = .keyword_rule ; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index 9f322053..68895aee 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -26,7 +26,7 @@ class CatalaNvLexer(RegexLexer): (u'(param)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', bygroups(Keyword.Declaration, Text, Name.Variable)), (u'\\b(match|with|fixed|by|decreasing|increasing|varies|with\\s+param|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b', bygroups(Keyword.Reserved)), - (u'\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\\b', + (u'\\b(scope|fun\\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def|label|exception)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index 84a1ed97..4688d65f 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -161,7 +161,7 @@ match - \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def)\b + \b(scope|fun\s+of|new|includes|set|content|option|struct|enum|param|rule|condition|data|ok|assert|def|label|exception)\b name keyword.other.catala_nv From ea1611cd4124c20793f7a0705fa9018baf893f8a Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 18 Dec 2020 15:59:15 +0100 Subject: [PATCH 091/142] Flipped defaults to an exception-based structured --- src/catala/catala_surface/desugaring.ml | 4 +- src/catala/default_calculus/ast.ml | 2 +- src/catala/default_calculus/interpreter.ml | 59 ++++----- src/catala/default_calculus/print.ml | 8 +- src/catala/default_calculus/typing.ml | 8 +- src/catala/desugared/ast.ml | 11 +- src/catala/desugared/desugared_to_scope.ml | 125 ++++++++++++-------- src/catala/scope_language/ast.ml | 8 +- src/catala/scope_language/print.ml | 8 +- src/catala/scope_language/scope_to_dcalc.ml | 8 +- tests/test_default/conflict.catala.A.out | 2 +- tests/test_func/func.catala.S.out | 2 +- tests/test_money/no_mingle.catala.A.out | 4 +- tests/test_scope/scope.catala.A.out | 2 +- tests/test_scope/sub_sub_scope.catala.B.out | 2 +- 15 files changed, 139 insertions(+), 114 deletions(-) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 7c740e23..c554239e 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -364,7 +364,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop (def_key : Desugared.Ast.ScopeDef.t Pos.marked) (param_uid : Scopelang.Ast.Var.t Pos.marked option) (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) - (parent_rule : Desugared.Ast.RuleName.t option) (just : Ast.expression Pos.marked option) + (exception_to_rule : Desugared.Ast.RuleName.t option) (just : Ast.expression Pos.marked option) (cons : Ast.expression Pos.marked) : Desugared.Ast.rule = let just = match just with Some just -> Some (translate_expr scope ctxt just) | None -> None in let just = merge_conditions precond just (Pos.get_position def_key) in @@ -385,7 +385,7 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop "this definition has a parameter but its type is not a function" (Pos.get_position (Bindlib.unbox cons)) | _ -> None); - parent_rule; + exception_to_rule; } (** Wrapper around {!val: process_default} that performs some name disambiguation *) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 5080a7dc..78f8165c 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -89,7 +89,7 @@ type expr = | EApp of expr Pos.marked * expr Pos.marked list | EAssert of expr Pos.marked | EOp of operator - | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + | EDefault of expr Pos.marked list * expr Pos.marked * expr Pos.marked | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked (** {1 Variable helpers} *) diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 441240d1..d3402a4b 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -248,44 +248,31 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = "Expected a term having a sum type as an argument to a match (should not happend if \ the term was well-typed" (Pos.get_position e1) ) - | EDefault (just, cons, subs) -> ( - let just = evaluate_expr just in - match Pos.unmark just with - | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e - | ELit (LBool true) -> ( - match evaluate_expr cons with - | ELit LEmptyError, pos -> - evaluate_expr - (Pos.same_pos_as - (Ast.EDefault ((ELit (LBool false), pos), (Ast.ELit LEmptyError, pos), subs)) - e) - | e' -> e' ) - | ELit (LBool false) -> ( - let subs_orig = subs in - let subs = List.map evaluate_expr subs in - let empty_count = List.length (List.filter is_empty_error subs) in - match List.length subs - empty_count with - | 0 -> Pos.same_pos_as (A.ELit LEmptyError) e - | 1 -> List.find (fun sub -> not (is_empty_error sub)) subs + | EDefault (exceptions, just, cons) -> ( + let exceptions_orig = exceptions in + let exceptions = List.map evaluate_expr exceptions in + let empty_count = List.length (List.filter is_empty_error exceptions) in + match List.length exceptions - empty_count with + | 0 -> ( + let just = evaluate_expr just in + match Pos.unmark just with + | ELit LEmptyError -> Pos.same_pos_as (A.ELit LEmptyError) e + | ELit (LBool true) -> evaluate_expr cons + | ELit (LBool false) -> Pos.same_pos_as (A.ELit LEmptyError) e | _ -> - Errors.raise_multispanned_error - "There is a conflict between multiple rules for assigning the same variable." - ( ( if Pos.get_position e = Pos.no_pos then [] - else - [ - ( Some "This rule is not triggered, so we consider rules of lower priority:", - Pos.get_position e ); - ] ) - @ List.map - (fun (_, sub) -> (Some "This justification is true:", Pos.get_position sub)) - (List.filter - (fun (sub, _) -> not (is_empty_error sub)) - (List.map2 (fun x y -> (x, y)) subs subs_orig)) ) ) + Errors.raise_spanned_error + "Default justification has not been reduced to a boolean at evaluation (should not \ + happen if the term was well-typed" + (Pos.get_position e) ) + | 1 -> List.find (fun sub -> not (is_empty_error sub)) exceptions | _ -> - Errors.raise_spanned_error - "Default justification has not been reduced to a boolean at evaluation (should not \ - happen if the term was well-typed" - (Pos.get_position e) ) + Errors.raise_multispanned_error + "There is a conflict between multiple exceptions for assigning the same variable." + (List.map + (fun (_, except) -> (Some "This justification is true:", Pos.get_position except)) + (List.filter + (fun (sub, _) -> not (is_empty_error sub)) + (List.map2 (fun x y -> (x, y)) exceptions exceptions_orig))) ) | EIfThenElse (cond, et, ef) -> ( match Pos.unmark (evaluate_expr cond) with | ELit (LBool true) -> evaluate_expr et diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 44f42809..e4c1c601 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -202,11 +202,11 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = e1 format_expr e2 format_expr e3 | EOp (Binop op) -> Format.fprintf fmt "%a" format_binop (op, Pos.no_pos) | EOp (Unop op) -> Format.fprintf fmt "%a" format_unop (op, Pos.no_pos) - | EDefault (just, cons, subs) -> - if List.length subs = 0 then + | EDefault (exceptions, just, cons) -> + if List.length exceptions = 0 then Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons else - Format.fprintf fmt "@[⟨%a ⊢ %a |@ %a⟩@]" format_expr just format_expr cons + Format.fprintf fmt "@[⟨%a@ |@ %a ⊢ %a ⟩@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) - subs + exceptions format_expr just format_expr cons | EAssert e' -> Format.fprintf fmt "@[assert@ (%a)@]" format_expr e' diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 9640a43a..c150ce95 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -241,10 +241,10 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m typecheck_expr_top_down env e1 t_app; t_ret | EOp op -> op_type (Pos.same_pos_as op e) - | EDefault (just, cons, subs) -> + | EDefault (excepts, just, cons) -> typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); let tcons = typecheck_expr_bottom_up env cons in - List.iter (fun sub -> typecheck_expr_top_down env sub tcons) subs; + List.iter (fun except -> typecheck_expr_top_down env except tcons) excepts; tcons | EIfThenElse (cond, et, ef) -> typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); @@ -372,10 +372,10 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | EOp op -> let op_typ = op_type (Pos.same_pos_as op e) in unify op_typ tau - | EDefault (just, cons, subs) -> + | EDefault (excepts, just, cons) -> typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); typecheck_expr_top_down env cons tau; - List.iter (fun sub -> typecheck_expr_top_down env sub tau) subs + List.iter (fun except -> typecheck_expr_top_down env except tau) excepts | EIfThenElse (cond, et, ef) -> typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); typecheck_expr_top_down env et tau; diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 2941b0dc..074d94e6 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -25,6 +25,8 @@ module RuleName : Uid.Id with type info = Uid.MarkedString.info = Uid.Make (Uid. module RuleMap : Map.S with type key = RuleName.t = Map.Make (RuleName) +module RuleSet : Set.S with type elt = RuleName.t = Set.Make (RuleName) + (** Inside a scope, a definition can refer either to a scope def, or a subscope def *) module ScopeDef = struct type t = @@ -39,6 +41,11 @@ module ScopeDef = struct Scopelang.Ast.ScopeVar.compare x y | SubScopeVar (_, x), SubScopeVar (_, y) -> Scopelang.Ast.ScopeVar.compare x y + let get_position x = + match x with + | Var x -> Pos.get_position (Scopelang.Ast.ScopeVar.get_info x) + | SubScopeVar (x, _) -> Pos.get_position (Scopelang.Ast.SubScopeName.get_info x) + let format_t fmt x = match x with | Var v -> Scopelang.Ast.ScopeVar.format_t fmt v @@ -62,7 +69,7 @@ type rule = { just : Scopelang.Ast.expr Pos.marked Bindlib.box; cons : Scopelang.Ast.expr Pos.marked Bindlib.box; parameter : (Scopelang.Ast.Var.t * Scopelang.Ast.typ Pos.marked) option; - parent_rule : RuleName.t option; + exception_to_rule : RuleName.t option; } let empty_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked option) : rule = @@ -73,7 +80,7 @@ let empty_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked opti ( match have_parameter with | Some typ -> Some (Scopelang.Ast.Var.make ("dummy", pos), typ) | None -> None ); - parent_rule = None; + exception_to_rule = None; } type assertion = Scopelang.Ast.expr Pos.marked Bindlib.box diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 60e16ebb..8adf2da5 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -20,47 +20,85 @@ module Cli = Utils.Cli (** {1 Rule tree construction} *) -type rule_tree = Leaf of Ast.rule | Node of Ast.rule * rule_tree list +type rule_tree = Leaf of Ast.rule | Node of rule_tree list * Ast.rule (** Transforms a flat list of rules into a tree, taking into account the priorities declared between rules - {e Invariant:} only one rule does not have any parent rule + {e Invariant:} there are no exceptions cycles - {e Invariant:} there are no dandling pointer parents in the rules *) -let rec def_map_to_tree (def : Ast.rule Ast.RuleMap.t) : rule_tree = - (* first we look to the only rule that does not have any parent *) - let has_no_parent _ (r : Ast.rule) = Option.is_none r.Ast.parent_rule in - let no_parent = Ast.RuleMap.filter has_no_parent def in - let no_parent_name, no_parent = - if Ast.RuleMap.cardinal no_parent = 1 then Ast.RuleMap.choose no_parent else assert false + {e Invariant:} there are no dandling exception pointers in the rules *) +let rec def_map_to_tree (def_info : Ast.ScopeDef.t) + (is_def_func : Scopelang.Ast.typ Pos.marked option) (def : Ast.rule Ast.RuleMap.t) : + rule_tree list = + (* first we look to the rules that don't have any exceptions *) + let has_no_exception (r : Ast.RuleName.t) _ = + not + (Ast.RuleMap.exists + (fun _ r' -> match r'.Ast.exception_to_rule with Some r_ex -> r_ex = r | None -> false) + def) in - let def = Ast.RuleMap.remove no_parent_name def in - (* we look for all the direct children of no_parent *) - let children, rest = - Ast.RuleMap.partition (fun _ r -> r.Ast.parent_rule = Some no_parent_name) def + let no_exceptions = Ast.RuleMap.filter has_no_exception def in + (* Then, for each top-level rule (that has no exceptions), we build a rule tree *) + (* Among the top-level rules are the base rules that are exceptions to nothing *) + let base_rules, rules_that_are_exceptions = + Ast.RuleMap.partition (fun _ r -> Option.is_none r.Ast.exception_to_rule) no_exceptions in - if Ast.RuleMap.cardinal children = 0 then Leaf no_parent - (* it doesn't matter that [rest] contains more rules since each rule in [rest] is supposed to - have a parent rule containted in the original tree, so it will get treated at some point *) - else - let children_no_parent = - Ast.RuleMap.map (fun r -> { r with Ast.parent_rule = None }) children - in - let tree_children = - List.map - (fun (child_no_parent_name, child_no_parent) -> - def_map_to_tree (Ast.RuleMap.add child_no_parent_name child_no_parent rest)) - (Ast.RuleMap.bindings children_no_parent) - in - Node (no_parent, tree_children) + let base_trees : rule_tree Ast.RuleMap.t = + Ast.RuleMap.map + (fun r -> + (* we look at the the eventual rule of which r is an exception *) + match r.Ast.exception_to_rule with None -> Leaf r | Some _ -> assert false + (* should not happen *)) + base_rules + in + (* Now let's deal with the rules that are exceptions but have no exception. We have to bucket + these, each bucket containing all the rules that are exception to the same rule *) + let exception_targets = + Ast.RuleMap.fold + (fun _ r acc -> + match r.Ast.exception_to_rule with + | None -> assert false (* should not happen *) + | Some r' -> Ast.RuleMap.add r' () acc) + rules_that_are_exceptions Ast.RuleMap.empty + in + (* In each bucket corresponding to an exception target, we have all the rules that are exceptions + to the target *) + let exception_trees = + Ast.RuleMap.mapi + (fun r' _ -> + (* we recursively call the function of a def where we have removed exception edges: this is + why the function should terminate *) + let def_rec = + Ast.RuleMap.map + (fun r -> + { + r with + Ast.exception_to_rule = + ( match r.Ast.exception_to_rule with + | None -> None + | Some r'' -> if r'' = r' then None else Some r'' ); + }) + def + in + let def_rec = + Ast.RuleMap.filter (fun r _ -> not (Ast.RuleMap.mem r exception_targets)) def_rec + in + let exceptions = def_map_to_tree def_info is_def_func def_rec in + Node (exceptions, Ast.RuleMap.find r' def)) + exception_targets + in + List.map snd (Ast.RuleMap.bindings base_trees) + @ List.map snd (Ast.RuleMap.bindings exception_trees) (** From the {!type: rule_tree}, builds an {!constructor: Dcalc.Ast.EDefault} expression in the scope language. The [~toplevel] parameter is used to know when to place the toplevel binding in the case of functions. *) let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t option) (tree : rule_tree) : Scopelang.Ast.expr Pos.marked Bindlib.box = - let rule, children = match tree with Leaf r -> (r, []) | Node (r, child) -> (r, child) in + let exceptions, rule = + match tree with Leaf r -> ([], r) | Node (exceptions, r) -> (exceptions, r) + in (* because each rule has its own variable parameter and we want to convert the whole rule tree into a function, we need to perform some alpha-renaming of all the expressions *) let substitute_parameter (e : Scopelang.Ast.expr Pos.marked Bindlib.box) : @@ -77,12 +115,14 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti in let just = substitute_parameter rule.Ast.just in let cons = substitute_parameter rule.Ast.cons in - let children = Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false is_func) children) in + let exceptions = + Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false is_func) exceptions) + in let default = Bindlib.box_apply3 - (fun just cons children -> - (Scopelang.Ast.EDefault (just, cons, children), Pos.get_position just)) - just cons children + (fun exceptions just cons -> + (Scopelang.Ast.EDefault (exceptions, just, cons), Pos.get_position just)) + exceptions just cons in match (is_func, rule.parameter) with | None, None -> default @@ -99,8 +139,6 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) (typ : Scopelang.Ast.typ Pos.marked) : Scopelang.Ast.expr Pos.marked = (* Here, we have to transform this list of rules into a default tree. *) - (* Because we can have multiple rules at the top-level and our syntax does not allow that, we - insert a dummy rule at the top *) let is_func _ (r : Ast.rule) : bool = Option.is_some r.Ast.parameter in let all_rules_func = Ast.RuleMap.for_all is_func def in let all_rules_not_func = Ast.RuleMap.for_all (fun n r -> not (is_func n r)) def in @@ -128,22 +166,15 @@ let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) Pos.get_position (Bindlib.unbox r.Ast.cons) )) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_func n r)) def)) ) in - let dummy_rule = Ast.empty_rule Pos.no_pos is_def_func in - let dummy_rule_name = Ast.RuleName.fresh ("dummy", Pos.no_pos) in - let def = - Ast.RuleMap.add dummy_rule_name dummy_rule - (Ast.RuleMap.map - (fun r -> - match r.Ast.parent_rule with - | Some _ -> r - | None -> { r with parent_rule = Some dummy_rule_name }) - def) - in - let def_tree = def_map_to_tree def in + let top_list = def_map_to_tree def_info is_def_func def in Bindlib.unbox (rule_tree_to_expr ~toplevel:true (Option.map (fun _ -> Scopelang.Ast.Var.make ("ρ", Pos.no_pos)) is_def_func) - def_tree) + ( match top_list with + | [] -> + (* In this case, there are no rules to define the expression *) + Leaf (Ast.empty_rule Pos.no_pos is_def_func) + | _ -> Node (top_list, Ast.empty_rule Pos.no_pos is_def_func) )) (** Translates a scope *) let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 1d8b69bd..17ef90e5 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -94,7 +94,7 @@ type expr = | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list | EOp of Dcalc.Ast.operator - | EDefault of expr Pos.marked * expr Pos.marked * expr Pos.marked list + | EDefault of expr Pos.marked list * expr Pos.marked * expr Pos.marked | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked let rec locations_used (e : expr Pos.marked) : LocationSet.t = @@ -121,11 +121,11 @@ let rec locations_used (e : expr Pos.marked) : LocationSet.t = | EIfThenElse (e1, e2, e3) -> LocationSet.union (locations_used e1) (LocationSet.union (locations_used e2) (locations_used e3)) - | EDefault (just, cons, subs) -> + | EDefault (excepts, just, cons) -> List.fold_left - (fun acc sub -> LocationSet.union (locations_used sub) acc) + (fun acc except -> LocationSet.union (locations_used except) acc) (LocationSet.union (locations_used just) (locations_used cons)) - subs + excepts type rule = | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 02a863ec..3510fb6a 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -106,10 +106,10 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = e1 format_expr e2 format_expr e3 | EOp (Binop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_binop (op, Pos.no_pos) | EOp (Unop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_unop (op, Pos.no_pos) - | EDefault (just, cons, subs) -> - if List.length subs = 0 then + | EDefault (excepts, just, cons) -> + if List.length excepts = 0 then Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons else - Format.fprintf fmt "@[⟨%a ⊢ %a |@ %a⟩@]" format_expr just format_expr cons + Format.fprintf fmt "@[⟨%a@ |@ %a ⊢ %a⟩@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) - subs + excepts format_expr just format_expr cons diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index cef03149..33356632 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -68,7 +68,7 @@ let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) Bindlib.box_apply2 (fun caller callee -> ( Dcalc.Ast.EDefault - ((Dcalc.Ast.ELit (Dcalc.Ast.LBool true), Pos.no_pos), caller, [ callee ]), + ([ caller ], (Dcalc.Ast.ELit (Dcalc.Ast.LBool true), Pos.no_pos), callee), Pos.no_pos )) caller callee in @@ -211,11 +211,11 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po Bindlib.box_apply (fun b -> Dcalc.Ast.EAbs (pos_binder, b, List.map (translate_typ ctx) typ)) binder - | EDefault (just, cons, subs) -> + | EDefault (excepts, just, cons) -> Bindlib.box_apply3 - (fun j c s -> Dcalc.Ast.EDefault (j, c, s)) + (fun e j c -> Dcalc.Ast.EDefault (e, j, c)) + (Bindlib.box_list (List.map (translate_expr ctx) excepts)) (translate_expr ctx just) (translate_expr ctx cons) - (Bindlib.box_list (List.map (translate_expr ctx) subs)) | ELocation (ScopeVar a) -> Bindlib.box_var (fst (Ast.ScopeVarMap.find (Pos.unmark a) ctx.scope_vars)) | ELocation (SubScopeVar (_, s, a)) -> ( diff --git a/tests/test_default/conflict.catala.A.out b/tests/test_default/conflict.catala.A.out index d9df4b10..50a09b66 100644 --- a/tests/test_default/conflict.catala.A.out +++ b/tests/test_default/conflict.catala.A.out @@ -1,4 +1,4 @@ -[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] There is a conflict between multiple exceptions for assigning the same variable. [ERROR] [ERROR] This justification is true: [ERROR] --> test_default/conflict.catala diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out index e21ec185..f2799c4a 100644 --- a/tests/test_func/func.catala.S.out +++ b/tests/test_func/func.catala.S.out @@ -1,4 +1,4 @@ -[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] There is a conflict between multiple exceptions for assigning the same variable. [ERROR] [ERROR] This justification is true: [ERROR] --> test_func/func.catala diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out index 70c03391..c4eefbc9 100644 --- a/tests/test_money/no_mingle.catala.A.out +++ b/tests/test_money/no_mingle.catala.A.out @@ -18,7 +18,7 @@ [ERROR] 12 | def z := (x *$ y) [ERROR] | ^^ [ERROR] -[ERROR] Type money → money coming from expression: +[ERROR] Type money → any type coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | [ERROR] 12 | def z := (x *$ y) @@ -30,7 +30,7 @@ [ERROR] 12 | def z := (x *$ y) [ERROR] | ^^ [ERROR] -[ERROR] Type money → money → money coming from expression: +[ERROR] Type money → money → any type coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | [ERROR] 12 | def z := (x *$ y) diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index d2c46188..da0d117b 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -1,4 +1,4 @@ -[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] There is a conflict between multiple exceptions for assigning the same variable. [ERROR] [ERROR] This justification is true: [ERROR] --> test_scope/scope.catala diff --git a/tests/test_scope/sub_sub_scope.catala.B.out b/tests/test_scope/sub_sub_scope.catala.B.out index 0002ddb0..2c583348 100644 --- a/tests/test_scope/sub_sub_scope.catala.B.out +++ b/tests/test_scope/sub_sub_scope.catala.B.out @@ -1,4 +1,4 @@ -[ERROR] There is a conflict between multiple rules for assigning the same variable. +[ERROR] There is a conflict between multiple exceptions for assigning the same variable. [ERROR] [ERROR] This justification is true: [ERROR] --> test_scope/sub_sub_scope.catala From 6ac46a0b8ffdf8812db872c81140faa2a3bd0ab3 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 18 Dec 2020 16:22:23 +0100 Subject: [PATCH 092/142] Unit tests for tutorial --- examples/Makefile | 11 +++++-- .../tutorial/tests/test_tutorial.catala_en | 29 +++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 examples/tutorial/tests/test_tutorial.catala_en diff --git a/examples/Makefile b/examples/Makefile index 87471edf..5ff13a4d 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -20,13 +20,20 @@ TEST_FILES=$(wildcard */tests/*.catala*) -TEST_FILES_SCOPES=$(foreach TEST_FILE,$(TEST_FILES),\ +TEST_FILES_SCOPES_EN=$(foreach TEST_FILE,$(TEST_FILES),\ $(foreach TEST_SCOPE,\ $(shell grep -Po "declaration scope [^:]*" $(TEST_FILE) | cut -d " " -f 3), \ $(word 1,$(subst /, ,$(TEST_FILE))).$(word 1,$(subst ., ,$(word 3,$(subst /, ,$(TEST_FILE))))).$(TEST_SCOPE).run \ ) \ ) -test_examples: $(TEST_FILES_SCOPES) +TEST_FILES_SCOPES_FR=$(foreach TEST_FILE,$(TEST_FILES),\ + $(foreach TEST_SCOPE,\ + $(shell grep -Po "déclaration champ d'application [^:]*" $(TEST_FILE) | cut -d " " -f 3), \ + $(word 1,$(subst /, ,$(TEST_FILE))).$(word 1,$(subst ., ,$(word 3,$(subst /, ,$(TEST_FILE))))).$(TEST_SCOPE).run \ + ) \ +) + +test_examples: $(TEST_FILES_SCOPES_EN) $(TEST_FILES_SCOPES_FR) .FORCE: \ No newline at end of file diff --git a/examples/tutorial/tests/test_tutorial.catala_en b/examples/tutorial/tests/test_tutorial.catala_en new file mode 100644 index 00000000..80153178 --- /dev/null +++ b/examples/tutorial/tests/test_tutorial.catala_en @@ -0,0 +1,29 @@ +@@Include: ../tutorial_en.catala_en@@ + +@Test@ + +/* +declaration scope UnitTest1: + context tax_computation scope NewIncomeTaxComputation + +scope UnitTest1: + definition + tax_computation.individual + equals + Individual { + -- income: $230,000 + -- number_of_children: 0 + } + assertion tax_computation.income_tax = $72,000 + +declaration scope UnitTest2: + context tax_computation scope NewIncomeTaxComputationFixed + +scope UnitTest2: + definition tax_computation.individual equals Individual { + -- income: $4,000 + -- number_of_children: 0 + } + + assertion tax_computation.income_tax = $0.00 +*/ \ No newline at end of file From ed29103742a7681c3956d765b0b52388559b614c Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 18 Dec 2020 16:40:43 +0100 Subject: [PATCH 093/142] Finished tutorial --- examples/tutorial/tutorial_en.catala_en | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index ce7b87de..ac88294f 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -320,11 +320,15 @@ scope Test2: This test case should compute a $0 income tax because of Article 6. But instead, execution will yield an error saying that there is a conflict between rules. +@@Defining exceptions to rules@@+ + Indeed, the definition of the income tax in article 6 conflicts with the definition of income tax in article 5. But actually, article 6 is just an exception of article 5. In the law, it is implicit that if article 6 is applicable, then it takes precedence over article 5. +@Fixing the computation@ + This implicit precedence has to be explicitely declared in Catala. Here is a fixed version of the NewIncomeTaxComputation scope: @@ -341,9 +345,13 @@ scope NewIncomeTaxComputationFixed : -- rate2: 40% } + # To define an exception to a rule, you have to first label the rule that + # you want to attach to exception to. You can put any snake_case identifier + # for the label label article_5 definition income_tax equals two_brackets.tax_formula of individual.income + # Then, you can declare the exception by referring back to the label exception article_5 definition income_tax under condition individual.income <=$ $10,000 @@ -361,6 +369,16 @@ scope Test3: -- income: $4,000 -- number_of_children: 0 } - assertion tax_computation.income_tax = $0 -*/ \ No newline at end of file +*/ + +@@Conclusion@@+ + +This tutorial present the basic concepts and syntax of the Catala language +features. It is then up to you tu use them to annotate legislative texts +with their algorithmic translation. + +There is no single way to write Catala programs, as the program style should be +adapted to the legislation it annotates. However, Catala is a functional +language at heart, so following standard functional programming design patterns +should help achieve concise and readable code. \ No newline at end of file From 14eec276e3cfdc2eaee493532f922aaf0cbc4f00 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 18 Dec 2020 19:24:04 +0100 Subject: [PATCH 094/142] Change formalization with the exceptions --- doc/formalization/formalization.tex | 147 +++++++++++++--------------- 1 file changed, 70 insertions(+), 77 deletions(-) diff --git a/doc/formalization/formalization.tex b/doc/formalization/formalization.tex index 798c6df5..e058d6d2 100644 --- a/doc/formalization/formalization.tex +++ b/doc/formalization/formalization.tex @@ -175,7 +175,7 @@ lambda-calculus extensions (such as algebraic data types or $\Lambda$-polymorphi &&\synalt&\synlambda\synlparen\synvar{x}\syntyped\synvar{\tau}\synrparen\syndot\synvar{e}\synalt\synvar{e}\;\synvar{e}&$\lambda$-calculus\\ &&\synalt&\synvar{d}&default term\\ &&&&\\ - Default&\synvar{d}&\syndef&\synlangle\synvar{e}\synjust\synvar{e}\synmid $[\synvar{e}^*]$\synrangle&default term\\ + Default&\synvar{d}&\syndef&\synlangle $[\synvar{e}^*] \synmid\synvar{e}\synjust\synvar{e}$\synrangle&default term\\ &&\synalt&\synerror&conflict error term\\ &&\synalt&\synemptydefault&empty error term\\ \end{tabular} @@ -183,7 +183,8 @@ lambda-calculus extensions (such as algebraic data types or $\Lambda$-polymorphi Compared to the regular lambda calculus, we add a construction coming from default logic. Particularly, we focus on a subset of default logic called -categorical, prioritized default logic \cite{Brewka2000}. In this setting, a default is a logical +categorical, prioritized default logic \cite{Brewka2000}. +In this setting, a default is a logical rule of the form $A \synjust B$ where $A$ is the justification of the rule and $B$ is the consequence. The rule can only be applied if $A$ is consistent with the current knowledge $W$: from $A\wedge W$, one should not derive $\bot$. @@ -196,19 +197,18 @@ be an expression that can be evaluated to \syntrue{} or \synfalse{}, and $B$ the expression that the default should reduce to if $A$ is true. If $A$ is false, then we look up for other rules of lesser priority to apply. This priority is encoded trough a syntactic tree data structure\footnote{Thanks to Pierre-Évariste Dagand for this insight.}. -A node of the tree contains a default to consider first, and then a list of lower-priority -defaults that don't have a particular ordering between them. This structure is +A node of the tree contains a base case to consider, but first a list of higher-priority +exceptions that don't have a particular ordering between them. This structure is sufficient to model the base case/exceptions structure or the law, and in particular the fact that exceptions are not always prioritized in the legislative text. -In the term \synlangle\synvar{e_{\text{just}}}\synjust -\synvar{e_{\text{cons}}}\synmid \synvar{e_1}\synellipsis\synvar{e_n}\synrangle, \synvar{e_{\text{just}}} +In the term \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid\synvar{e_{\text{just}}}\synjust +\synvar{e_{\text{cons}}} \synrangle, \synvar{e_{\text{just}}} is the justification $A$, \synvar{e_{\text{cons}}} is the consequence $B$ and -\synvar{e_1}\synellipsis\synvar{e_n} is the list of rules to be considered if \synvar{e_{\text{just}}} -evaluates to \synfalse{}. +\synvar{e_1}\synellipsis\synvar{e_n} are the list of exceptions to be considered first. Of course, this evaluation scheme can fail if no more -rules can be applied, or if two or more rules of the same priority have their +rules can be applied, or if two or more exceptions of the same priority have their justification evaluate to \syntrue{}. The error terms \synerror{} and \synemptydefault{} encode these failure cases. Note that if a Catala program correctly derived from a legislative source evaluates to \synerror{} or \synemptydefault{}, this could mean a flaw in the @@ -275,14 +275,15 @@ of the default should be typed. \begin{mathpar} \inferrule[T-Default] { - \typctx{\Gamma}\typvdash\synvar{e_{\text{just}}}\typcolon\synbool\\ - \typctx{\Gamma}\typvdash\synvar{e_{\text{cons}}}\typcolon\synvar{\tau}\\ \typctx{\Gamma}\typvdash\synvar{e_1}\typcolon{\tau}\\ \cdots\\ - \typctx{\Gamma}\typvdash\synvar{e_n}\typcolon{\tau} + \typctx{\Gamma}\typvdash\synvar{e_n}\typcolon{\tau}\\ + \typctx{\Gamma}\typvdash\synvar{e_{\text{just}}}\typcolon\synbool\\ + \typctx{\Gamma}\typvdash\synvar{e_{\text{cons}}}\typcolon\synvar{\tau} } - {\typctx{\Gamma}\typvdash\synlangle\synvar{e_{\text{just}}}\synjust\synvar{e_{\text{cons}}}\synmid - \synvar{e_1}\synellipsis\synvar{e_n}\synrangle\typcolon\synvar{\tau}} + {\typctx{\Gamma}\typvdash\synlangle + \synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_{\text{just}}}\synjust\synvar{e_{\text{cons}}}\synrangle\typcolon\synvar{\tau}} \end{mathpar} The situation becomes more complex in the presence of functions. Indeed, want @@ -307,11 +308,11 @@ currently being reduced. &&\synalt&\syntrue\synalt\synfalse & booleans\\ &&\synalt&\synerror\synalt\synemptydefault&errors\\ Evaluation &\synvar{C_\lambda}&\syndef&\synhole\;\synvar{e}\synalt\synvar{v}\;\synhole&function application\\ - contexts&&\synalt&\synlangle\synhole\synjust\synvar{e}\synmid $[\synvar{e}^*]$\synrangle&default justification evaluation\\ + contexts&&\synalt&\synlangle$[\synvar{v}^*]$\syncomma\synhole\syncomma$[\synvar{e}^*]$\synmid + \synvar{e}\synjust\synvar{e}\synrangle&default exceptions evaluation\\ &\synvar{C}&\syndef&\synvar{C_\lambda}®ular contexts\\ - &&\synalt&\synlangle\syntrue\synjust\synhole\synmid $[\synvar{e}^*]$\synrangle&default consequence evaluation\\ - &&\synalt&\synlangle\synfalse\synjust\synvar{e}\synmid $[\synvar{v}^*]$% - \syncomma\synhole\syncomma$[\synvar{e}^*]$\synrangle&sub-default evaluation + &&\synalt&\synlangle$[\synvar{v}^*]$\synmid\synhole\synjust\synvar{e}\synrangle&default justification evaluation\\ + &&\synalt&\synlangle$[\synvar{v}^*]$\synmid\syntrue\synjust\synhole \synrangle&default consequence evaluation\\ \end{tabular} \end{center} @@ -331,70 +332,55 @@ later. } \end{mathpar} -Now we have to describe how the default terms reduce. Thanks to a the -\TirName{D-Context} rule, we can suppose that the justification of the default -is already reduced to a variable \synvar{v}. By applying the beta-reduction -rule \TirName{D-$\beta$}, we can further reduce to the case where \synvar{v} is a boolean. -This is where we encode our default logic evaluation semantics. If \synvar{v} is -\syntrue{}, then this rule applies and we reduce to the consequence. We don't -even have to consider rules of lower priority lower in the tree. This behavior -is similar to short-circuit reduction rules of boolean operators, that enable -a significant performance gain at execution. -\begin{mathpar} - \inferrule[D-DefaultTrueNoError] - {v\neq\synemptydefault} - {\synlangle \syntrue\synjust \synvar{v}\synmid \synvar{e_1}\synellipsis\synvar{e_n}\synrangle\exeval v} -\end{mathpar} - -However, if the consequence of the first default evaluates to \synemptydefault, -then we fall back on the rules of lower priority, as if the justification had -evaluated to \synfalse. This behavior is useful when the consequence of the -first default is itself a \enquote{high-priority} default tree. In this case, - \synvar{e_1}\synellipsis\synvar{e_n} acts a the \enquote{low-priority} default - tree. The chaining -behavior from the high-priority tree to the low-priority tree -defined by \TirName{D-DefaultTrueError}, will be very useful in -\sref{scope:formalization}. -\begin{mathpar} - \inferrule[D-DefaultTrueError] - {} - { - \synlangle \syntrue\synjust \synemptydefault\synmid \synvar{e_1}\synellipsis\synvar{e_n}\synrangle\exeval - \synlangle \synfalse\synjust \synemptydefault\synmid \synvar{e_1}\synellipsis\synvar{e_n} \synrangle - } -\end{mathpar} - -If the consequence of the default is \synfalse{}, then we have to consider rules of lower priority -\synvar{e_1}\synellipsis\synvar{e_n} that should be all evaluated (left to right), +Now we have to describe how the default terms reduce. First, we consider +the list of exceptions to the default, +\synvar{e_1}\synellipsis\synvar{e_n}, that should be all evaluated (left to right), according to the sub-default evaluation context. Then, we consider all the -values yielded by the sub-default evaluation and define two functions over these +values yielded by the exception evaluation and define two functions over these values. Let $\exeemptysubdefaults(\synvar{v_1}\synellipsis\synvar{v_n})$ returns -the number of empty error terms \synemptydefault{} among the values. We then case analyze on this count: +the number of empty error terms \synemptydefault{} among the exception values. + We then case analyze on this count: \begin{itemize} \item if $\exeemptysubdefaults(\synvar{v_1}\synellipsis\synvar{v_n}) =n$, then - none of the sub-defaults apply and we return \synemptydefault; + none of the exceptions apply and we evaluate the base case; \item if $\exeemptysubdefaults(\synvar{v_1}\synellipsis\synvar{v_n}) =n - 1$, - then only only one of the sub-default apply and we return its corresponding value; + then only only one of the exceptions apply and we return its corresponding value; \item if $\exeemptysubdefaults(\synvar{v_1}\synellipsis\synvar{v_n}) < n - 1$, - then two or more sub-default apply and we raise a conflict error \synerror. + then two or more exceptions apply and we raise a conflict error \synerror. \end{itemize} \begin{mathpar} - \inferrule[D-DefaultFalseNoSub] + \inferrule[D-DefaultFalseNoExceptions] {} - {\synlangle \synfalse\synjust \synvar{e}\synmid \synemptydefault{}\synellipsis\synemptydefault{}\synrangle\exeval \synemptydefault{}} + {\synlangle \synemptydefault{}\synellipsis\synemptydefault{}\synmid\synfalse\synjust \synvar{e} \synrangle\exeval \synemptydefault{}} - \inferrule[D-DefaultFalseOneSub] + \inferrule[D-DefaultTrueNoExceptions] {} - {\synlangle \synfalse\synjust \synvar{e}\synmid - \synemptydefault\synellipsis\synemptydefault\syncomma\synvar{v}\syncomma\synemptydefault\synellipsis\synemptydefault\synrangle\exeval \synvar{v}} + {\synlangle \synvar{e_1}\synellipsis\synvar{e_n}\synmid\syntrue\synjust \synvar{v}\synrangle\exeval v} - \inferrule[D-DefaultFalseSubConflict] + + \inferrule[D-DefaultOneException] + {} + {\synlangle \synemptydefault\synellipsis\synemptydefault\syncomma\synvar{v}\syncomma\synemptydefault\synellipsis\synemptydefault + \synmid \synvar{e_1}\synjust \synvar{e_2} + \synrangle\exeval \synvar{v}} + + \inferrule[D-DefaultExceptionsConflict] {\exeemptysubdefaults(\synvar{v_1}\synellipsis\synvar{v_n}) - rule b = < true :- a + 1 | > + rule a = < true :- 0 > + rule b = < true :- a + 1 > scope Y: - rule X_1[a] = < true :- 42 | > + rule X_1[a] = < true :- 42 > call X_1 - rule c = < X_1[b] == 1 :- false | >, < X_1[b] == 43 :- true | > + rule c = < X_1[b] != 43 :- false | X_1[b] == 43 :- true > \end{Verbatim} Considered alone, the execution \Verb+X+ is simple: \Verb+a+ and \Verb+b+ are defined by @@ -498,7 +485,7 @@ a single default whose justification is \Verb+true+. Hence, \Verb+a+ should eval to \Verb+0+ and \Verb+b+ should evaluate to \Verb+1+. Now, consider scope \Verb+Y+. It defines a single variable \Verb+c+ with two defaults -lines 8 and 9, but the justifications for these two defaults use the result of +line 8, but the justifications for these two defaults use the result of the evaluation (line 7) of variable \Verb+b+ of the sub-scope \Verb+X_1+. Line 6 shows an example of providing an \enquote{argument} to the subscope call. The execution goes like this: at line 7 when calling the sub-scope, @@ -506,7 +493,9 @@ The execution goes like this: at line 7 when calling the sub-scope, from line 6. Because the caller has priority over the callee, the default from line 6 wins and \Verb+X_1[a]+ evaluates to \Verb+42+. Consequently, \Verb+X_1[b]+ evaluates to \Verb+43+. -This triggers the second default in the list of line 9 which evaluates \Verb+c+ to \Verb+true+. +This triggers the second default in the list of line 8: the exception +evaluates first, but does not apply. Then, the base case applies, +and evaluates \Verb+c+ to \Verb+true+. The goal is to provide an encoding of the scope language into the lambda calculus that is compatible with this intuitive description @@ -515,9 +504,9 @@ picture of the translation, we first show what the previous simple program will to, using ML-like syntax for the target default calculus: \begin{Verbatim}[frame=lines,label=Simple default program, numbers=left, framesep=10pt, samepage=true] let X (a: unit -> int) (b: unit -> int) : (int * int) = - let a : unit -> int = a ++ (fun () -> < true :- 0 | >) in + let a : unit -> int = < a | true :- fun () -> < true :- 0 >> in let a : int = a () in - let b : unit -> int = b ++ (fun () -> < true :- a + 1 | >) in + let b : unit -> int = < b | true :- fun () -> < true :- a + 1 >> in let b : int = b () in (a, b) @@ -525,13 +514,17 @@ let Y (c: unit -> bool) : bool = let X_1[a] : unit -> int = fun () -> < true :- 42 | > in let X_1[b] : unit -> int = fun () -> EmptyError in let (X_1[a], X_1[b]) : int * int = X(X_1[a], X_1[b]) in - let c : unit -> bool = c ++ (fun () -> - < X_1[b] == 1 :- false>, < X_1[b] == 43 :- true >) + let c : unit -> bool = + < c | true :- fun () -> + < X_1[b] != 43 :- false | X_1[b] == 43 :- true > + > in let c : bool = c () in c \end{Verbatim} +% TODO: fix text below here + We start unravelling this translation with the scope \Verb+X+. \Verb+X+ has been turned into a function whose arguments are all the local variables of the scope. However, the arguments have type \Verb+unit -> +. Indeed, we want the From 01b1fdf0b67fcdfe1c48c282fea07acb2f301e6c Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 14:50:45 +0100 Subject: [PATCH 095/142] Updated formalization --- doc/formalization/formalization.pdf | Bin 358913 -> 357410 bytes doc/formalization/formalization.tex | 92 ++++++++++++---------------- 2 files changed, 38 insertions(+), 54 deletions(-) diff --git a/doc/formalization/formalization.pdf b/doc/formalization/formalization.pdf index 5e418d71bde9ee3069ae9991d10e1f6728c4c1af..392dd3fb9657faee271efcecb951449ed457d3df 100644 GIT binary patch delta 83087 zcmV(^K-Is2^cAA$6|gJ<0r`_H0!#sAvw8v}1_aP*qqCEt2q*$GHkaX|0Vsd1TT7GU zwh_MXuTW0WRIRvp@#R#?6~9u>A$IJk%3*g?;YgH*HYLg=<(bLBzdii`NP?oMk=KVE zfp~T|8r@$vuwt=Wh{fOE2>biR{hN2+=y)MzkcOdJ+;11LTEt-zq*^ZSH;ea670A1l zlqy{Q_;R?@a@l6jcOUQn(anG1e&2l~VImQvB9%B%qyi(&VkOfc3GHO}cPd%F9Pd`} zljAJ!zA?fZqyrPfbkzHU(1ttdbl6G8KyB)JefHU3nVukmDzT`699#SWsWQ=UtcrqA zNH_MOs!ER;=q|nPAxNTI>ZcnPiUQHocsdmAXdPczaTJ)o`vVE6;=g}oo*nL1TI*$Y z*l>ZSgOXXcLxDC{q8RqWD<9dC;mj2Lana3r(`^GAO=46x)MC4XO%KnmY{ zo}I^`n&fb}-v6*L>-7^ zY%@Wl!4Jp6YPf$$pclGjt5`x$F=B#P!yz5?{CJg>Bmh7%vO5FoU9^}rh@j_bPvE4w-RADqWrhFk6$-zu4q#)#Vr_}Y z>$<8xg&uvGp3h%FPrg4g0Al};*LQMhDKf(Y8Ob1tLMVTL-2nBYv0qmEV^-&gsDxU! z75)OaeFU(J_6I-ee0M6dntPPl9+zThw#m2>EDtP+#s`Nr=%+-oe7YlqLUUvrY}wck zJE}S~;MN_qp_+Yh*m0+AUG2HH-*8;N+7;`783F^7I+Nx^`aLe1)ormxn#-5FL@$Y+ zu%kz%$#Q>-s4@nU8~#QL@HgY1=Je3yt!>)!Z$}1x5E)pEk@*tkht=z>&39E@K%HIm zSQqf!7XNcy2Ghj-G|BS4{K#wxpP_G2HY$ZJDH_~Su>{Im5Yt=!%D8!OD#Vg{LZxk^ zRbY$gqozH={mQvB^2ZD0T-aiV3YBO-iTFZLqdtE+`P)_V0#Q{Qn{)e;+-6_Y(7b#x zc`P{8vI{*u=JjN71qdz_%A@~mCXZw%PL>de?59)H76>z7zgc;qmE;JG*o)K?PG6wG zzI)qQpGp$5pfF~FI-_7|xAG-6wbVXw!fl_RW0n7M$`9*2xLX+`miMlyUwlo$6cnmM z`NDst2OCi^amQm>kX3+>Vmqk^CJaoZugNir&qzfIi>A#FcpzJ@dn(Z8FeA?P$P^A} zU1Ps^*;=6j_eze0`tzZ}sh;2*?k2Z91kc@>)PG-~G?7WKq^nREwn0-GWB`YRBhGz; z55+`vO7@?rSyJ$7>IS0lz{j{_D4R$xo5z3ZRBpI@s9G*;^1ApHzC5E5<5t(!@ z;97c+0~!>9Tl;p)vy<%yGgBN(O9ZM^GsRs3F|p7$SP2!#9)A5^6cQ!TgqcusfYA~N zt-%R`W@_6@PKzN*0VnjmE}T~d)?}m$*ZGv6&S(4@K8?qxn&J~I1Yl%>8Pr<5+u=T+Goux5WgR!vXCg`;18a5H$O1MH@ zopz6QSxZ>{3_aF`C8DZP@c}zbcu+RX+L>>|I?K*>3PRi?W&nI(61gl6>#F8lOI3q& z=UVo~SlU*AuBe2o;IDP*Jh&+~c1VA9s=08it6iP#8R*b}?65m!I}}(b2{qy2r6$B6 zQ|2dzT~3mD%c}#^oxav`(`_bxWCymW2Ee2ajW2_|PadsI1XlVHw;M~O8Cd8igO8l^ z6y*tIw6Q~~8*(r*0p&~8Otxo~BSDbd*)aesH!Ni!5LR;upR=VR9Sw{yfQNre#sHv& zO!U0>hM-UNX{|>mz>5O!x@`K`d4Z5I2ovq^n)3*-rGVNur!|fgDephjO*`@w%uizG zwMh*f9w|Rehr0w0B8pOU5Yui~Md|ODnRW$4ZP4+P1wl3(fX5!CO$-0bpQoc8h+z-* ztzcMfB|$EVigZYEG>AI4JuQDi=KzZ1iWq>K8p)PIqlhgNMHS>4BLG)qv!KPBh-zF5 zU@<0lLnaMsT4&L4M*eAD80TaV5UpLW+~Rcjpa?2!U2lqW+AlUh#u1m$&8B| zWFeA)yN_U}XpMs-nm@^oM$X_fc@FBrP8*YW*(E@EgzqvigV5hZ#3+CKJY-GIrFB;# z>6(zCA((RX9wuEroLX*2uw6H;H&0o(3Ze{tAB!FA`f9Wh(2zf`QIba#VOu~6j~Uok zUX;%o_S;m4KilGChT|=iqHfugb2)agCdevEtRsRIXn`G8#?Dj{MXbcA(uxoF9#Oi| zR*|rKzqizft1&1ADMWwkqQlLKtt^e%yS*yAiS61XV?~y`$={(Qju^BwQ``(z#^9B5 z2qLsQ4uz70@`Sr1g}sP@>f&I7-GMN?aodb?C8Coxlz~N%JR(9qxhspTQfRk-*RkJ{)q%?c)TCSZt~~vgCgae9U)So8p4du;Fl7xhyYK z42+X0ZROASNlZ3!X> zFqoHKACOPB3%Cxn(8aX;P=qSsWGVhKOo0L?53uB;H>~NP7^m-fSW$EFEEkKFD7?^y zqjtnC(Wrk0(g!Kl>(Qvf;vi>cw9UE_G2ML(5duh}nYxEc!k~}Be!G-S)f4Am`}rKL zgV>k;=ND#6`vlz}M8W-}^FZKS8qzMtgiwztvLP0erJo@N~|ax)xhVM5V4dQ zSJ~8uou{hneBDw`NOpNk*x`*`l<$9_$<8!{aj}1U`C^&yK`b1oHJ!@X%S+Jdb$N-g z^i#CKa$fu@kbSPIbA63?Te?FBmh5n=}18!#}QOl z*e=$5#SWs|*0#yZZ7@Zt5+dlG;O7?^?z$j3ja!U%d%SGymfaK^8y6Y@abf7WHpcb_ zqA!2@hG|`FDNIw#CmV=KIPyo^%E6;#Mxjr}pF689wzer+Hk1@NYM7}g^QnDS5UIxM z>PGiH9NR{AaiUuGkzBF&olDLr;r~!`LtN z8>`Q*pzZYu-u`B5?DuG07^gw7!Mz{L_-B7-&ylU|1Zb7Te+?-x;Y7H?K895GG2}fy zg?u^M%>&8p1lBhJ>>wQU-|M1AJ56Nmselkzxm~jB=;)u zDXlV~OJHr*`#0}Dip2)%AxsZ+nk=5E*M4E5z+hOkC>KAz`Ik2w;-wUPEGE6@W)PHH z1%(~YAY~FLP{L1`0(rPPdc*>~Djt7Z7GOp%6y}K|n{%u4Y}44IX#wU3p~UI1$?NX0 zlLEp)xOpcfps{55mRN{cC=-ou90~utq{Ze3*@GV^Ey~XBJ53>IhVZ;29k{4yYc)yY&jRt=Y*JjVY z=dMji*Lg#CeL1R+K)cL^*FkH}eqyHCvIv4n3_U*_nW_+!kn))>rrBpl_f+ycNdwmD z?D_2tdOCW6dYhRP7ghK#;~l_7};njRDiaxvK=Rmq5qa~lXd_Yn(@+f_ee)Dc-4Qf zP$IIoHGpUlTK9L|Ly`R-^$p}f3T19&b98cLVQmU!Ze(v_Y6>zrATX2g77_w8HJ9O{ z0VsdnTU(FYHWq%LU!lIqK+KAFDn(JWX;N&lD6rkM`;Z1$jjfqcAlp-2GRaGS`yO5- zQM4@EGm~Vx4~aPxbx0nb>&K%cx{i|Qr;Eh>{_y(Z>sMGtI6-NW;^_5Nq!dc2h$Pp) z(6f%-#Q#|+8t028r8KUatZHoYazSML(YAk^8~41e+pN@07FTVV*S2?e<=!qfw~Hl? z%LR@dbnm62ELMN33D zj+R&8ZFMrz>%|DAq55Iu@MG0aYc3r{NhrfRP2{=Ggp92XHqKH#s3H^~IiKTzh zF>jU@!#=GPDF)9irT+$Ggl@tA<~1>XO{B7W?T>^f@DCq+J9=Xn^n7nX(k;<8e|1Ay z+-^I*xX}SW6-F2s>a*eX@^!T!ByRI3&eQ!(&vLh^+WZkYd%4?{bDT{H5{U>n`)Yx) zjI*+S61-K9#@j2srO(M+g@9tf+~0pKbF0tI*TknKkixypelsEidm~cCAI@GM=7vAOz$9BO$~i$$|P5av)BZgD)Zm`Pti22;=*2>g!iTLRf#0%A^~T zu!td^a68T(;mg+-e_mi?Wwf{BNO2ko#Sxb*T5T@gyiKAtJp38fNmCWwnW38q6M`hy zn=7M#U;Jx!Una&1POO_rGT;&a^mf}*y<{fNApGPA1t)%ZGJ8B6N%9%Z!7Onr2gAze zf~pwJP7Z3PTVF`N!(9f_FtC5+tNBfUO0ZLuhZ^N!p7I1{mrF3VEF$1Bdy9K}d%iJ4 zI28{wxTh+{aeD=Pz#bpqz-0<+LxQ@c;j{NAkp#ARB<^L}{8cfaI9?SwDj*Oi!8_h7 z_mq-w9qNJHAp&uocMLS1(&4K~E}wVy31KHWHU@veM4H~$u~9A{ z7Ezzau|41jr6-^vnc<+pJ~UqES6N#&ZhT&CYP47~#^P5+RX5MN_ci+CXyjG3 zt6aYx-wnwek-EvY4jX^E>IP<8AAa&tq$z|*r-msRLqsoj+pDrzH7_fJZ0xG1ntH=f zGP1`6VbTl3U*|hnicw9lkZ%y-bov*glXoENQd%|Cjbf{NL3{GLDYnsMd1wDG^K7dv5$yNwrYQ5NH7jUxd1T3BH?Z1m z>!}r!1V&2V+OL1ItzB0Be!)eYm2KAKw#S%Q_#G@9{Lzh?v~HMySxb8<|1rN>s1)|C z@!E1B;Cz3`>U?TpLZO8B$kbrV^=TUL9;UwO1kNn(rdwr|yH?#)?W$?3+@1kV2vQ1< z&!D>iaBhS7P6B+$&8{ui_JKYo*?XJO?ZDL51%uPzA@+Yi!GU|FBHX1S^3&qhf8SJO zyhS3BB4ikqU~uxl{H`Tz>)e%6F;4WqU_8m@QiAP0KmeWQJ}f0T7ttJ_&=+In0Ye&? z{_`{z`~qi(*?HO(hA-%QHxB14he13})YIp6=d{k_bqcv8eyHdM0IWjboj9m_Lg`$Z zO0mA3=J$V1Qwi2M1Bp1{2y^!N?s*-?e>0D^KnO$A^Ap)w;1fiVji4Imq+nz8hOLdiaF;Q1rpD&zr^C+c1?dGBI!fY$1uxL6iG#)fq}B@@dyY3 z6A{-%)7rEG{**3?&sV#R2~T0bW>>kP(0N8{lZH2>uwlJP zyj*`gYak7HV73Ookga8#98xj87A{%*!^dtw=~`J??(~}Obc#2jz(f*AjnpHhSqf5c z-@@A+i0%w}p*!wVNs2Hz=v4QzC8C>ySy@sg^;uXD%4W0X9A$UB&}i$t>KSbl5e90h zf@4|dt1>eJBba+xaF6x&fe{|)&!!YB3GaXMWXcX+qU|viJXt^5AzU!gU6tL|!J>u~ z33{)p-NttJ&v$K87wcRL3sv!NwMqLeg`&1Y>Xqi&O}@!B7bVdGx{;eobIb_mRj6z`y3M8PFuSi;Nq3qfq^-oqZ_8DJ5R z`tuG7?+fX`l3W)(teVK~$e@2<6?At+Z_X5M;P{qxliwQqL33aNFBGJkyqCm;qlluz7n8lMVb7f%mX2M{2r zB#cVI*25BJqEkk}j}O7APXmMTl@V10VbHl58i~Gi)A{)x4bD))*u!XadpUnjBiPGC z!KhvkVHAjQM7!Vub$${05;@Yue`qmc)Ok|IOigH++s-oEUboq`u~w|p@v=3p9v)l6 z&8T%*=4}fXd8l4(-t`>2o366I-Bkml1Lz5^w%1IiOIUMDJ9Dpe*xT~3x9=hpnd*4V zLa`s3+V)t#33>@3kXRKCSG9jWJq3lYS5?vZR5Q>ywbTa(d-}U-omblEt3+EM%c1_c zvh&Mfe&yJv$@ONvS8;C-cZI%`F?TCgk8gIRQ{-a1E;P7nJd6+H)$Qd{^U>AlwpHct zZh-ULo6K4m2jvaXXIBG7QzJ{}VoJHF<9B^DRtTo9>$E8M4)wh=;vs)5AO<`C{Q0*> zow~k<{v2g7>Is#_&`(wt6Iu+eFNgc-20fhs6qg#=mLdpK-klM7>eOtwl-aBH-9s=r z=yrcB=S<|MI{SsMArGX^M0+;vT}_<84DKy)?}Bi&>A$9knae6R+GuzkCj6^`@1{;N zr3lNxvue}oE@B8UQu2Rvd~Pqt)@(wX1-P4`Q1-d-CDwe&{5J!<`6c8U*zSok17=G|q?6F)?Iy!4SnILIb;P8|C{E`_4WL&JD7 z$~Ma)7>>vF%Z|_IA!lq4Ih);&;Z-t)h3%#6kSPz4`sm^^|FFt$yC@T)oBXJSTVgIP z+U0BFi>Xu6nInItLEJJGstm^KT#FfE69goJ_$IT;uiG+nB{#?H#W8RFCGCbfStHaV zXaww#6MmY7fQX3^_Jrl1DI|uCj^zJctKH4G`ok*5lp>rM&HSJEm{VotwD597;N*|i zA_|O=#7dGlAW3*ylEjRcJ1R4jA~l3dBbm|n75Sg7gW`WDji&x~M_;LMn+b{#J;SlZ zHC@D9yUxr#(C;|L5{7Y%m15f=@X%lyxYph2`m8mdRSHuv|XN&w*5Mb z*P9bb{L6o?af1!=ykAX26N=an4E?x#vD+F-Q)yfZLwk){+q1AA{Hl1nYwU8?xh)G- z7GAKxydX%4@V+Fd0d;kvccxCXSePT1u>&X^gbb~lOm`0zst&xEs!MIEJZr|tWnWF| z&2A#-3MSl{R(9=~wGzaonk+*y7aXH1q=0!rn(Tjl=OCXB3JL}={77n#4rK3;I4-?$ z_a`PHI#wfE-%k4qL~tJok%hTMznaW^xo;=`nk?%>Y;XkMOeMa|ueSJZI#2UxTu+oT zFan7z7;q*LPiJcxFovOwjUm=RSOiBr!c;(@%w_^cg}6M!3FcEY{IKBd84@|Z>Ai2L0fr5bbL%YCGQvImt&gmEqZQXHZ|wc4bxUo zK#~~1hBNS_2HeRL{A`b$j!)7j^x58=3Urh08!j?z_x)LxTRw{AKD^}PYVu(c?D22p zjZivAt0 zO=LgVr()tWJJ1E6rq_O6!qU{;L_lPedY`6nhDY=3U=<>)%A={@EsNR_++EF;fOzPD zE|}lBUlTe)!!2#H77G(y<$m5bY3I~|iN~%3Q>WK~$rJ0q{JPq`@Y9qsjdrqR3F%F0 zDuBCvRk>2}aJ>e9WF~lohF^Q{25P%l=2wk>VjwFz0KL93k)t*VW-f>gSF2sMws%{0 z^aupt2?Qg|NV-xER-mIH5H$P`#|S(5lW8R<0yH$2(KiJtf9)IFj@vf&JzwE{lYv+j zNl~J@y9m%WX;XB!*mi(Eq`^XC(_?jI$<<{tvk(3DJr_!rWQ}Jgw`PkXKul7Hhveb8 z^GvX~S_F%)p9Jpri;E|py%6z21bz}EVsWuu#Bvd9<0lGwo5d@y+1cev#m1}K%hkqi z(>8B-z+Nx4fA-S6O`EJNcx(*~X}reXH2!j>VdP?Gi>L6>B;FhRWP89m+t`YGX`XYV zU#-J!Ywq7>Hs9C{cP3wG#+z(J3{`qE6A>q0C z!`DFkI2;mR#)%)91ORx~`$NM=1r*bZlChuYr~~~sgN)G`Ul`dztjo6O_QJRS*$b77 zFlt{5-NFAH=zx)i!4N9+W!NLVW(X-3u$wp_0PRa-fc$=>VuljDtRLaR@INjcMq{M0 zl8eEVf2VUxYd@BzTl(|mN<=aLMDWA#BdkKggt(jVbaMDp-0}2S;n`yq3^gXAhVRkv zBtSh{jg?+R;gk=oA`1h{A3&&*ruZTaZCdf1q?<7FP}{3Lvf23m|nzq7aA5`)O&E zN3aqm!L>n0cn*4<)(%Ztr1|ZCU8h6V?6R6^A|m0-Sd7IRd7Jdk=hHhDqccRlf@7|v zBu01FBjU-V$-$}F9X#7ULY$#FVAwyU`Hv#aWX=9QcP0tUc_exU$o3e(C721`@)k)$d7!$?!~7->?A!IV3tDgFecDSD7JMPq3)cS}ojG9z`8yy?lR=BY zYX-kVbkRF@MlJzPGGpOnAA!X)YY>wPfpe=07pf8afgFOe*kov&@pEs4KRsDa{*>ka zcUg{4WO?Q=#y6s;_uO>}1IUv0`klC9lf+e+KA6RJm1ebTrcQw4z*pwPOD!PK)Y-aWA!gT{DIrHLLJ0A9FId0L zozeKA=~>ukh)97tOd_BTiZmbzrCPwQe9#08_|@twyIq3wk}jq6+I$I&)x1~=fl8vb z|16*1EF~EK?({S4Ji0O$Wp}xPf8CVx)Ks9%ruZVrp2~-;Fuwr83pDBl>Ob(@qJ-OV)0<9kPlVu@^@G5=6$L5dp7$B-|8&p5&zu3XY;r{ zhxZcLd_uNU&fCsYXEN62e;)PQDXIrM7_@>*&tfCnk-!IEzo1??~h|tg%i3SS6d86nPj}O)FmpT0?uE1UKVf?Vn zX*~Z9GF~tyLw$@7k!$DU!vM5ed~bX>N=h)rpI4Sf6-Zbc<#@rFS63!ycDA}8dFAD{edbaV7{I^LiP13wS~JXYn)M>~`6GsPf3 zOp3vL*c8M4-sDINev+2r9m23r)>4de6XTGUer3`qEpmA3cJxKS^_7i1b6fD4R z9N5CNsfr@^hz|q9f6NQ^IrCydOyj6n_wO4xX`MQJb$h_fr}4_#p=ow$Gr{~zTQ?cL z^RK%SfPVeBgThjPuD}6Ck57(%0t6l9a?-rA=>}85u(`@^+BFp?80|GB|EBznGq6>b zUgmaA5JA5HL8lsbn$U`dFGebfy*ImTjV5u&i`Bcb&D{nre~A{Bmrsvll<-0-<(4Q% z!>*75+SggN6kgMIS#6k1Gef}uf7ZF!Ut3$Oti0qznekBgN>%ZlCVu z4|nWZ#@jHzSSJP$T>IhlQKBeaGSlTq@zKF%fVOhOL@{Xel1s1oRmoXcf=}I}#-MTm zyCjRqjrlNNO1aL(P$Zpx`7W&+O!fxicsmA^jb*`fe|KZdu-pemcl}PFQ??buSd;}S zoWLFzP7uVQDi7&Z+Td+QLF9d5*J)cjTue=9Ap6ujcgslPQT^1NYGqodBopQB(qqLD zkKjpUB9CPcZg^*Te6~geAyA+Zz!imH)13{!W`!HtxpnfaZg{AhSkr~{2dR;v2G7p4 zsk9)bf53K{(^aJS`L>=b%*ytAyUBo_$UG7*xhF7oL$?=XD!dThH4ekBXDeCa#Ftu~ zuVfK^pn4EGG%_KUpvkVDg;t#21wFU*^=&nSr!{{;amGFosBQtBJJ1HK9g4mX-VZ4X zhSNnN3BV1S+<(uxNdS6UhFBFv(M24`=Qo%55yXiDKvp$J zGKo`>QyOFrIOcq9;P{@YkT3MUK^4v)89!X@w#;)@AN_+X>J3&}(6H{2mUY0f7)uTK ze;k(ld?wtE19Ig+UBexiF5ZT48n^Tu6y@#niW1)a3sNwNf(#W&4WsC@LHO8_goycQ zJRh3M2fGza@;;-;ON7c#WU>Gg1h;lJ@`8KPTJ(Vz2U`($gN%D3aH4RxqWriH} zYL2wZ503djJCA4ZWb*nERFC{15^qEGf9Tu;ijXmYBm~K^JBq>k> z8|_PcuTp}75CT=8zJ%1?kL&V)jv$w8YcEfWt2Vu|bIKU3x&*x1r9HkUKPo}@f43rC zJdCVxcwkD%ry>t0+gLY}@|?a1oV)!77-o|m8uIND=i4Qn2Zqa4>9%3548t}1mARWr zaScMJHyviu;{MP>agy>p?c*#Bi&jmxCN$ci(cPlZaA>&mCZnQuJvyJ8Sab~}6Br*Z zJ;0I9bA%=s9CpCD?j2WmUpns#f1@#>y)W8^$B(|Ob|lew1$k~c13PuTnjJ^Xf$ULY zPoPsI9R}#73{nF*a|dp34wbEIwwHnE0&e)?jvb(Px<9my?Eu_Nn8s`n$bObMMhBhu zp7IW!ary5zB^Tv0sa`1Cf?0-Y<(G?roj-u$Jxje{Q(BYO|Zm+UB2dCnCR7`eyhNE~$nH6sgM$cYIA4s9RAl|7;Wvte2xdP> z0r8hB%V8+>$f=j6;|4nQI&C110AezkROstKjD$a}Ai^Ty>%2;6~pf= z0tFXSW}P?sYnwIByPXjZ@N}zke?J#If&)Zwa{vDE9`KJ5M%#XoRTSMT*^y5w?=o+z zibw^XOP=kyC=%L}Xvnx|NKV8HakNF&@Zahn+w+)PK+aHGN}@LHM0+Ji*S~;zt$C{Z znCW@t#xOB9$k0DsYCeLR+hj*X9!&qk-iN@R%2GFaVTp3Z4dlQ z$`bqaxPNHf1ef~MUSZdu(bMXdyO$Z2k-BLd!7zAj2iu!rv0=s&69i!#dY7aILrq~a z{bFfd7_pS&KvQMcS(>{}$-kSDq3ROyFg^$T zf7ZPM-%1}-7EfJ9jZ(ldxhBxvXIHy{#G?1GKcsb6b&L>{7RsCKkh=iZxic(!y{s;@ z_Dui|KfaW84Nnx|2n2lb{{hXQTHBL=GA9EtIWm{wq5&y?T3c`AwiSN&ub4hnMl%fW z7o!`XDY9vTph&a(kYKZD+-g#TI?#fYiL+n+#R;7 zZkY42+?NkkSM6JJy;PPJulvPeHCB{uwOn2Mr+t>*u$ri(PDRp-GN2l(UizdcqyBIc89-LAG>P1Zn4|*Z35qB!nYsR zRQGk;lwJKkbmQ=LwR=QKd7iZ4#mj3eirpT6uD5MhZdVluTf(3+`3RQrtbP7c(y7WQ z@~Du-zu=HmtBeyy6^sl+R;8D(rp3DYnF_h}l2gtv<~yhA$t}kyC)$aAvX9yIC}GO> zL%JP*&b$fY?4>cT)f}=5X+snrCMk34C}OnkM|cC(y0|@bIC;6(!B1uiY@jJEfo2CzDx!4#Z#! zo#ibg-m=g0F!->oJ8YpR_*O{l@pmuChsUywb3b?$fyC;^ri!cWL1RtTi!0?p2nyjz z{01ics{7iz02+ehAU>HIf(H%4Fi(`35CuK^L&P_%XA83ZB;`VXiI0g6!aJlzbt(mO z<_K5vWNLKa945)Y{d&AuRr{`gthd-#eSF+kZ4czY^tS7eG+|sM&!fM(8wT`w0?a9z zVIq)~*Uk_G{vC}xT02CvvW;D>E$eZuk|T za*Iub_|TZ4KtF1S&mq}`1=dvz#ol51Wp91gr`ghwNA96ec&I#kQqtm84G=mX&LrW6 zoeKrV+0UM+k^-5yJyyWp;MQ{Mk zkopg|%U*6EAAoZp*hEff72xsrV}`(J@eq^aoF^YAw!lrB2kIbyZtc!FV@?a4O$IF? z9YEk%YGMSAVtIUO!1KXz`&698pqglH{tqPaVlHj~n`+&4+z%+d{JEBfXtQjcrmXL?knyax)fDywE zNB{J0%D}H7rf~^>C4r9Gn9=18D_`?!$RsDj#xjmc!@z9*7^FQ&4B^f6;VoZIP(#M_ zwLP+G7?Z5}UBBTH(nNM*zz=TV=a&dF-7Lwfv2wb(d65Mo$)GF_VNj_|>e9I-WS|a9 z8PtaKhf{>xvBrkT+8!}3`D6HM;Z;xi=n?F3YrBurMNW@V~#~|Wa~si zt(=*AlBWUZ*(r<%qY^nSA}p99`L{U{uvESiUwe0dQoeRtl2;dK&M=*5E`%xT5ru`C zH}o&hY7}HQ4zJGg6J*uHgVT{s6E>FKY3_>qBcWujFA4@Kk>Ew1lV*+{uU_am&qy>+ zt5ZRYohFx~QT=!fpCgQQH9)GPkYWr%BchtcAxqTn5{EoDrvs6YXj~IPJFe;kZMS`6C1LhAE|y zQ+)w0bUM#6cc5GS)B+N=5mNszY^Ph6OJ+2PS^)o+h(0U|!sE{64}RbBu-)QDsqq`` z<-=oBU9gY&UDf?D>@moqZXjQGVEtiZKoy&RT|B?@FLAp-rVtd~hi&38>=6(BKDGF| z3#UmiDsHc{ut^=JsUPD0qbweMJ+p^;2GtnXE90mA7R%&YaP+YCJ{;_!A%FGy>enk4 zTnlPHz7P-`1qgQaaP{UbU96%1Tks13c;iDD^#I|MLjdv4+ALmO{R7W*XD$h4l+d7m zPNs;2ERLQQ$yXqK^wQ9rl!YlZLesF$ZzT!xv;y-oI(QY#0rdxWj!4dv3VY`50KmsY zGNJRw8yucYyNtsV-{QG>J!l(4LqJPm+7cfx@bPDSbo)d6`DTevijOaHG{mVB8pLyG zxV?;qNa~;P!JbJ`0A;hIWA!Wz{B*H@2J~~d|M8#fP5JgR5lH?_uFZK$u!@S5Tsp6P z4u`88bDr(n$o3!NPg11p-jz)o=lIXluU;JaY82ZS*%-qdgJ5b;IkZ%aaHCU)&fXhg z+JWm!Wcja9EY<6{XRK^dHoI*VPU-t-44u`-YIT^v6+PcvpPbA5m_O*yV+k66cA{Wb z49+*XIThqze(vmKGNs?5%xM>D4=YX{U!y4cY4(xf>B%9y4kw2yT=ziYxA)C3x-UuL z<-^9Gl;Y8gk%Y?GS=2koeqldp3ZLsXN4}xct%_hHxibmwo6{3`DT}{V;etwLQYnZK z=R`Y!Wc^KnP+(v8=U&YL6S&`h2j1nDadf()N{=lg&ufq~enx}8H?{1@HI`8q@%oYo zIdX;*|BishA6I)^5&a9)V(imnsu^sS5W)u7_tP;l>_piXX8oqa*(diR{A(H4jF#%# znVmd6zeJ}7H)A5S)no!vArgIh#untB_Fuu(MOe%K+>?qdyqI*o-wab78= zJ`=WkY`EYN8u3IUG^a%Pj*$reb{NKOVq;&maW~1vo$$$zRe$$sa8(N+TT$f2zZrOC z>DT9EESV&HEKZNuG>qy;Ov%FQLR=6%yIC?TOLOajqm29GL*kq%*KcmI%A<2%Ujy=mfAD&aLWr!D2GrAA6Pi`@=&#IPwQy)6>RY6Mn_R zZCVnzctNI#$BD0d;b^FBg_vI{?DH4M&K37N#Pcn_Hub-TV>TD=EZtl$A-NP~hd2D9 z>B5f&A0IY&m=-QfHi0kvG!9FZkqyIwS|Z0QO%YLLG$I`2kYW2Ntc*0L&ITR5o%@4B z#S2K{N!1PV;F2iK!?hG^?F3B@g8+5>7lFJvwv$0WCImAyFg2Iqq5&v>%^KU1+qU)H zU!lHf+ZBQ%4v_tNqPJrpfxQ zsUPU+P*w##rE7V6vr*iCth@VyUe)l_&|{t*4kw$_VRN#M*v&>Owf?HeZ^Sz5Z#H7x zx_1LWgyJFIXDvM(o3d`o?ncJz5ANI>nXG@tAHUc^NG$|_Ulg}DZ(jZxDBlRhj82I{ zw@j~h#a-4PIvRL%^?O%StXg`?svSc79=XQ1X&2Cjqz(No5lJMb=4L>^+knj>kc1o z61~1%Iw6jk&`F5@_ALHU`f&uPfdF-u06h|bg4<}FFsTj6&(N!v_az*rfV{3L_xqyp zBNVGr926?AK~8pmau6{N%4)JwfTY`w_SAQNrgHC+=fFd)#>K_^yf}7c?SRaP$EhE< z(oNgl(rDYeV|O+12DH?zs_Je@E3@Mf1*EL(v<5PZ%0ki}1-0I0t$WJdleYWHqP?a0 zj0jg2Ju{%UAQPz)7Rx~y^Cg+2Ohto8mPHFBz;VNxrZ1L%07;3DGvUf8W-5)RYw6L9*4f{O7eBIU{|zxQ#y6T2_zKP-&@|iqscb+RJLy7zU~h@ zS{W)Z=v<`D`X%aLO-uJhM-LhO-Ix3O%>g!nD=C0mhb1LGmU-7Vh@(gdCE?t%7T|%J ztZEM#B7KVvDg`_pNwCaW4-MLp4j8?&>^)iDUER=&!9KgJv24S)f#*?!c09*3 zpMCxE*-y^|9L-k(<8Pz|i{n-P@a**)zS_Yw;030Utlrs04-jBLeFSbftiF5pH;UtP zd)6#}QV9U#EJ-zy^PS_1k!C~)2cAhM=%^?Hqc1|=*Nk%N_Fc{wFo{Dwpnr;(G^<#{m7X7tg3G7`f#GFIQc}S z^oYe*h}EU7;faejG?DgQUo8pRFFz}3$YM#jPnE4Rv*b#Gw*O~>zJ54%AHHrH^!?X= zDP?*E=6E)V<2EGaL?aeF*Myi?j{;i8UvU@IoPhkS;)ZIGKkg$!8UDuY zh5}-uOLy6!Ehd}8U7wxVHR|ML2eZfv@i;H?#aOT7go#973ar`)CgW%tSf}}PlGtn# zDn6zohtoeXdBa2`fqV!u5llUj1T?;X$;L|A)#tbdb4|!EA(d-sWssiH3d%?At9uW4 z$S4=J8Sqg9170mv0wydv*b#Xd48GBBtYzsuh*PxNoXrM@W}c|JF3h z=tJ^bJg`f5xD{bw?Pkphy$jX55>Nzx37mG`6zFwm z95|+C#b6vbb%r+_z(wK_{}9gw?_f&&GpV(<{Jg%>Q-nyZEA7O=?yA>$qv87}+z@ml}{A%YZ*R^vWA~g^prz2Klr$R@0a!5j4rNte_w71 zdE;#t9*$WDYVA&WgcZq-k)*Vsn#!TY^tw4N{SyQlLpE!jqd0Hzsg)m{TmbR~1Wj^mu0;R36(gGrnUN zQ6?NRpt38oL-`+!0WwaVg>!G8d|eei$oJrIP}6vnFdh#%*%xQJ_h!uesQrmxssDy2 z4k6a!v#)9!k8ohu!iwU3k@w!UaK9nX`gSp85oyF^Ae?1?4-v+@>v)* z#lAme4Go}(&7Fr4FblKaX-yBpa7?AS3 z?!D8bCNm{lc0k%vgWugA3cvl>yQO!ya+!OQ3l>Fxmv4QRN;HVGVB)DUlKLAQuWmHf zOb}+(z*kw?$@i!@E5(^g);dl@@`7ne^pzk3=U6K%U ze*kJgmA~wF`yjSZ$zb0!n6TLVv_d)8^bcI~i$`JdIL4sjih~j+#%sTSOb$5*K&7+m#WX16xC_8itYVhN+;IZV z*nnPxSFr2q8wHW4njAOj!)Q>eG+If#w!e7Ck%D?Be`e^!gb)N1k-bEf`XUI9ec(i@ z6A%W=JpIdHctRcrF{5Omr-b<6UAxrE`YBghp5DWct&zcbDoCjs{NiHQ`}-@fA9-ZSn(7`BFK}(=RL_;R`S{959CX$ z0M_q6!u>^zM^8mMR?0V_wihKAfqesC#|?pU>+uVcX=2(2+DcMwuVDX1L=#W}Y2gLCnrWb6lB>|Lex({1Ju#s= zOZgLZPeIO*g#1|4z3&_bI>10k7MqC)IOS&%Zie4)PCkG!HUSK_yuPTKSmg{!diDh9 zaWwGl%}2QM1Sm?LZZ(e?jR0nu%SHo2e}hbC+T@!xGJRwQF9Gbv?{t7CVZTz@8qI#D zJN7I;I%%=3!RTz#azdkoS^_XRc%To=L}etU%`fF9b9 z)UMEkc)Ss#rXphCrJI%2?Oa=vmU>*Xy#r*@$$#%??FfwKp53*m{?Le_&Eo`HqqwSj@7@C5|^6 zzHYPIGN*J=(KG-4vB}#OD}nNyGTWM-cUcqNeDnU#&@mRp(6t8pN3VbTBlJ<4u#X}U z5li8l?coQ;xciw#H69X|QEG%QUid*2AB&wI0`ziu^GO^f`lR_Uz7l+;BcquuWFjoR z;ZY(JDp=otNVa~eX1gj_#KkK33F&$TVMHXgUfMG)B^7Lsx0eVgRJscOcnf4p^!n+c z*xmqlJmBxEjpA_>L;D-}Ay$TpZtDt*95UntDb>2kZ-7IPO&)=@^g7=jijP<%FF#R< z!$XcQa@}t0N6UWszqFK7W5Fj^)5n`QS!Ydw+}2WmmgPe%*wq1r;z1#(Ue^a*doV)cUC?OM2VkV7gIl;iV~VsV*!KQ)jT`p~>kDSVanyY}@1B<=STOWtZP&cHx%?%GhS*_E;WUN#B`bCxhG=z za+rHKK9@LxM)W!1Gr^V=5EfS9V&!9tI|Kh7e zf?P0(NN{{?wE;n7q#MEe%{y2dITciFAQ_kf*1-{j%u1Zh`mZY_RvN|JcuM|uI7MfF zDo}DDj3btCU%~H}Rlo;B;LwHG*YLlii5Du6oC%CkTbZ6Z(!84_iimiuRzb05LJX_O z2tf)$Qz_oDH! zOOi}Y=AuQQ;qSqyzntw2vV5=OrJ7_eotP{7Gi>05&3-##qCTZZixwoP6=xHi0m3mA zdeEu;6-0t{%0N_HMI}B#CN)c@{S{<_deU@ArX}KMWK0gbdDdc^HQ4_B{hNP(yx~@h z!GAL1CRu?v261Ip+x?rbzhSE#eETzWLz;B;WJ~TrkAaTl$V=tw-JAa=cVIY10kf9G z0&HGjakE6epGsF{rlspLMQ)I*VG zxn8Cx7i4<+8D+Y@B-4k(dY(*wPtM5nWsCs!iU4+1L-T5E*qt!2z}KtzL8`#Hi`jD8 zozo2ZN;RJXpQYy|-C5feCGW8+PA%P_p~32uaY&rsT%l;M)jQW1H5MNjb%l@SDAvh9 zXxatg-;w|mn44-1)xIoI)XmFLWGQDvIhxeot-cEkK~zJR(s zbwYtJs9uJ5$DD`*49COd*dR)b7_(;2uHzQ^@^W@a>fDfCeTrfcuYY%i40ev>&_1=MiK3!Sd@Z!Qi42wzIKXTV}2o+;SOHg~h&ja)}8KAdRt3z3FYlE48b)Ge4kvGxJCeeKT z9zorjzW5e$O7;LarFZ$Z%o^&zguoKgM7?A7ZfX)>{&m_-=u?5zz?!qRb-PLhwC?(e zGty3DjOeB6OMVxBhTkO@`Ca-a=68+B9NX`Mkyrqq5N4w8v2`z*gQ^)g<_XeF!SZl> zeGhr*H~{fuV}Ox=?bgQq9yd2C3MTZp4vAD{>Ic=) z4d!wk~$1nUZXd?@Oequ*)<*~QjPp6yzCwYnRG)dwcnz1vBy+$VZGHuZgz z?I#y-g3!Ji$gUGLCZe<#ZxrcZDybIs2-tt9#m51?pNuQ4fr$iQyUv zYDHYKnN*KI1|}NTPOYSVQcVz5Gs)aiM1m(H$9rr%u%5TyI+j)-lR#V!SQ-|Q9oX); zwWC%nq4gE7tNe-52juZjkKOm@aXpF%C4Z2pJ&CJ-iL`<71m!_m@Eb188V%!wum4oJ zA)t$Jx+NZi6iYfv4tB&(Vgpn!PjJz_b>SkNH5P-TP-8}yP}Y) zAVB5rSov5Jrv>5bwr+sAY1nnOb73hI#WW0m{2IrpOwE~0RFs%_R-Ecc_7=Ylt4Y@H z{eb4BCr}OMlFK2RPcC|JV|sA%@Q|VRFZjAW01=TuLb#Y5$ei(WnT1P!^>fcEVvg=y zU&`VwK+?>S+pm?T$Q{*zEtiLkB^-=tb1q`+M5PQs?c2h#bBl}A2jF3!%B*$FP**vB z^~uK07VQIZKYY2hT9ZDyp*+;3tH5K{V^>x%)JW=7;E!zSh{*s_i+SW#yowl;XQCUK z@PL6Jg=pWXQ}~v-oQxiiWwy=XD@7&ZKQ%o&0fY%0cUcnLBRVulc)ce&`GW7Ae4!+Y zmqA$&FFvSFaWnJ|#F|t%#<5LkC=hXf7QA~b^UI4z+vta1>i)rVEa_#svAQ^{9<@5Z ze=s&xgKnUPOxgNB>w}+E61!j&+dyN;$+n;f5Z7^+lXx|P3nboO|mQK8Xog%Yf z_Uj97#vttF!S?W@vruhgzH!VuR^K7^m;2CavhqnWPsNV{*WtV>3L{nCX8zlaFzd70 z&ju~MUL5HQ0EzrZ4H``rZ4!y;xRT`g(Um6>4gJUG_Nd=ROI`t*<12!?CViiih=Bx6 zzu<@0WXDnGIf#{bruWO3HjYw%@DRfx{g{j^evOQ~92vI&0Y6=j=@gw8FGuksEyoL3 zIc~Ek$s!TY!pkBByTYWiA+4ySm0E$_7=aT1h3cAg*^*6v-L<-U$%@xep<}i?apcd& zNyX>lq)z$rkT2|8dO8^?;QBOyG~r+SXNDwAPXj{wD_{D=I<<5)T@}r(FRaw9Fgl0$g(z z4&|qjuW%NQ5H)`s4g+jeIyw$V$B3msf9yVo(KVDJKtKxbpFvie?cJNlL(Ew`1Y`(| zQ7pkjLO8@Vbi8d3#o_3G=2IBjRKz|~U(z*<>tj(LT{h06MH3}>p!P_r_10L2@?)WG z<|^~&rTgKLx2PFdWMXdT5P?)W%%|3fFnug`_Bf(wce0Fxq(@TJ{z%U&h7yP&Uj`l}{fCbIDhC0rF>^vqm28CO_<=};l zObrE;j^{Xq8SZ4exMp_*j07gn?xUX9+KjP@;t>d&Nclhd)P(X@z;I&b{7Vo=i(>j= z`7yMsoUxyem7Pz*OCu#zT@K9V_N-3u&$qLE0M_ac3oj$Bjq6kn#f398 zy5HpZ-Qp857;4cUp_muFDiVE2!mpzD7b1G~b)r|lzUWSRu3BNl%Knyf! zj3AEkJXA1><1!KNecwqzlSDk6lh=n4E`?*`9aae9Y_kJ`fJh<=TCl`AHuT~!7#lW& z=`ySCkJ-ITWo1ctldB-leB4X$uZx#MSVl(5MvMi2I(-x|$YXcP&EGhdQzE$J50iCe zZ)bzjb+ygyDY(?5OZId3n~h#@6*sws$z<9cy;JM9sP4;ir74?`Gme#UR6t1#z*W3rMs9WB3)(FMQISV}?825#K@p z%zcA@**oNouQ_Y#W3?L=wkRQHl=*#Ou{ItwrvFu{ccn_K4h|dKghi)8Dw} zZd1fO;ugF?F+l9_L%=PHdG?YP$82-|OFsf>#&95(7>0vjj=#9g9s{#ES&2t5K2aUp zx-9eUA>Tz)69m$s$?xjMa!um#-GtLUb`I!&<_-eqJx0zcz%SvhE6pdDyQc+GH;2p} zN~8SBRfNRBmvAXz+7rk1!wqVi*;qGQgR7~1sE_52-fx2i#l}|~?jK=xi8rK&upPOH zOuO9mpxWit_7i2^H`${rXnC*uL7LME9o)Z(iwOk%A6oyH3roTT@L}GRpDaCTV%^$* zvNPl_U$er^=Heuk$1F$OiwG)Cr)VQ)RPlYIlQZMVyNB3nv}+YFTL1<#P-v+EVlGc;a|pb zEOBs`bT4kM>axBEv0hScz}A?$qbFT|Hfh_Xa}>EthkY6aNc&dKMl%Xy{B4kuF(=9V zt_2>GqP2v1Mb#ENm)-q4;5IWj^K0d{^m3cAiRtl;6U$*6u4rBXv9=^54aT?X^{2jP zr*hAm4a-%r0+UgR^N9Wx5IyvRsYM9AOvEK8OGRmHJ`b3Y3~z>gE{<&QK+tD@!I6cC zL}IQ3e)LtF&p*2Wgfl+rh`N`Z(%5=fFM`mgU`Q`U=uL<#`TH1#RxY?HObrelhW7%4 z6%KMb&+Rb?e`TypZ4jyUN5$~Nx5wSRk8Y(LD>&i#LEu3QK?$p3uecCdib#s(-i=Zs z;_2w*8{#$-R}xctd_Q)u!|LOIW!u{A2>nZR>oeW<{42hHBi)_FT%T{;>}2Ky=%Zlz??M`}#k zb;F;K!2a*^=H3SwFk|7kp*3SUig_)~QaYX}neOjtzO#3JkmCXQ&hcP>okJ7;-Mc7| zm_IQj@Z4nI>+H-Smj0NYWpQjQjHtdQupzVFdw(f^yoe`Vks>MO$kNNl8++FvA+30fHXJ^4fqFY<^d+OY^(j)CYLk z*1jwD&0T43mc?pS?o8cc^>9ViyucP7Yg2Z2wMgfM{c*pmw!3PNl^)IOTfF}XUuYWf zTQ14f_iz6S9bKf12%eh`z14L@GB1C+68POi(*r2m-rzO04M9P*S#E#V)#la|7rWcT zy4>J*_qDB1n@2a>-LkwkW$zmz@s<1g)gv|lq`XRqM9#zie*wmG=`xPOf@D%QHOwe31Q9gzhf)i`1N4Nl zM!YD60+a}Ie^*!;QKp2=QJU=t>fzF_+S_tACq8*j2@QcpFEHa*x_&u`zuG7UfL(ovnW#s=Xn{ytv=m>z(ac zKs`5u4A=Vbe&LhCd{Ru&b*Xz$VFR^!v)Ejl8=OxyDgd6&|8b>Q)67G)TG@~6i{0Mb zw&L$nXE+v_k9Oc#O8~yWB2+U?we%PW^|W3vk2Oo+iqx7xU=0OOTGaJcH@2(_GxkvE ze}x!flx&uhTvC6j=OrbIr+Q4XMk&5s{IR@wb9ny--Yl^gxmzV^p8hU6vr;0`Rvp-Hz@*7Yo+U=R6PBtOCnDjd zQW9&2aw1cp*r|7_u{_cksC~((_nrw z$=!ba&`X3OnaC!w_J>2gALMSTNFr0049zafPnfW(nRbhT$-zKVI@L#!xJ2tR$SDa1 z!XvSoAnpD<1I?4MPE7iGB!MxZtMlqlZ(sfURjPkgFVYBgfF>zG`+2JxE-Iz)lOZ^iVBk@^GX z^hj-UG%SjwipDiZFh8U=b~x}#IVMDpdeRJ=x&3=YL@7zZjdb2d|Dkv6sM1Dbl<^be z>=l2VVz07iwO2B3uL5@A5s_1kh)czh4UuDQ2%kCC#|{2?BSKvo zt8qGy`sPDrc{gErax?*k)!70ZWuin7zOH}DeZNMdczcdJ|1=)>r>W869M@I(`~czW zXa%L0ELyGetA4!+Oy=Ub^k#B;QRlmaioRFenq5$h;VKt)0lfq4R$pEPSyGCGSQ6BFg>JCj$*oBYnB z`BhizYE|q^mHjrdT$?fwotD35p*DZMN*m<8a+2m=Dh2ekS^tJl70dmhSgjt-FQDRn zRqn{uLQp>cYHv!fadjDJwO!e4ZTU@E><>HJEnJP(OZ+&~GEV)Owk~(KP?7R%u9u{- z=f&QnQ3BBj);M6eyWsaXS7>W~)1NvLgj2V_RN~6LUIt$lhuV@6uEJ9;!`y!XR$En9 z>HJ5N%7`sY3s3=KL~zbXF7jblRuU=XC-2IJEC)s0dLqTnGFXcV-rVc_3Gx^7HdvxF z7kUud0r<7$x0{Hx`7sI-%!Q04JCg*{UhArk4vqvrH4n$;BV{Iz$KPimC{OU%7f!Wx zS?Fw4k~Ep5B-KezC~yQfLQ{XvNy@_TDwrgo_d3=ri;bDo(Da>7RJV!6#3Wkb)4Otc z*wvN$#7(Sy0YxdDSGJk1$#lMiDOBimT7o%5J+@mrwh4@p3dXkD*X0URd`wwI#d0r) zrXo2sb(HyoqOEPE+BXH*xrdEy#7U1WI4I$-w|m=`=6Hm)EK#I0vzLEOcXh^e|D^o~ z#V_<9x`{N^eURgwhddw3`GZfIx0b)Ml2cq?msS*w@Q!55g5`=Z;0p9@;mEfQ`9%@4^Yd%egi$w~z(az(Ej!uxy+#^ZQZj^!;m7%_>VCU}(&< zdP1&)N^pg9aehc3FImEh%<6WGtyO_>KwfU6s-7o)Xc})7>~?>`13(XW6eO7N|G3j) z1j@r0LTzG7TM}Teps2B1HImm!)+r}cr6iS4;)HOOdrn9IGXm1AoR!vwdLSXZHxmS& z9O`Ow`#KiLP{apFKax2KISB?aBWaep!3=jo4^BbglnCHO5x7m~Vek_(NaO6TW3U;J zHi=yFVKYq!{uh78HyS8lMsqAyMqTQW%4fmKd=sMv`;~{Qv%QOzQy@3~w{DmN?0BHsq11p(s_KOn--bsBtu>v)2V$!Q-gLy9ig_}9Q9p93YFMEA(W zGnng)2CNKHK>d2Qj8LRk9nU045Jmm5{dNLAr-)L6E^U8gDbHOfO}tgSbb@D>LG#pg zUxpzV>9IKpMii~d0L2K*VqyZ>;Z(#meuwNYf))JkR~D?C+0;pl*DQtM%ZAoXlh~5! z$ml}KY#OuA(w1a zFx=I=|1^J9{KhcZ)piW%`AIt)yZQ_sF$RX8p3V`TSREb@P7FrwNExAN;2$reeNh+{ zQJeBCwK7s`JR^=3pu@ z7oHo;l5XYzMr(z+bxDoSyO#+ z?4D{F;}~hF&fmB9S*{tsEWSL`;!6)~_uLEw8|6pwkH0ED9-YgCA~csiI`_-lqT0N^ zT5w6{dyUlPOj@Ka-f1KV-W2AtLO>hd;BgFiJ#6j^eKO3Cx|P)6JMf8VESs+}HC}%h z0FG_TZ}Ya?l)GY8{l^|}fn}Ke*Ppqwgt!M_oIXawJJJJ4Sgj5)a>PtmL2yVPCm#bn|v}cjf4k}4q z3<5mx5SR9hlCR63_mKluZc66}73bg==WB5|W9HhT-aPXNCZ*J463B7%;2pw}CjqO3 z->Wutb={nJ(+MmEf!*Hjiggq#3u4#-VZVue$Xl`{QD^|?pkBBLL4Fr-Q|N!~^Iq=| zA)VzQ71sxSAQS#*(X{%P!BxY}&0(`N`UHPbhl1&pi z+u1kUwWZdaj-|=38%va7@=N(B)1XtC2+@8};-dXB9|H?d(Z*N$h&q3GrrnFIIjRl{ zwAX@K82te2-lQ6{rT$5W_bn08jFtC z=4+tWmsMRNgC9+a;XZ%V`CSK%av9B zy9Vf)5~bmk?s;qWkTkINx-y!{4)`3?%S@*{Cmqglk`YoHY^SDUb)7TZxVMo7Nz=9w zAFQj!m9Fg>Z|oQw%p0fN>lX8&)2W-D`+byL7+uG2AwjorRM)5{f1poptbPnsjjn4gu=)g`I>6?m-WL?hvKw zpp`e#>+#kI&dh(Yi?*7MrA1f$y1Xe4t9@HrldZ~GVTm>42ZhDASW@d)6Mj2v&HP;t}Xt5$@6yG$+(@{IhdSm{MK!t zmv`|`akyPO$EYGfM&sh0k-sGA`sK$Vx=70=ZqoGSKIRqTE|;f>g&lFr9oPIsU<&bA zV_mH2vF?8fcBNWjS4{CubN=X|ZZ=MA%oCjEJMVDQ_Hy2c<=T`r{yUZ${~b%U?m$UtO)8cmjaa(fwVP9Re*NVZx4G|aeKVFg;GSsG zL9q*=vAAmbR2~zZ>@gt%)^%hvmdwA}*NwxJndpDqUyABR&V)(Y!G!C-50%~t3%BM- z0Bs5sIwnh7t~dI^)t#;O?ZUR^c|f#va<%$}LD4t2=23Ivf$zyM3f_4phCCTOcA=TQ zCU$Fl1-+Bmo1j>9v)isMrOk$|6x^ZA)55E℘9s7q1WGZBJNkXTt>KpCXK%9hV%t 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 z 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

If$?;gZhzf#{rY+M>409WEb3 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 diff --git a/doc/formalization/formalization.tex b/doc/formalization/formalization.tex index e058d6d2..64537cbc 100644 --- a/doc/formalization/formalization.tex +++ b/doc/formalization/formalization.tex @@ -504,48 +504,39 @@ picture of the translation, we first show what the previous simple program will to, using ML-like syntax for the target default calculus: \begin{Verbatim}[frame=lines,label=Simple default program, numbers=left, framesep=10pt, samepage=true] let X (a: unit -> int) (b: unit -> int) : (int * int) = - let a : unit -> int = < a | true :- fun () -> < true :- 0 >> in - let a : int = a () in - let b : unit -> int = < b | true :- fun () -> < true :- a + 1 >> in - let b : int = b () in + let a : int = < a () | < true :- 0 >> in + let b : int = < b () | < true :- a + 1 >> in (a, b) let Y (c: unit -> bool) : bool = - let X_1[a] : unit -> int = fun () -> < true :- 42 | > in + let X_1[a] : unit -> int = fun () -> < true :- 42 > in let X_1[b] : unit -> int = fun () -> EmptyError in let (X_1[a], X_1[b]) : int * int = X(X_1[a], X_1[b]) in - let c : unit -> bool = - < c | true :- fun () -> - < X_1[b] != 43 :- false | X_1[b] == 43 :- true > - > - in - let c : bool = c () in + let c : bool = < c () | < X_1[b] != 43 :- false | X_1[b] == 43 :- true >> in c \end{Verbatim} -% TODO: fix text below here We start unravelling this translation with the scope \Verb+X+. \Verb+X+ has been turned into a function whose arguments are all the local variables of the scope. However, the arguments have type \Verb+unit -> +. Indeed, we want the -arguments of \Verb+X+ (line 1 ) to be the default expression supplied by the caller of -\Verb+X+, which will later be merged with a higher priority (operator \Verb|++|) to the default -expression defining the local variables of \Verb+X+ (lines 2 and 4). But since defaults are not -values in our default calculus, we have to thunk them in the arguments of \Verb|X| -so that their evaluation is delayed. After the defaults have been merged, we apply -\Verb+()+ to the thunk (lines 3 and 5) to force evaluation and get back the value. -Finally, \Verb+X+ returns the tuple of all its local variables (line 6). +arguments of \Verb+X+ (line 1) to be the default expression supplied by the caller of +\Verb+X+, which are considered as exceptions to the base +expression defining the local variables of \Verb+X+ (lines 2 and 3). +After the merging of scope-local and +scope-arguments defaults, we apply +\Verb+()+ to the thunk to force evaluation and get back the value. +Finally, \Verb+X+ returns the tuple of all its local variables (line 4). The translation of \Verb+Y+ exhibits the pattern for sub-scope calls. -Lines 9 translates the assignment of the sub-scope argument \Verb+X_1[a]+. -Before calling \Verb+X_1+ (line 11), the other argument \Verb+X_1[b]+ is +Lines 7 translates the assignment of the sub-scope argument \Verb+X_1[a]+. +Before calling \Verb+X_1+ (line 8), the other argument \Verb+X_1[b]+ is initialized to the neutral \synemptydefault{} that will be ignored at execution because \Verb+X+ provides more defaults for \Verb+b+. The sub-scope call is translated to a regular -function call (line 11). The results of the call are then used in the two defaults -for \Verb+c+ (lines 13), which have been turned into a default tree taking into -account that no priority has been declared between the two defaults. - Finally, \Verb+c+ is evaluated (line 15). +function call (line 9). The results of the call are then used in the two defaults +for \Verb+c+ (line 10), which have been turned into a default tree taking into +account the possible input for \Verb+c+. \subsection{Formalization of the translation} \label{sec:scope:formalization} @@ -632,17 +623,21 @@ with the definitions of scope variables. \begin{mathpar} \inferrule[T-DefScopeVar]{ \synvar{a}\notin\redctx{\Delta}\\ - \redctx{\Delta}\typvdash\synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle\typcolon\synvar{\tau} + \redctx{\Delta}\typvdash + \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle\typcolon\synvar{\tau} }{ \synvar{P}\redsc\redctx{\Delta}\redturnstile{\synvar{S}} \synrule\synvar{a}\syntyped\synvar{\tau}\synequal - \synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle + \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle \reduces \\ - \synlet a\syntyped\synvar{\tau}\synequal \synlparen\synvar{a} \synmerge - \synlambda \synlparen \synunit\syntyped\synunitt\synrparen\syndot - \synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle - \synrparen\;\synunit\synin\synhole - \redproduce\synvar{a}\redcolon\synvar{\tau}\redcomma\redctx{\Delta} + \synlet a\syntyped\synvar{\tau}\synequal + \synlangle a\;\synunit\synmid + \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle + \synrangle\synin\synhole + \redproduce\synvar{a}\redcolon\synvar{\tau}\redcomma\redctx{\Delta} } \end{mathpar} @@ -665,26 +660,12 @@ which seeds the typing judgment of \sref{defaultcalc:typing} with \redctx{\Delta Since scope variables are also arguments of the scope, \TirName{T-DefScopeVar} redefines \synvar{a} by merging the new default tree with the default expression \synvar{a} of type \synunitt\synarrow\synvar{\tau} passed as an argument to \synvar{S}. -The merging operator,\synmerge, has the following definition : -\begin{align*} -\synlet \synlparen\synmerge\synrparen\;& -\synlparen\synvar{e_1}\syntyped\synunitt\synarrow\synvar{\tau}\synrparen\; - \synlparen\synvar{e_2}\syntyped\synunitt\synarrow\synvar{\tau}\synrparen\syntyped - \synunitt\synarrow\synvar{\tau} - \synequal\\ - &\synlangle\synlambda\synlparen\synunit\syntyped\synunitt\synrparen\syndot\syntrue\synjust - \synvar{e_1}\synmid\synvar{e_2}\synrangle -\end{align*} +This merging is done by defining the incoming argument as an exception to the +scope-local expression. This translation scheme ensures that the caller always +has priority over the callee. The evaluation of the incoming arguments is forced by applying \synunit, +yielding a value of type \synvar{\tau} for \synvar{a}. -\synmerge is asymetric in terms of priority: in \synvar{e_1}\synmerge\synvar{e_2}, -\synvar{e_1} will have the highest priority and it is only in the case where -none of the rules in \synvar{e_1} apply that \synvar{e_2} will be considered. -In \TirName{T-DefScopeVar}, the left-hand-side of \synmerge is coherent with -our objective of giving priority to the caller. - -Finally, the evaluation of the merged default tree is forced by applying \synunit, -yielding a value of type \synvar{\tau} for \synvar{a} which will be available -for use in the rest of the translated program. Now that we have presented the +ow that we have presented the translation scheme for rules defining scope variables, we can switch to the translation of sub-scope variables definitions and calls. We will start by the rules that define sub-scope variables, prior to calling the associated @@ -693,16 +674,19 @@ sub-scope. \inferrule[T-DefSubScopeVar]{ S\neq S'\\ \synvar{S'}_\synvar{n}\synlsquare\synvar{a}\synrsquare\notin\redctx{\Delta}\\ - \redctx{\Delta}\typvdash\synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle + \redctx{\Delta}\typvdash\synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle \typcolon\synvar{\tau} }{ \synvar{P}\redsc\redctx{\Delta}\redturnstile{\synvar{S}} \synrule\synvar{S'}_\synvar{n}\synlsquare\synvar{a}\synrsquare\syntyped\synvar{\tau}\synequal - \synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle + \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle \reduces \\ \synlet \synvar{S'}_\synvar{n}\synlsquare\synvar{a}\synrsquare\syntyped\synunitt\synarrow\synvar{\tau}\synequal \synlambda \synlparen\synunit\syntyped\synunitt\synrparen\syndot - \synlangle\synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synmid\synvar{e_1}\synellipsis\synvar{e_n}\synrangle + \synlangle\synvar{e_1}\synellipsis\synvar{e_n}\synmid + \synvar{e_\mathrm{just}}\synjust\synvar{e_\mathrm{cons}}\synrangle \synin\synhole\redproduce\\\synvar{S'}_\synvar{n}\synlsquare\synvar{a}\synrsquare\redcolon\synunitt\synarrow\synvar{\tau}\redcomma\redctx{\Delta} } \end{mathpar} From 606b148c74ec90051c892ed7a9e4335311f30f18 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 16:02:00 +0100 Subject: [PATCH 096/142] Lots of documentation --- CONTRIBUTING.md | 78 +++++------ INSTALL.md | 4 - Makefile | 4 +- README.md | 14 +- doc/formalization/README.md | 10 ++ examples/Makefile | 4 +- .../{Makefile.common => Makefile.common.mk} | 7 - examples/README.md | 122 ++++++++++++++++++ examples/allocations_familiales/Makefile | 2 +- examples/code_general_impots/Makefile | 2 +- examples/tutorial/Makefile | 2 +- examples/us_tax_code/Makefile | 2 +- src/dune | 1 + 13 files changed, 177 insertions(+), 75 deletions(-) create mode 100644 doc/formalization/README.md rename examples/{Makefile.common => Makefile.common.mk} (83%) create mode 100644 examples/README.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d949b201..d3c087d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,53 +14,21 @@ by contributing, you disclaim all copyright interests in favor of Inria. Both the code for the compiler and the examples in this repository are distributed under the Apache2 license. -## Writing Catala examples - -### Setting up the machinery - -This section describes what to do to setup a working directory for a new Catala example, as well as the development cycle. Let us suppose that you want to create a new example named `foo`. - -First, follow the instructions of [the installation readme](INSTALL.md) to get the compiler up and working up to `make build`. You can also set up the syntax highlighting for your editor. - -Then, create the directory `examples/foo`. In there, create a master source file `foo.catala` that will be the root of your Catala program. You can then start programming in `foo.catala`, or split up your example into multiple files. In the later case, `foo.catala` must only contain something like this: - -``` -@@Master file@@ - -@@Include: bar.catala@@ -``` - -where `examples/bar.catala` is another source file containing code for your example. Make sure you start by including some content in the source files, like - -``` -Hello, world! -``` - -Now let's build the example, create a `Makefile` with the following contents: - -```Makefile -CATALA_LANG=en # or fr if your source code is in French -SRC=foo.catala - -include ../Makefile.common -``` - -The `include` creates automatically all the targets you will need for your example. For instance, after making sure the compiler is built, you can launch - -``` -make -C examples/foo foo.tex -``` - -from the repository root to create the LaTeX weaving output of your source program. `Hello, world!` should appear in there. - -Finally, please add a rule for your example in the repository root `Makefile` in the section "Examples-related rules", following the pattern for other examples. This will ensure that -your example is built every time the compiler is modified; if a change in the compiler breaks your example, the authors will be notified and find a solution. - ### Writing Catala code -Let us now present the typical Catala workflow. First, you need to locate the legislative text that you want to use as a reference. Then, simply copy-paste the text into your source file. +Before writing Catala code, please read the +[tutorial](https://catala-lang.org/en/examples/tutorial). You can run the +programs of the tutorial yourself by following the instruction in the +[README of the `examples` directory](examples/README.md). Then, it is suggested +that you create a new example directory again according to the instructions of +this README. -First you will have to format the copy-pasted text using Catala headings and articles markers: +Let us now present the typical Catala workflow. First, you need to locate +the legislative text that you want to use as a reference. Then, simply +copy-paste the text into your source file. + +First you will have to format the copy-pasted text using Catala headings +and articles markers: ``` @@Heading@@ @@ -70,14 +38,18 @@ First you will have to format the copy-pasted text using Catala headings and art @Legislative atom@ ``` -Please look at the code of other examples to see how to format things properly. While formatting the text, don't forget regularly to try and parse your example using for instance +Please look at the code of other examples to see how to format things properly. +While formatting the text, don't forget regularly to try and parse your example +using for instance ``` make -C examples/foo foo.tex ``` -to see if you've made any syntax errors. Once the text formatting is done, you can start to annotate each legislative atom (article, provision, etc.) with some Catala code. To open up a code section in Catala, simply use +to see if you've made any syntax errors. Once the text formatting is done, you +can start to annotate each legislative atom (article, provision, etc.) with +some Catala code. To open up a code section in Catala, simply use ``` /* @@ -87,7 +59,9 @@ scope Foo: */ ``` -While all the code sections are equivalent in terms of execution, you can mark some as "metadata" so that they are printed differently on lawyer-facing documents. Here's how it works: +While all the code sections are equivalent in terms of execution, you can +mark some as "metadata" so that they are printed differently on lawyer-facing +documents. Here's how it works: ``` @@Begin metadata@@ # @@Début métadonnées@@ en français @@ -101,11 +75,17 @@ declaration structure FooBar: @@End metadata@@ # @@Fin métadonnées@@ en français ``` -Again, make sure to regularly check that your example is parsing correctly. The error message from the compiler should help you debug the syntax if need be. +Again, make sure to regularly check that your example is parsing correctly. The error message from the compiler should help you debug the syntax if need be. You can also +live-test the programs you wrote by feeding them to the interpreter +(see the [README of the `examples` directory](examples/README.md)); this will +also type-check the programs, which is useful for debugging them. ## Working on the compiler -The Catala compiler is a standard dune-managed OCaml project. You can look at the [online OCaml documentation](https://catala-lang.org/ocaml_docs/) for the different modules' interfaces. +The Catala compiler is a standard dune-managed OCaml project. +You can look at the +[online OCaml documentation](https://catala-lang.org/ocaml_docs/) for the +different modules' interfaces as well as high-level architecture documentation. ## Internationalization diff --git a/INSTALL.md b/INSTALL.md index 3afb6f51..bfc696ee 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -75,10 +75,6 @@ You will need the `man2html` executable to generate the HTML versions of the man pages, as well as the `rsync` executable to transfer files (preferred to `cp`) because it also works with a remote server. -## Usage - -Use `catala --help` to get more information about the command line options available. - ## Syntax highlighting The Catala language also comes with syntax highlighting to diff --git a/Makefile b/Makefile index 8aadc270..754a8e14 100644 --- a/Makefile +++ b/Makefile @@ -136,10 +136,10 @@ literate_examples: literate_allocations_familiales literate_code_general_impots .FORCE: test_suite: .FORCE - @$(MAKE) --no-print-directory -C tests + @$(MAKE) --no-print-directory -C tests pass_tests test_examples: .FORCE - @$(MAKE) --no-print-directory -C examples test_examples + @$(MAKE) --no-print-directory -C examples tests tests: test_suite test_examples diff --git a/README.md b/README.md index fe8333aa..ba8efc8c 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,15 @@ The Catala language is the only programming language to our knowledge that embeds default logic as a first-class feature, which is why it is the only language perfectly adapted to literate legislative programming. -## Installation +## Building and installation See [the dedicated readme](INSTALL.md). +## Usage + +Use `catala --help` to get more information about the command line +options available. + ## Examples See [the dedicated readme](examples/README.md). @@ -86,12 +91,7 @@ The library is released under the [Apache license (version 2)](LICENSE.txt). Catala is a research project from Inria, the French National Research Institute for Computer Science. The compiler is yet -unstable and lacks some of its features. Currently, here is the list -of existing features: - -* Literate programming output to HTML or LaTeX -* Typechecker and interpreter for most of the language - +unstable and lacks some of its features. ## Pierre Catala diff --git a/doc/formalization/README.md b/doc/formalization/README.md new file mode 100644 index 00000000..3310b203 --- /dev/null +++ b/doc/formalization/README.md @@ -0,0 +1,10 @@ +# The Catala formalization + +This folder contains the LaTeX sources of the document describing the +formalization the Catala programming language. To build the PDF output, +simply invoke: + + make formalization + +The directory also contains the F* sources of the proof of type soundness +of this formalization. \ No newline at end of file diff --git a/examples/Makefile b/examples/Makefile index 5ff13a4d..5ff1621a 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -18,7 +18,7 @@ > /dev/null || { echo "[FAIL $@]"; exit 1; } @echo "[PASS $@]" -TEST_FILES=$(wildcard */tests/*.catala*) +TEST_FILES?=$(wildcard */tests/*.catala*) TEST_FILES_SCOPES_EN=$(foreach TEST_FILE,$(TEST_FILES),\ $(foreach TEST_SCOPE,\ @@ -34,6 +34,6 @@ TEST_FILES_SCOPES_FR=$(foreach TEST_FILE,$(TEST_FILES),\ ) \ ) -test_examples: $(TEST_FILES_SCOPES_EN) $(TEST_FILES_SCOPES_FR) +tests: $(TEST_FILES_SCOPES_EN) $(TEST_FILES_SCOPES_FR) .FORCE: \ No newline at end of file diff --git a/examples/Makefile.common b/examples/Makefile.common.mk similarity index 83% rename from examples/Makefile.common rename to examples/Makefile.common.mk index 09001348..63385d4f 100644 --- a/examples/Makefile.common +++ b/examples/Makefile.common.mk @@ -12,10 +12,6 @@ CATALA=dune exec --no-print-director ../../src/catala.exe -- $(CATALA_OPTS) --la LEGIFRANCE_CATALA=dune exec ../../src/legifrance_catala.exe -- CATALA_EXE=../../_build/default/src/catala.exe -LEGIFRANCE_CATALA_EXE=../../_build/default/src/legifrance_catala.exe - -CLIENT_ID?=$(shell cat ../../legifrance_oauth_id.txt) -CLIENT_SECRET?=$(shell cat ../../legifrance_oauth_secret.txt) ifeq ($(CATALA_LANG),fr) PYGMENTIZE=$(PYGMENTIZE_FR) @@ -51,9 +47,6 @@ endif HTML \ $< -%.expired: %.catala_$(CATALA_LANG) $(CATALA_EXE) $(LEGIFRANCE_CATALA_EXE) - $(LEGIFRANCE_CATALA) $< $(CLIENT_ID) $(CLIENT_SECRET) - %.pdf: %.tex cd $(@D) && $(LATEXMK) -g -pdf -halt-on-error -shell-escape $(%F) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..884004df --- /dev/null +++ b/examples/README.md @@ -0,0 +1,122 @@ +# Catala examples + +This directory contains examples of Catala programs. It is highly recommended +to locate your own Catala programs in this directory, since programs in this +directory will receive first-class support during the alpha and beta stage +of the Catala programming language development. + +## List of examples + +* `allocations_familiales/`: computation of the French family benefits, based +on the _Code de la sécurité sociale_. This case study is the biggest and +most ambitious for Catala so far. +* `code_general_impots/`: computation of the French income tax, based on the +_Code général des impôts_. Currently, there are only stubs of program. +* `tutorial/`: Catala language tutorial for developers of tech-savvy lawyers. +The tutorial is written like a piece of legislation that gets annotated by +Catala snippets. +* `us_tax_code/`: contains the Catala formalization of several sections of the +US Tax Code. + +## Building and running examples + +Building and running examples is done via Makefiles. Each example directory +contains its own Makefile, which includes `Makefile.common.mk`. This common +Makefiles defines a list of targets that call the Catala compiler with the +right options. Each of these targers can be called from the root of the +repository with: + + make -C examples/ + +The `` can be replaced with the following (we assume an example +file `examples/foo/foo.catala_en`) list. + +* `foo.tex`: builds the LaTeX literate programming output from the Catala program +* `foo.pdf`: compiles `foo.tex` using `latexmk` +* `foo.html`: builds the HTML literate programming output from the Catala program +* `foo.run`: interprets the Catala program contained in `foo.catala_en`. Note +that you have to pass in the scope that you want to interpret via the `SCOPE` +Makefile variable (`SCOPE=FooScope make -C examples/foo foo.run`). + +When invoking any of these targets, additional options to the Catala compiler +can be passed using the `CATALA_OPTS` Makefile variable. + +## Testing examples + +Unit testing is important, and we encourage Catala developers to write lots +of tests for their programs. Again, the Makefile system provides a way to +collect tests into a regression test suite. + +In order to enjoy the benefits of this system, you have to create a `tests/` +directory in your examples directory, for instance `examples/foo/tests`. Then, +create a test file `foo_tests.catala_en` inside that directory. + +Inside `foo_tests.catala_en`, declare one ore more test scopes. It is assumed +that all these scopes should execute correctly. Include the program scope you +want to test and use assertions to provide the expected values of your test. +See existing tests in examples directory for more information. + +Once your tests are written, then will automatically be added to the regression +suite executed using + + make -C examples tests + +You can isolate a part of the regression suite by invoking: + + TEST_FILES=examples/tests/foo/foo_tests.catala_en make -C examples tests + +## Adding an example + +This section describes what to do to setup a working directory for a new Catala +example, as well as the development cycle. Let us suppose that you want to +create a new example named `foo`. + +First, follow the instructions of [the installation readme](../INSTALL.md) to +get the compiler up and working up to `make build`. You can also set up the +syntax highlighting for your editor. + +Then, create the directory `examples/foo`. In there, create a master source +file `foo.catala` that will be the root of your Catala program. +You can then start programming in `foo.catala`, or split up your example +into multiple files. In the later case, `foo.catala` must only contain +something like this: + +``` +@@Master file@@ + +@@Include: bar.catala@@ +``` + +where `examples/bar.catala` is another source file containing code for your +example. Make sure you start by including some content in the source files, +like + +``` +Hello, world! +``` + +To build and run the example, create a `Makefile` in `foo/` +with the following contents: + +```Makefile +CATALA_LANG=en # or fr if your source code is in French +SRC=foo.catala + +include ../Makefile.common.mk +``` + +The `include` creates automatically all the targets you will need for your example. For instance, after making sure the compiler is built, you can launch + +``` +make -C examples/foo foo.tex +``` + +from the repository root to create the LaTeX weaving output of your source +program. `Hello, world!` should appear in `examples/foo/foo.tex`. + +Finally, please add a rule for your example in the repository root +`Makefile` in the section "Examples-related rules", following the pattern +for other examples. This will ensure that your example is built every +time the compiler is modified; if a change in the compiler breaks your example, +the authors will be notified and find a solution. + diff --git a/examples/allocations_familiales/Makefile b/examples/allocations_familiales/Makefile index f342353e..1b5e0c16 100644 --- a/examples/allocations_familiales/Makefile +++ b/examples/allocations_familiales/Makefile @@ -1,4 +1,4 @@ CATALA_LANG=fr SRC=allocations_familiales.catala_fr -include ../Makefile.common +include ../Makefile.common.mk diff --git a/examples/code_general_impots/Makefile b/examples/code_general_impots/Makefile index 9697bde2..ccc7da6a 100644 --- a/examples/code_general_impots/Makefile +++ b/examples/code_general_impots/Makefile @@ -1,4 +1,4 @@ CATALA_LANG=fr SRC=code_general_impots.catala_fr -include ../Makefile.common +include ../Makefile.common.mk diff --git a/examples/tutorial/Makefile b/examples/tutorial/Makefile index 549ee89d..5bcab213 100644 --- a/examples/tutorial/Makefile +++ b/examples/tutorial/Makefile @@ -1,4 +1,4 @@ CATALA_LANG=en SRC=tutorial_en.catala_en -include ../Makefile.common +include ../Makefile.common.mk diff --git a/examples/us_tax_code/Makefile b/examples/us_tax_code/Makefile index bb149ed1..f71051a0 100644 --- a/examples/us_tax_code/Makefile +++ b/examples/us_tax_code/Makefile @@ -1,4 +1,4 @@ CATALA_LANG=en SRC=us_tax_code.catala_en -include ../Makefile.common +include ../Makefile.common.mk diff --git a/src/dune b/src/dune index 4769aef9..65b5a0fd 100644 --- a/src/dune +++ b/src/dune @@ -1,5 +1,6 @@ (executable (name catala) + (modes native js) (package catala) (modules catala) (public_name catala) From 73c19df068f2a958b9d8275a6179bcd0d7a0c125 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 16:06:01 +0100 Subject: [PATCH 097/142] Added the js_of_ocaml to the deps --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 754a8e14..9b29b303 100644 --- a/Makefile +++ b/Makefile @@ -24,6 +24,7 @@ install-dependencies-ocaml: bindlib \ zarith \ ocamlgraph \ + js_of_ocaml-compiler \ odate init-submodules: From 2068a6ffe414ab0f9601030a2c96ee85a2040700 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 16:15:42 +0100 Subject: [PATCH 098/142] Better test suite terminal output --- examples/Makefile | 16 +++++++++++++--- tests/Makefile | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/examples/Makefile b/examples/Makefile index 5ff1621a..28e12340 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,8 +1,18 @@ +BLACK := $(shell tput -Txterm setaf 0) +RED := $(shell tput -Txterm setaf 1) +GREEN := $(shell tput -Txterm setaf 2) +YELLOW := $(shell tput -Txterm setaf 3) +LIGHTPURPLE := $(shell tput -Txterm setaf 4) +PURPLE := $(shell tput -Txterm setaf 5) +BLUE := $(shell tput -Txterm setaf 6) +WHITE := $(shell tput -Txterm setaf 7) + +RESET := $(shell tput -Txterm sgr0) + ################################ # Running legislation unit tests ################################ - # Usage `make ..` # This Makefile rule assumes the following directory structure: # foo_example @@ -15,8 +25,8 @@ %.run: .FORCE @SCOPE="$(word 3,$(subst ., ,$*))" $(MAKE) --no-print-directory -C \ $(word 1,$(subst ., ,$*)) tests/$(word 2,$(subst ., ,$*)).run \ - > /dev/null || { echo "[FAIL $@]"; exit 1; } - @echo "[PASS $@]" + > /dev/null || { echo "[${RED}FAIL${RESET} ${PURPLE}$@${RESET}]"; exit 1; } + @echo "${GREEN}PASS${RESET} ${PURPLE}$@${RESET}" TEST_FILES?=$(wildcard */tests/*.catala*) diff --git a/tests/Makefile b/tests/Makefile index 2b58b826..ec89a840 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -2,6 +2,17 @@ # Preamble ############################################ +BLACK := $(shell tput -Txterm setaf 0) +RED := $(shell tput -Txterm setaf 1) +GREEN := $(shell tput -Txterm setaf 2) +YELLOW := $(shell tput -Txterm setaf 3) +LIGHTPURPLE := $(shell tput -Txterm setaf 4) +PURPLE := $(shell tput -Txterm setaf 5) +BLUE := $(shell tput -Txterm setaf 6) +WHITE := $(shell tput -Txterm setaf 7) + +RESET := $(shell tput -Txterm sgr0) + CATALA_OPTS?= CATALA=dune exec --no-buffer --no-print-director ../src/catala.exe -- Interpret $(CATALA_OPTS) @@ -23,8 +34,8 @@ reset_tests: $(subst .out,.in,$(wildcard */*.out)) # /.catala..out %.out: .FORCE @$(CATALA) --unstyled $(word 1,$(subst ., ,$*)).catala -s $(word 3,$(subst ., ,$*)) 2>&1 | \ - colordiff -u -b $@ - || { echo "[FAIL $*]"; exit 1; } - @echo "[PASS $*]" + colordiff -u -b $@ - || { echo "${RED}FAIL${RESET} ${PURPLE}$*${RESET}"; exit 1; } + @echo "${GREEN}PASS${RESET} ${PURPLE}$*${RESET}" # Usage: make /.catala..in # This rule runs the test /.catala, prints its output and From 03f34c7d933b42d41a13b3f6882ce971bcd0d19e Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 16:52:17 +0100 Subject: [PATCH 099/142] Fixed dependency --- catala.opam | 2 +- dune-project | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/catala.opam b/catala.opam index 5c92c447..e1204662 100644 --- a/catala.opam +++ b/catala.opam @@ -17,7 +17,7 @@ depends: [ "sedlex" {>= "2.1"} "menhir" {>= "20200211"} "menhirLib" {>= "20200211"} - "unionfind" {>= "20200320"} + "unionFind" {>= "20200320"} "bindlib" {>= "5.0.1"} "dune-build-info" {>= "2.0.1"} "cmdliner" {>= "1.0.4"} diff --git a/dune-project b/dune-project index 0536991d..9a9430c1 100644 --- a/dune-project +++ b/dune-project @@ -24,7 +24,7 @@ (sedlex (>= 2.1)) (menhir (>= 20200211)) (menhirLib (>= 20200211)) - (unionfind (>= 20200320)) + (unionFind (>= 20200320)) (bindlib (>= 5.0.1)) (dune-build-info (>= 2.0.1)) (cmdliner (>= 1.0.4)) From 293438ea38c7bc65a6b4b07a02af42732f8beaa2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 18:15:53 +0100 Subject: [PATCH 100/142] Missing JS stubs --- INSTALL.md | 2 +- Makefile | 10 +++++----- catala.opam | 1 + dune-project | 2 ++ src/catala/catala_surface/dune | 3 ++- src/catala/default_calculus/dune | 2 +- 6 files changed, 12 insertions(+), 8 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index bfc696ee..a45bddd6 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -18,7 +18,7 @@ the hint and enter `opam switch create 4.09.1`. Next, install all the OCaml packages that Catala depend on, as well as some git submodules, with - make install-dependencies + make dependencies This should ensure everything is set up for developping on the Catala compiler! diff --git a/Makefile b/Makefile index 9b29b303..e958b786 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ K := $(foreach exec,$(EXECUTABLES),\ $(if $(shell which $(exec)),some string,$(warning [WARNING] No "$(exec)" executable found. \ Please install this executable for everything to work smoothly))) -install-dependencies-ocaml: +dependencies-ocaml: opam install \ ocamlformat \ ANSITerminal \ @@ -22,7 +22,7 @@ install-dependencies-ocaml: obelisk \ unionfind \ bindlib \ - zarith \ + zarith zarith_stubs_js \ ocamlgraph \ js_of_ocaml-compiler \ odate @@ -30,7 +30,7 @@ install-dependencies-ocaml: init-submodules: git submodule update --init -install-dependencies: install-dependencies-ocaml init-submodules +dependencies: dependencies-ocaml init-submodules ########################################## @@ -161,7 +161,7 @@ website-assets: doc literate_examples grammar.html catala.html # Misceallenous ########################################## -all: install-dependencies build doc tests literate_examples website-assets +all: dependencies build doc tests literate_examples website-assets clean: dune clean @@ -177,5 +177,5 @@ inspect: # Special targets ########################################## .PHONY: inspect clean all literate_examples english allocations_familiales pygments \ - install build doc format install-dependencies install-dependencies-ocaml \ + install build doc format dependencies dependencies-ocaml \ catala.html diff --git a/catala.opam b/catala.opam index e1204662..c6ed412e 100644 --- a/catala.opam +++ b/catala.opam @@ -23,6 +23,7 @@ depends: [ "cmdliner" {>= "1.0.4"} "re" {>= "1.9.0"} "zarith" {>= "1.10"} + "zarith_stubs_js" {>= "0.14.0"} "dune" {build} "ocamlgraph" {>= "1.8.8"} "odate" {>= "0.6"} diff --git a/dune-project b/dune-project index 9a9430c1..66210e9d 100644 --- a/dune-project +++ b/dune-project @@ -1,4 +1,5 @@ (lang dune 2.2) + (name catala) (version 0.2.0) (generate_opam_files true) @@ -30,6 +31,7 @@ (cmdliner (>= 1.0.4)) (re (>= 1.9.0)) (zarith (>= 1.10)) + (zarith_stubs_js (>= 0.14.0)) (dune (and :build )) (ocamlgraph (>= 1.8.8)) (odate (>= 0.6)) diff --git a/src/catala/catala_surface/dune b/src/catala/catala_surface/dune index af62d0bd..cb1d342e 100644 --- a/src/catala/catala_surface/dune +++ b/src/catala/catala_surface/dune @@ -1,6 +1,7 @@ (library (name surface) - (libraries utils menhirLib sedlex re desugared scopelang zarith odate) + (libraries utils menhirLib sedlex re desugared scopelang zarith + zarith_stubs_js odate) (public_name catala.surface) (preprocess (pps sedlex.ppx))) diff --git a/src/catala/default_calculus/dune b/src/catala/default_calculus/dune index ff9f00da..97def089 100644 --- a/src/catala/default_calculus/dune +++ b/src/catala/default_calculus/dune @@ -1,7 +1,7 @@ (library (name dcalc) (public_name catala.dcalc) - (libraries bindlib unionFind utils zarith odate)) + (libraries bindlib unionFind utils zarith zarith_stubs_js odate)) (documentation (package catala)) From cc2c93f157e76c6aa8b03a228144715b5e3156a2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 18:18:57 +0100 Subject: [PATCH 101/142] Fixed github actions --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1a2f80a6..9c0db435 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -44,7 +44,7 @@ jobs: - name: Install dependencies run: | eval $(opam env) - make install-dependencies + make dependencies sudo apt update sudo apt install python3-dev python3-setuptools man2html rsync colordiff sudo python3 -m pip install --upgrade pip From dbfd990f9599c8e3d61e75cd1d716b659b6f2439 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 21 Dec 2020 18:26:01 +0100 Subject: [PATCH 102/142] Makefile tweaks --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index e958b786..eba1f55b 100644 --- a/Makefile +++ b/Makefile @@ -41,8 +41,8 @@ format: dune build @fmt --auto-promote | true build: - $(MAKE) -C src/catala/catala_surface parser_errors.ml - $(MAKE) format + @$(MAKE) --no-print-directory -C src/catala/catala_surface parser_errors.ml + @$(MAKE) --no-print-directory format dune build doc: @@ -171,7 +171,7 @@ clean: $(MAKE) -C $(CODE_GENERAL_IMPOTS_DIR) clean inspect: - gitinspector -f ml,mli,mly,iro,tex,catala,md,ir --grading + gitinspector -f ml,mli,mly,iro,tex,catala,catala_en,catala_fr,md,fst,mld --grading ########################################## # Special targets From 0cfab486d827199dfa912acaebec3669bb4d1b47 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 10:22:25 +0100 Subject: [PATCH 103/142] correct typo word teach --- examples/tutorial/tutorial_en.catala_en | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index ac88294f..356a8da1 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -1,7 +1,7 @@ @@The Catala language tutorial@@ Welcome to this tutorial, whose objective is to guide you through the features -of the Catala language and trach you how to annotate a legislative text using +of the Catala language and teach you how to annotate a legislative text using the language. This document is addressed primarily to developers or people that have a programming background, though tech-savvy lawyers will probably figure things out. From 31b7df38ae0eda253ebda351c494d146f629d7d0 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 11:43:26 +0100 Subject: [PATCH 104/142] correct typos in English tutorial --- examples/tutorial/tutorial_en.catala_en | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index ac88294f..fec882b2 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -72,7 +72,7 @@ declaration structure Individual: */ @@End metadata@@ -This structre contains two data fields, "income" and "age". Structures are +This structre contains two data fields, "income" and "number_of_children". Structures are useful to group together data that goes together. Usually, you get one structure per concrete object on which the law applies (like the individual). It is up to you to decide how to group the data together, @@ -110,7 +110,7 @@ programming. Scopes also have to be declared in metadata, so here we go: declaration scope IncomeTaxComputation: # Scope names use CamlCase context individual content Individual - # This line declares a context element of the scope, which is aking to + # This line declares a context element of the scope, which is akin to # a function parameter in computer science term. This is the piece of # data on which the scope will operate context fixed_percentage content decimal From d7ad0f2c20b184a1ae14da92100492b7275b199f Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 14:32:51 +0100 Subject: [PATCH 105/142] Reference to modified variable name --- examples/tutorial/tutorial_en.catala_en | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index fec882b2..7af667cb 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -239,7 +239,7 @@ income tax is 20% of the income. /* declaration scope NewIncomeTaxComputation: context two_brackets scope TwoBracketsTaxComputation - # This line says that we add the item two_brackets_for_rich to the context. + # This line says that we add the item two_brackets to the context. # However, the "scope" keyword tells that this item is not a piece of data # but rather a subscope that we can use to compute things. context individual content Individual From cda45a34b32a7c0ec171428f7792c1b3c59dc084 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 15:50:11 +0100 Subject: [PATCH 106/142] correct typos in conclusion --- examples/tutorial/tutorial_en.catala_en | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial/tutorial_en.catala_en index 7af667cb..374d88de 100644 --- a/examples/tutorial/tutorial_en.catala_en +++ b/examples/tutorial/tutorial_en.catala_en @@ -374,8 +374,8 @@ scope Test3: @@Conclusion@@+ -This tutorial present the basic concepts and syntax of the Catala language -features. It is then up to you tu use them to annotate legislative texts +This tutorial presents the basic concepts and syntax of the Catala language +features. It is then up to you use them to annotate legislative texts with their algorithmic translation. There is no single way to write Catala programs, as the program style should be From b2f34c33c60cf69060cd32c35a5301201830f0c6 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 22 Dec 2020 18:53:44 +0100 Subject: [PATCH 107/142] Fixed dependencies --- catala.opam | 4 ++-- dune-project | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/catala.opam b/catala.opam index c6ed412e..1b87454e 100644 --- a/catala.opam +++ b/catala.opam @@ -12,7 +12,7 @@ license: "Apache2" homepage: "https://github.com/CatalaLang/catala" bug-reports: "https://github.com/CatalaLang/catala/issues" depends: [ - "ocaml" {>= "4.07.0"} + "ocaml" {>= "4.08.0"} "ANSITerminal" {>= "0.8.2"} "sedlex" {>= "2.1"} "menhir" {>= "20200211"} @@ -24,7 +24,7 @@ depends: [ "re" {>= "1.9.0"} "zarith" {>= "1.10"} "zarith_stubs_js" {>= "0.14.0"} - "dune" {build} + "dune" {>= "2.2"} "ocamlgraph" {>= "1.8.8"} "odate" {>= "0.6"} ] diff --git a/dune-project b/dune-project index 66210e9d..f5180d38 100644 --- a/dune-project +++ b/dune-project @@ -20,7 +20,7 @@ "\| higher-level specification languages for fiscal legislation. ) (depends - (ocaml (>= 4.07.0)) + (ocaml (>= 4.08.0)) (ANSITerminal (>= 0.8.2)) (sedlex (>= 2.1)) (menhir (>= 20200211)) @@ -32,7 +32,7 @@ (re (>= 1.9.0)) (zarith (>= 1.10)) (zarith_stubs_js (>= 0.14.0)) - (dune (and :build )) + (dune (>= 2.2)) (ocamlgraph (>= 1.8.8)) (odate (>= 0.6)) ) From e0f8098853e4c66d9447df0d82fab231ff9ac1e3 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 09:38:42 +0100 Subject: [PATCH 108/142] init french translation + first paragraph --- examples/tutorial/tutorial_fr.catala_fr | 384 ++++++++++++++++++++++++ 1 file changed, 384 insertions(+) create mode 100644 examples/tutorial/tutorial_fr.catala_fr diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr new file mode 100644 index 00000000..e705292a --- /dev/null +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -0,0 +1,384 @@ +@@Tutoriel d'utilisation du langage Catala@@ + +Bienvenue dans ce tutoriel, son objectif est de vous accompagner dans les +fonctionnalités du langage Catala et de vous apprendre à annoter des textes +législatifs avec ce langage. Ce document s'adresse principalement à des développeurs +ou des personnes ayant déjà programmé, même si des juristes avec des appétences +en informatique devraient pouvoir s'en sortir. + +@@Literate programming@@+ + +To begin writing a Catala program, you must start from the text of the +legislative source that will justify the code that you will write. Concretely, +that means copy-pasting the text of the law into a Catala source file and +formatting it according so that Catala can understand it. Catala source files +have the ".catala_en" extension. If you were to write a Catala program for a +French law, you would use the ".catala_fr" extension. + +You can write any kind of plain text in Catala, and it will be printed as is +in PDF or HTML output. You can split your text into short lines, those +will appear as a single paragraph in the output. If you want to create a +new paragrah, you have to leave a blank line in the source. + +Catala allows you to declare section or subsection headers as it is done +here, with the "at" symbol repeated twice. You can define heading of lower +importance by adding increasing numbers of "+" after the title of the heading. + +The fundamental division unit is the article, introduced by a single "at". +Let's analyse a fictional example that defines an income tax. + +@Article 1@ +The income tax for an individual is defined as a fixed percentage of the +individual's income over a year. + +/* +# Welcome to the code mode of Catala. This is a comment, because the line is +# prefixed by #. +# We will soon learn what to write here in order to translate the meaning +# of the article into Catala code. +*/ + +To do that, we will intertwine short snippets of code between the sentences of +the legislative text. Each snippet of code should be as short as possible and +as close as possible to the actual sentence that justifies the code. This style +is called litterate programming, a programming paradigm invented by the famous +computer scientist Donald Knuth in the 70s. + +@@Defining a fictional income tax@@+ + +The content of article 1 uses a lot of implicit context: there exists an +individual with an income, as well as an income tax that the individual has +to pay each year. Even if this implicit context is not verbatim in the law, +we have to explicit it for programming purposes. Concretely, we need a +"metadata" section that defines the shape and types of the data used +inside the law. + +Let's start our metadata section by declaring the type information for the +individual: + +@@Begin metadata@@ +/* +declaration structure Individual: + # The name of the structure "Individual", must start with an + # uppercase letter: this is the CamlCase convention. + data income content money + # In this line, "income" is the name of the structure field and + # "money" is the type of what is stored in that field. + # Available types include: integer, decimal, money, date, duration, + # and any other structure or enumeration that you declare + data number_of_children content integer + # "income" and "number_of_children" start by a lowercase letter, + # they follow the snake_case convention +*/ +@@End metadata@@ + +This structre contains two data fields, "income" and "age". Structures are +useful to group together data that goes together. Usually, you +get one structure per concrete object on which the law applies (like the +individual). It is up to you to decide how to group the data together, +but you should aim to optimize code readability. + +Sometimes, the law gives an enumeration of different situations. These +enumerations are modeled in Catala using an enumeration type, like: +@@Begin metadata@@ +/* +declaration enumeration TaxCredit: +# The name "TaxCredit" is also written in CamlCase +-- NoTaxCredit +# This line says that "TaxCredit" can be a "NoTaxCredit" situation +-- ChildrenTaxCredit content integer +# This line says that alternatively, "TaxCredit" can be a +# "ChildrenTaxCredit" situation. This situation carries a content +# of type integer corresponding to the number of children concerned +# by the tax credit. This means that if you're in the "ChildrenTaxCredit" +# situation, you will also have access to this number of children +*/ +@@End metadata@@ + +In computer science terms, such an enumeration is called a "sum type" or simply +an enum. The combination of structures and enumerations allow the Catala +programmer to declare all possible shapes of data, as they are equivalent to +the powerful notion of "algebraic datatypes". + +We've defined and typed the data that the program will manipulate. Now we have +to define the logical context in which these data will evolve. This is done in +Catala using "scopes". Scopes are close to functions in terms of traditional +programming. Scopes also have to be declared in metadata, so here we go: + +@@Begin metadata@@ +/* +declaration scope IncomeTaxComputation: + # Scope names use CamlCase + context individual content Individual + # This line declares a context element of the scope, which is aking to + # a function parameter in computer science term. This is the piece of + # data on which the scope will operate + context fixed_percentage content decimal + context income_tax content money +*/ +@@End metadata@@ + +We now have everything to annotate the contents of article 1, which is copied +over below. + +@Article 1@ +The income tax for an individual is defined as a fixed percentage of the +individual's income over a year. +/* +scope IncomeTaxComputation: + definition income_tax equals + individual.income *$ fixed_percentage +*/ + +In the code, we are defining inside our scope the amount of the income tax +according to the formula described in the article. When defining formulaes, +you have access to all the usual arithmetic operators: addition "+", +substraction "-", multiplication "*" and division (slash). + +However, in the Catala code, you can see that we use "*$" to multiply the +individual income by the fixed percentage. The $ suffix indicates that we +are performing a multiplication on an amount of money. Indeed, in Catala, +you have to keep track of what you are dealing with: is it money ? Is it +an integer? Using just "+" or "*" can be ambiguous in terms of rounding, +since money is usually rounded at the cent. So to disambiguate, we suffix these +operations with something that indicates the type of what we manipulate. +The suffixes are "$" for money "." for decimals, "at" (like in email adresses) +for dates and the hat symbol for durations. If you forget the suffix, the Catala type +checker will display an error message that will help you put it where it +belongs. + +But inside article 1, one question remains unknown: what is the value of +of the fixed percentage? Often, precise values are defined elsewhere in the +legislative source. Here, let's suppose we have: + +@Article 2@ +The fixed percentage mentionned at article 1 is equal to 20 %. +/* +scope IncomeTaxComputation: + definition fixed_percentage equals 20 % + # Writing 20% is just an abbreviation for 0.20 +*/ + +You can see here that Catala allows definitions to be scattered throughout +the annotation of the legislative text, so that each +definition is as close as possible to its location in the text. + +@@Conditional definitions@@+ + +So far so good, but now the legislative text introduces some trickyness. Let us +suppose the third article says: + +@Article 3@ If the individual is in charge of 2 or more children, then the fixed +percentage mentionned at article 1 is equal to 15 %. +/* +# How to redefine fixed_percentage? +*/ + +This article actually gives another definition for the fixed percentage, which +was already defined in article 2. However, article 3 defines the percentage +conditionnally to the individual having more than 2 children. Catala allows +you precisely to redefine a variable under a condition: + +/* +scope IncomeTaxComputation: + definition fixed_percentage under condition + individual.number_of_children >= 2 + consequence equals 15 % + # Writing 15% is just an abbreviation for 0.15 +*/ + +When the Catala program will execute, the right definition will be dynamically +chosen by looking at which condition is true. A correctly drafted legislative +source should always ensure that at most one condition is true at all times. +However, if it is not the case, Catala will let you define a precedence on the +conditions, which has to be justified by the law. + + +@@Functions@@+ + +Catala lets you define functions anywhere in your data. Here's what it looks +like in the metadata definition when we want to define a two-brackets tax +computation: +@@Begin metadata@@ +/* +declaration structure TwoBrackets: + data breakpoint content money + data rate1 content decimal + data rate2 content decimal + +declaration scope TwoBracketsTaxComputation : + context brackets content TwoBrackets + context tax_formula content money depends on money +*/ +@@End metadata@@ + +And in the code: + +@Article4@ The tax amount for a two-brackets computation is equal to the amount +of income in each bracket multiplied by the rate of each bracket. + +/* +scope TwoBracketsTaxComputation : + definition tax_formula of income equals + if income <=$ brackets.breakpoint then + income *$ brackets.rate1 + else ( + brackets.breakpoint *$ brackets.rate1 +$ + (income -$ brackets.breakpoint) *$ brackets.rate2 + ) +*/ + +@@Scope inclusion@@+ + +Now that we've defined our helper scope for computing a two-brackets tax, we +want to use it in our main tax computation scope. + +@Article 5@ For individuals whose income is greater than $100,000, the income +tax of article 1 is 40% of the income above $100,000. Below $100,000, the +income tax is 20% of the income. +/* +declaration scope NewIncomeTaxComputation: + context two_brackets scope TwoBracketsTaxComputation + # This line says that we add the item two_brackets_for_rich to the context. + # However, the "scope" keyword tells that this item is not a piece of data + # but rather a subscope that we can use to compute things. + context individual content Individual + context income_tax content money + +scope NewIncomeTaxComputation : + definition two_brackets.brackets equals TwoBrackets { + -- breakpoint: $100,000 + -- rate1: 20% + -- rate2: 40% + } + definition income_tax equals two_brackets.tax_formula of individual.income +*/ + +@Article 6@ +Individuals earning less than $10,000 are exempted of the income tax mentionned +at article 1. +/* +scope NewIncomeTaxComputation: + definition income_tax under condition + individual.income <=$ $10,000 + consequence equals $0 +*/ + +That's it! We've defined a two-brackets tax computation simply by annotating +legislative article by snippets of Catala code. However, attentive readers +may have caught something weird in articles 5 and 6. What happens when the +income of the individual is between $10,000 and $100,000 ? + +The law leaves it unspecified ; our dummy articles are clearly badly drafted. +But Catala can help you find this sort of errors via simple testing or +even formal verification. Let's start with the testing. + +@@Testing Catala programs@@+ + +Testing Catala programs can be done directly into Catala. Indeed, writing test +cases for each Catala scope that you define is a good practice called +"unit testing" in the software engineering community. A test case is defined +as another scope: + +@Testing NewIncomeTaxComputation@ +/* +declaration scope Test1: + context tax_computation scope NewIncomeTaxComputation + +scope Test1: + definition + tax_computation.individual + # We define the argument to the subscope + equals + # The four lines below define a whole structure by giving a value to + # each of its fields + Individual { + -- income: $230,000 + -- number_of_children: 0 + } + + # Next, we retrieve the income tax value compute it by the subscope and + # assert that it is equal to the expected value : + # ($230,000-$100,00)*40%+$100,000*20% = $72,000 + assertion tax_computation.income_tax = $72,000 +*/ + +This test should pass. Let us now consider a failing test case: +/* +declaration scope Test2: + context tax_computation scope NewIncomeTaxComputation + +scope Test2: + definition tax_computation.individual equals Individual { + -- income: $4,000 + -- number_of_children: 0 + } + + assertion tax_computation.income_tax = $0 +*/ + +This test case should compute a $0 income tax because of Article 6. But instead, +execution will yield an error saying that there is a conflict between rules. + +@@Defining exceptions to rules@@+ + +Indeed, the definition of the income tax in article 6 conflicts with the +definition of income tax in article 5. But actually, article 6 is just an +exception of article 5. In the law, it is implicit that if article 6 is +applicable, then it takes precedence over article 5. + +@Fixing the computation@ + +This implicit precedence has to be explicitely declared in Catala. Here is a +fixed version of the NewIncomeTaxComputation scope: + +/* +declaration scope NewIncomeTaxComputationFixed: + context two_brackets scope TwoBracketsTaxComputation + context individual content Individual + context income_tax content money + +scope NewIncomeTaxComputationFixed : + definition two_brackets.brackets equals TwoBrackets { + -- breakpoint: $100,000 + -- rate1: 20% + -- rate2: 40% + } + + # To define an exception to a rule, you have to first label the rule that + # you want to attach to exception to. You can put any snake_case identifier + # for the label + label article_5 + definition income_tax equals two_brackets.tax_formula of individual.income + + # Then, you can declare the exception by referring back to the label + exception article_5 + definition income_tax under condition + individual.income <=$ $10,000 + consequence equals $0 +*/ + +And the test that should now work: + +/* +declaration scope Test3: + context tax_computation scope NewIncomeTaxComputationFixed + +scope Test3: + definition tax_computation.individual equals Individual { + -- income: $4,000 + -- number_of_children: 0 + } + assertion tax_computation.income_tax = $0 +*/ + +@@Conclusion@@+ + +This tutorial present the basic concepts and syntax of the Catala language +features. It is then up to you tu use them to annotate legislative texts +with their algorithmic translation. + +There is no single way to write Catala programs, as the program style should be +adapted to the legislation it annotates. However, Catala is a functional +language at heart, so following standard functional programming design patterns +should help achieve concise and readable code. \ No newline at end of file From 5b8a4fff9a853717a0a8718acc37921a180482b6 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 09:56:20 +0100 Subject: [PATCH 109/142] Litterate programming paragragh translation --- examples/tutorial/tutorial_fr.catala_fr | 35 ++++++++++++++----------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index e705292a..d4013477 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -6,26 +6,29 @@ législatifs avec ce langage. Ce document s'adresse principalement à des dével ou des personnes ayant déjà programmé, même si des juristes avec des appétences en informatique devraient pouvoir s'en sortir. -@@Literate programming@@+ +@@Programmation littéraire@@+ -To begin writing a Catala program, you must start from the text of the -legislative source that will justify the code that you will write. Concretely, -that means copy-pasting the text of the law into a Catala source file and -formatting it according so that Catala can understand it. Catala source files -have the ".catala_en" extension. If you were to write a Catala program for a -French law, you would use the ".catala_fr" extension. +Pour commencer à écrire un programme Catala, vous devez partir du texte +d'une source législative qui va justifier le code que vous écrirez. +Concrètement, cela signifie faire un copier-coller du texte de la loi dans +un fichier de source Catala et le formatter afin que Catala puisse le comprendre. +Les fichiers de source Catala ont l'extension ".catala_en" en version anglaise. +Si vous écriviez un programme Catala pour une loi française, vous devrez utiliser +l'extension ".catala_fr". -You can write any kind of plain text in Catala, and it will be printed as is -in PDF or HTML output. You can split your text into short lines, those -will appear as a single paragraph in the output. If you want to create a -new paragrah, you have to leave a blank line in the source. +Vous pouvez écrire n'importe quel texte simple en Catala, cela sera affiché +sans modification dans une sortie PDF ou HTML. Vous pouvez découper votre texte +en de courtes lignes, cela apparaîtera comme un seul paragraphe dans la sortie. +Si vous voulez créer un nouveau paragraphe laisser une ligne vierge dans la source. -Catala allows you to declare section or subsection headers as it is done -here, with the "at" symbol repeated twice. You can define heading of lower -importance by adding increasing numbers of "+" after the title of the heading. +Catala vous permet de déclarer des entêtes de section ou de sous-section, +comme c'est le cas ici, acec la répétition deux fois de l'arobase. Vous pouvez +diminuer l'importance du titre en augmentant le nombre de "+" après le titre de +l'entête. -The fundamental division unit is the article, introduced by a single "at". -Let's analyse a fictional example that defines an income tax. +L'unité de division fondamentale est l'article, commencé par un simple +arobase. +Étudions un exemple ficitif qui définit un impôt sur le revenu. @Article 1@ The income tax for an individual is defined as a fixed percentage of the From 2ad8dafc29b6fb6c665f3856af331dd3b1673c0f Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 10:20:06 +0100 Subject: [PATCH 110/142] Translation of article 1 paragraph --- examples/tutorial/tutorial_fr.catala_fr | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index d4013477..cb4453ec 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -31,21 +31,21 @@ arobase. Étudions un exemple ficitif qui définit un impôt sur le revenu. @Article 1@ -The income tax for an individual is defined as a fixed percentage of the -individual's income over a year. +L'impôt sur le revenu d'un individu est calculé en tant qu'un pourcentage +fixe des revenus d'une personne pour une année. /* -# Welcome to the code mode of Catala. This is a comment, because the line is -# prefixed by #. -# We will soon learn what to write here in order to translate the meaning -# of the article into Catala code. +# Bienvenue au code Catala. Ceci est un commentaire car la ligne débute par +# le caractère #. +# Nous allons bientôt apprendre ce que l'on doit écrire ici pour traduire +# le sens d'un article de loi en code Catala. */ -To do that, we will intertwine short snippets of code between the sentences of -the legislative text. Each snippet of code should be as short as possible and -as close as possible to the actual sentence that justifies the code. This style -is called litterate programming, a programming paradigm invented by the famous -computer scientist Donald Knuth in the 70s. +Afin de faire cela, nous allons mélanger de courts bouts de code entre des phrases +d'un texte législatif. Chaque bout de code devra être aussi court que possible +et aussi proche que possible de la phrase qui justifie le code. Ce style +s'appelle programmation littéraire, un paradigme de programmation inventé par le +célèbre informaticien Donald Knuth dans les années 70. @@Defining a fictional income tax@@+ From 97481795f06f98ec35c344957c8f4eb13541befc Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 11:41:29 +0100 Subject: [PATCH 111/142] Translate metadata explanation --- examples/tutorial/tutorial_fr.catala_fr | 123 ++++++++++++------------ 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index cb4453ec..aea261b0 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -47,82 +47,83 @@ et aussi proche que possible de la phrase qui justifie le code. Ce style s'appelle programmation littéraire, un paradigme de programmation inventé par le célèbre informaticien Donald Knuth dans les années 70. -@@Defining a fictional income tax@@+ +@@Définir un impôt sur le revenu fictif@@+ -The content of article 1 uses a lot of implicit context: there exists an -individual with an income, as well as an income tax that the individual has -to pay each year. Even if this implicit context is not verbatim in the law, -we have to explicit it for programming purposes. Concretely, we need a -"metadata" section that defines the shape and types of the data used -inside the law. +Le contenu de l'article 1 utilise beaucoup d'éléments du contexte implicite: +il existe une personne avec un revenu et en même temps un impôt sur le revenu, +qu'une personne doit acquitter chaque année. Même si ce contexte implicite n'est +pas inscrit en tant que tel dans la loi, nous devons l'expliciter pour le traduire +en code. Concrètement, nous avons besoin d'une section "métadonnées" qui définit +la forme et les types de données contenues dans la loi. -Let's start our metadata section by declaring the type information for the -individual: +Commençons notre section métadonnées en déclarant l'information sur le type +personne : -@@Begin metadata@@ +@@Début métadonnées@@ /* -declaration structure Individual: - # The name of the structure "Individual", must start with an - # uppercase letter: this is the CamlCase convention. - data income content money - # In this line, "income" is the name of the structure field and - # "money" is the type of what is stored in that field. - # Available types include: integer, decimal, money, date, duration, - # and any other structure or enumeration that you declare - data number_of_children content integer - # "income" and "number_of_children" start by a lowercase letter, - # they follow the snake_case convention +déclaration structure Personne: + # Le nom de la structure "Personne", doit commencer + # par une lettre majuscule: c'est la convention CamlCase. + donnée revenu contenu argent + # A cette ligne, revenu est le nom du champ de la structure et + # "argent" est le type de de données de ce champ. + # On peut utiliser d'autres types comme : entier, décimal, argent, date, durée + # ou tout autre structure ou énumération que vous déclarez + donnée nombre_enfants contenu entier + # "revenu" and "nombre_enfants" commençent par une lettre minuscule, + # ils adhèrent à la convention snake_case */ -@@End metadata@@ +@@Fin métadonnées@@ -This structre contains two data fields, "income" and "age". Structures are -useful to group together data that goes together. Usually, you -get one structure per concrete object on which the law applies (like the -individual). It is up to you to decide how to group the data together, -but you should aim to optimize code readability. +Cette structure contient deux champs de de données, "revenu" et "nombre_enfants". +Les structures sont utiles pour regrouper des données qui vont ensemble. +Typiquement, vous aurez une structure pour une entité concrète sur laquelle +s'applique la loi (comme une personne). C'est à vous de décider comment regrouper +les données mais vous devrez viser à optimiser la lisibilité du code. -Sometimes, the law gives an enumeration of different situations. These -enumerations are modeled in Catala using an enumeration type, like: -@@Begin metadata@@ +Parfois, la loi donne une énumération de différentes situations. Ces énumérations +sont modélisés en Catala par le type énumération, comme suit : +@@Début métadonnées@@ /* -declaration enumeration TaxCredit: -# The name "TaxCredit" is also written in CamlCase --- NoTaxCredit -# This line says that "TaxCredit" can be a "NoTaxCredit" situation --- ChildrenTaxCredit content integer -# This line says that alternatively, "TaxCredit" can be a -# "ChildrenTaxCredit" situation. This situation carries a content -# of type integer corresponding to the number of children concerned -# by the tax credit. This means that if you're in the "ChildrenTaxCredit" -# situation, you will also have access to this number of children +déclaration énumération CreditImpot: +# Le nom "CreditImpot" s'écrit aussi en CamlCase +-- AucunCreditImpot +# Cette ligne indique que "CreditImpot" peut être en situation "AucunCreditImpot" +-- CreditImpotEnfants contenu entier +# Cette ligne indique, de manière alternative, que "CreditImpot" peut aussi +# être une situation "CreditImpotEnfants". Cette situation porte un contenu +# de type entier qui correspond au nombre d'enfants concernés par le crédit +# d'impôt. Cela signifie que si vous êtes dans la situation "CreditImpotEnfants", +# vous aurez aussi accès à ce nombre d'enfants. */ -@@End metadata@@ +@@Fin métadonnées@@ -In computer science terms, such an enumeration is called a "sum type" or simply -an enum. The combination of structures and enumerations allow the Catala -programmer to declare all possible shapes of data, as they are equivalent to -the powerful notion of "algebraic datatypes". +En informatique, une telle énumération est appelée "type somme" ou simplement enum. +La combinaison de structures et d'énumération permet au programmeur Catala de déclarer +toutes les formes possibles de données, car elles sont équivalentes à la notion puissante +de "types de données algébriques". -We've defined and typed the data that the program will manipulate. Now we have -to define the logical context in which these data will evolve. This is done in -Catala using "scopes". Scopes are close to functions in terms of traditional -programming. Scopes also have to be declared in metadata, so here we go: +Nous avons défini et typé les données que le programme va manipuler. Maintenant, +nous devons définir un contexte logique dans lequel ces données vont évoluer. +On effectue cela par la notion de "champs d'application" en Catala. +Les champs d'application sont proches des fonctions en termes de programmation traditionnelle. +Les champs d'application doivent avoir été déclarées préalablement dans les métadonnées, ainsi: -@@Begin metadata@@ +@@Début métadonnées@@ /* -declaration scope IncomeTaxComputation: - # Scope names use CamlCase - context individual content Individual - # This line declares a context element of the scope, which is aking to - # a function parameter in computer science term. This is the piece of - # data on which the scope will operate - context fixed_percentage content decimal - context income_tax content money +déclaration champ d'application CalculImpotRevenu: + # Les champs d'application utilisent le CamlCase + contexte personne contenu Personne + # Cette ligne déclare un élémént de contexte du champ d'application, + # cela ressemble à un paramètre de fonction en informatique. C'est la + # donnée sur laquelle le champ d'application va intervenir + contexte pourcentage_fixe contenu décimal + contexte impot_revenu contenu décimal */ -@@End metadata@@ +@@Fin métadonnées@@ -We now have everything to annotate the contents of article 1, which is copied -over below. +Nous avons maintenant tout ce dont nous avons besoin pour annoter le contenu +de l'article 1 qui a été copié ci-dessous. @Article 1@ The income tax for an individual is defined as a fixed percentage of the From e5cecae952561ea66eff0e53f85c93d49ae14c77 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 13:44:40 +0100 Subject: [PATCH 112/142] articles 1,2 and 3 translation --- examples/tutorial/tutorial_fr.catala_fr | 105 ++++++++++++------------ 1 file changed, 54 insertions(+), 51 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index aea261b0..ae5b0855 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -126,77 +126,80 @@ Nous avons maintenant tout ce dont nous avons besoin pour annoter le contenu de l'article 1 qui a été copié ci-dessous. @Article 1@ -The income tax for an individual is defined as a fixed percentage of the -individual's income over a year. +L'impôt sur le revenu pour une personne est défini comme un pourcentage fixe +des revenus de la personne pour une année. /* -scope IncomeTaxComputation: - definition income_tax equals - individual.income *$ fixed_percentage +champ d'application IncomeTaxComputation: + définition impot_revenu égal à + personne.revenu *$ pourcentage_fixe */ -In the code, we are defining inside our scope the amount of the income tax -according to the formula described in the article. When defining formulaes, -you have access to all the usual arithmetic operators: addition "+", -substraction "-", multiplication "*" and division (slash). +Dans le code, nous définissons à l'intérieur de notre champ d'application +le montant d'impôt sur le revenu selon la formule décrit dans l'article. +Quand nous définissons des fomules, vous avez accès à tous les opérateurs +arithmétiques habituels : addition "+", soustraction "-", multiplication "*" +et division (slash). -However, in the Catala code, you can see that we use "*$" to multiply the -individual income by the fixed percentage. The $ suffix indicates that we -are performing a multiplication on an amount of money. Indeed, in Catala, -you have to keep track of what you are dealing with: is it money ? Is it -an integer? Using just "+" or "*" can be ambiguous in terms of rounding, -since money is usually rounded at the cent. So to disambiguate, we suffix these -operations with something that indicates the type of what we manipulate. -The suffixes are "$" for money "." for decimals, "at" (like in email adresses) -for dates and the hat symbol for durations. If you forget the suffix, the Catala type -checker will display an error message that will help you put it where it -belongs. +Toutefois, dans le code Catala, vous pouvez voir que nous utilisons "*$" +pour multiplier les revenus d'une personne par le pourcentage fixe. Le +suffixe $ inique que nous effectuons une multiplication sur une somme d'argent. +En effet, en Catala, vous devez rester conscient de la donnée manipulée : +est-ce de l'argent ? est-ce un entier ? Utiliser simple "+" ou "*" est ambigu +en termes d'arrondis car l'argent est habituellement arrondi au centime. +Ainsi, afin d'être clair, nous suffixons ces opérations avec quelque chose +qui indique le type de donnée manipulé. Les suffixes sont "$" pour de l'argent, +"." pour les décimales, arobase (comme dans les adresses mail) pour les dates et +le symbole chapeau pour les durées. Si vous oubliez le suffixe, le vérificateur +de type Catala va afficher une message d'erreur afin de vous aider à le placer +comme il le faut. -But inside article 1, one question remains unknown: what is the value of -of the fixed percentage? Often, precise values are defined elsewhere in the -legislative source. Here, let's suppose we have: +Mais dans l'article 1, une question reste sans réponse: quelle est la valeur +de la pourcentage fixe? Souvent, des valeurs précises sont définis ailleurs +dans les sources législatives. Ici, supposons que nous avons: @Article 2@ -The fixed percentage mentionned at article 1 is equal to 20 %. +Le pourcentage fixe mentionné à l'article 1 est égal à 20%. /* -scope IncomeTaxComputation: - definition fixed_percentage equals 20 % - # Writing 20% is just an abbreviation for 0.20 +champ d'application CalculImpotRevenu: + définition pourcentage_fixe égal à 20 % + # Ecrire 20% est juste une abbréviation pour 0.20 */ -You can see here that Catala allows definitions to be scattered throughout -the annotation of the legislative text, so that each -definition is as close as possible to its location in the text. +Vous pouvez voir ici que Catala permet des définitions réparties dans toute +l'annotation du texte législatif, afin que chaque définition soit le plus +proche possible de sa localisation dans le texte. -@@Conditional definitions@@+ +@@Définitions conditionnelles@@+ -So far so good, but now the legislative text introduces some trickyness. Let us -suppose the third article says: +Jusqu'à là tout va bien mais maintenant le texte législatif présente quelques +difficultés. Supposons que le troisième article dispose : -@Article 3@ If the individual is in charge of 2 or more children, then the fixed -percentage mentionned at article 1 is equal to 15 %. + +@Article 3@ Si l'individu a à sa charge deux ou plus enfants alors +le pourcentage fixe mentionné à l'article 1 vaut 15 %. /* -# How to redefine fixed_percentage? +# Comment redéfinir pourcentage_fixe ? */ -This article actually gives another definition for the fixed percentage, which -was already defined in article 2. However, article 3 defines the percentage -conditionnally to the individual having more than 2 children. Catala allows -you precisely to redefine a variable under a condition: +Cet article donne en réalité une autre définition pour le pourcentage fixe, +préalablement défini à l'article 2. Toutefois, si l'article 3 définit le pourcentage +de manière conditionnelle pour la personne ayant plus de deux enfants. +Catala permet de redéfinir précisément uen variable sous une condition : /* -scope IncomeTaxComputation: - definition fixed_percentage under condition - individual.number_of_children >= 2 - consequence equals 15 % - # Writing 15% is just an abbreviation for 0.15 +champ d'application CalculImpotRevenu: + définition pourcentage_fixe sous condition + personne.nombre_enfants >= 2 + conséquence égal à 15 % + # Ecrire 15% est juste une abbréviation pour 0.15 */ -When the Catala program will execute, the right definition will be dynamically -chosen by looking at which condition is true. A correctly drafted legislative -source should always ensure that at most one condition is true at all times. -However, if it is not the case, Catala will let you define a precedence on the -conditions, which has to be justified by the law. - +Quand le programme Catala va s'exécuter, la définition qui est juste sera choisi +dynamiquement en vérifiant quelle condition est vraie. Une source législative +rédigée correctement doit toujours garantir qu'au maximum une seule condition +soit vrai à tout moment. Toutefois si ce n'est pas le cas, Catala vous permettra +de définir un ordre des priorités sur les conditions, qui doit être justifié par +la loi. @@Functions@@+ From 87b3b45d12d62ae530e2564e4537cf19c8baf5de Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 14:10:09 +0100 Subject: [PATCH 113/142] Functions translation --- examples/tutorial/tutorial_fr.catala_fr | 48 +++++++++++++------------ 1 file changed, 25 insertions(+), 23 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index ae5b0855..890e783b 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -201,37 +201,39 @@ soit vrai à tout moment. Toutefois si ce n'est pas le cas, Catala vous permettr de définir un ordre des priorités sur les conditions, qui doit être justifié par la loi. -@@Functions@@+ +@@Fonctions@@+ -Catala lets you define functions anywhere in your data. Here's what it looks -like in the metadata definition when we want to define a two-brackets tax -computation: -@@Begin metadata@@ +Catala vous permet de définir des fonctions partout dans vos données. Voici +à quoi cela ressemble dans la définition des métadonnées quand nous voulons +définir un calcul de l'impôt sur le revenu à deux tranches : + +@@Début métadonnées@@ /* -declaration structure TwoBrackets: - data breakpoint content money - data rate1 content decimal - data rate2 content decimal +déclaration structure DeuxTranches: + donnée seuil contenu argent + donnée taux1 contenu décimal + donnée taux2 contenu décimal -declaration scope TwoBracketsTaxComputation : - context brackets content TwoBrackets - context tax_formula content money depends on money +déclaration champ d'application CalculImpotDeuxTranches : + contexte tranches contenu DeuxTranches + contexte formule_imposition contenu argent dépend de argent */ -@@End metadata@@ +@@Fin métadonnées@@ -And in the code: +Et dans le code : -@Article4@ The tax amount for a two-brackets computation is equal to the amount -of income in each bracket multiplied by the rate of each bracket. +@Article4@ Le montant d'impôt pour le calcul à deux tranches +est égal au montant d'impôt dans chaque tranche multiplié +par le taux de chaque branche. /* -scope TwoBracketsTaxComputation : - definition tax_formula of income equals - if income <=$ brackets.breakpoint then - income *$ brackets.rate1 - else ( - brackets.breakpoint *$ brackets.rate1 +$ - (income -$ brackets.breakpoint) *$ brackets.rate2 +champ d'application CalculImpotDeuxTranches : + définition formule_imposition de revenu égal à + si revenu <=$ tranches.seuil then + revenu *$ tranches.taux1 + sinon ( + tranches.seuil *$ tranches.taux1 +$ + (revenu -$ tranches.seuil) *$ tranches.taux2 ) */ From 222c3262f01a1948439ca6875e5091fce44d42df Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 14:27:49 +0100 Subject: [PATCH 114/142] Article 5 translation --- examples/tutorial/tutorial_fr.catala_fr | 34 +++++++++++++------------ 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index 890e783b..6b49cb6b 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -237,30 +237,32 @@ champ d'application CalculImpotDeuxTranches : ) */ -@@Scope inclusion@@+ +@@Inclusion de champ d'application@@+ -Now that we've defined our helper scope for computing a two-brackets tax, we -want to use it in our main tax computation scope. +Maintenant que nous avons défini notre champ d'application utilitaire pour +calculer un impôt à deux tranches, nous voulons l'utiliser dans notre champ +d'application principal de calcul de l'impôt. + +@Article 5@ Pour les individus dont le revenu est supérieur à $100 000, +l'impôt sur le revenu de l'article 1 est de 40% du revenu au-dessus de +$100 000. En dessous de $100 000, l'impôt sur le revenu est de 20% du revenu. -@Article 5@ For individuals whose income is greater than $100,000, the income -tax of article 1 is 40% of the income above $100,000. Below $100,000, the -income tax is 20% of the income. /* -declaration scope NewIncomeTaxComputation: - context two_brackets scope TwoBracketsTaxComputation +déclaration champ d'application NouveauCalculImpotRevenu: + contexte deux_tranches champ d'application CalculImpotDeuxTranches # This line says that we add the item two_brackets_for_rich to the context. # However, the "scope" keyword tells that this item is not a piece of data # but rather a subscope that we can use to compute things. - context individual content Individual - context income_tax content money + contexte personne contenu Personne + contexte impot_revenu contenu argent -scope NewIncomeTaxComputation : - definition two_brackets.brackets equals TwoBrackets { - -- breakpoint: $100,000 - -- rate1: 20% - -- rate2: 40% +champ d'application NouveauCalculImpotRevenu : + définition deux_tranches.tranches égal à DeuxTranches { + -- seuil: $100,000 + -- taux1: 20% + -- taux2: 40% } - definition income_tax equals two_brackets.tax_formula of individual.income + définition impot_revenu égal à deux_tranches.formule_imposition de personne.revenu */ @Article 6@ From 2eaa4dd2371da0f68ce9e98be3727d0a114b49fa Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 14:40:13 +0100 Subject: [PATCH 115/142] Translate article 5 comments --- examples/tutorial/tutorial_fr.catala_fr | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index 6b49cb6b..c5c2aa37 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -250,9 +250,10 @@ $100 000. En dessous de $100 000, l'impôt sur le revenu est de 20% du revenu. /* déclaration champ d'application NouveauCalculImpotRevenu: contexte deux_tranches champ d'application CalculImpotDeuxTranches - # This line says that we add the item two_brackets_for_rich to the context. - # However, the "scope" keyword tells that this item is not a piece of data - # but rather a subscope that we can use to compute things. + # Cette ligne indique que nous ajoutons l'élément deux_tranches au contexte. + # Toutefois, les mots clé "champ d'application" indique que l'élément n'est + # pas une donnée mais plutôt un sous-champ d'application qui peut être utiliser + # pour calculer des choses. contexte personne contenu Personne contexte impot_revenu contenu argent From 9e160fdc064d60f2023b4a42f4385ad8687873ef Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 14:49:56 +0100 Subject: [PATCH 116/142] article 6 --- examples/tutorial/tutorial_fr.catala_fr | 27 +++++++++++++------------ 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index c5c2aa37..4ed3c2a8 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -267,23 +267,24 @@ champ d'application NouveauCalculImpotRevenu : */ @Article 6@ -Individuals earning less than $10,000 are exempted of the income tax mentionned -at article 1. +Les personnes ayant moins de $10 000 de revenus sont exemptés de l'impôt sur le revenu +prévu à l'article 1. /* -scope NewIncomeTaxComputation: - definition income_tax under condition - individual.income <=$ $10,000 - consequence equals $0 +champ d'application NouveauCalculImpotRevenu: + définition impot_revenu sous condition + personne.revenu <=$ $10,000 + conséquence égal à $0 */ -That's it! We've defined a two-brackets tax computation simply by annotating -legislative article by snippets of Catala code. However, attentive readers -may have caught something weird in articles 5 and 6. What happens when the -income of the individual is between $10,000 and $100,000 ? +Et voilà ! Nous avons défini un calcul d'impôt à deux tranches en annotant +tout simplement un texte législatif par des bouts de code Catala. +Cependant, les lecteurs attentifs auront vu quelque chose de curieux dans les +articles 5 et 6. Que se passe-t-il si le revenu d'une personne se situe entre +$10 000 et $100 000 ? -The law leaves it unspecified ; our dummy articles are clearly badly drafted. -But Catala can help you find this sort of errors via simple testing or -even formal verification. Let's start with the testing. +La loi ne le précise pas; nos articles sont clairement mal rédigés. +Mais Catala vous aide à trouver ce genre d'erreur par de simples tests ou +même la vérification formelle. Commençons par les tests. @@Testing Catala programs@@+ From c2e40f88c13516d6d100a694e3b9dd4a73e02a33 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Tue, 22 Dec 2020 15:48:28 +0100 Subject: [PATCH 117/142] Translate end of document --- examples/tutorial/tutorial_fr.catala_fr | 152 ++++++++++++------------ 1 file changed, 79 insertions(+), 73 deletions(-) diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutorial/tutorial_fr.catala_fr index 4ed3c2a8..7963d4f8 100644 --- a/examples/tutorial/tutorial_fr.catala_fr +++ b/examples/tutorial/tutorial_fr.catala_fr @@ -286,112 +286,118 @@ La loi ne le précise pas; nos articles sont clairement mal rédigés. Mais Catala vous aide à trouver ce genre d'erreur par de simples tests ou même la vérification formelle. Commençons par les tests. -@@Testing Catala programs@@+ +@@Tester les programmes Catala@@+ -Testing Catala programs can be done directly into Catala. Indeed, writing test -cases for each Catala scope that you define is a good practice called -"unit testing" in the software engineering community. A test case is defined -as another scope: +Tester les programmes Catala peut se faire directement en Catala. En effet, +écrire des cas de tests pour chaque champ d'application Catala que vous +définissez est une bonne pratique appelée "tests unitaires" dans la +communauté du génie logicielle. Un cas de test est défini dans un autre +champ d'application : -@Testing NewIncomeTaxComputation@ +@Tester NouveauCalculImpotRevenu@ /* -declaration scope Test1: - context tax_computation scope NewIncomeTaxComputation +déclaration champ d'application Test1: + contexte calcul_impot champ d'application NouveauCalculImpotRevenu -scope Test1: - definition - tax_computation.individual - # We define the argument to the subscope - equals - # The four lines below define a whole structure by giving a value to - # each of its fields - Individual { - -- income: $230,000 - -- number_of_children: 0 +champ d'application Test1: + définition + calcul_impot.personne + # L'on définit le paramètre au sous-champ d'application + égal à + # Les quatre lignes ci-dessous définissent une structure entière + # en valorisant chacun des champs + Personne { + -- revenu: $230,000 + -- nombre_enfants: 0 } - - # Next, we retrieve the income tax value compute it by the subscope and - # assert that it is equal to the expected value : + + # Ensuite, nous récupérons le montant d'impôt, calculé par + # sous-champ d'application et nous assertons qu'il vaut bien + # la valeur attendue : # ($230,000-$100,00)*40%+$100,000*20% = $72,000 - assertion tax_computation.income_tax = $72,000 + + assertion calcul_impot.impot_revenu = $72,000 */ -This test should pass. Let us now consider a failing test case: +Ce test devrait être bon. Maintenant étudions un test en échec : /* -declaration scope Test2: - context tax_computation scope NewIncomeTaxComputation +déclaration champ d'application Test2: + contexte calcul_impot champ d'application NouveauCalculImpotRevenu -scope Test2: - definition tax_computation.individual equals Individual { - -- income: $4,000 - -- number_of_children: 0 +champ d'application Test2: + définition calcul_impot.personne égal à Personne { + -- revenu: $4,000 + -- nombre_enfants: 0 } - assertion tax_computation.income_tax = $0 + assertion calcul_impot.revenu = $0 */ -This test case should compute a $0 income tax because of Article 6. But instead, -execution will yield an error saying that there is a conflict between rules. +Ce cas de test devrait calculer un impôt sur le revenu de $0, +en raison de l'article 6. Mais au lieu de cela, l'exécution produira +une erreur car il y a un conflit entre les règles. -@@Defining exceptions to rules@@+ +@@Définir des exceptions à des règles@@+ -Indeed, the definition of the income tax in article 6 conflicts with the -definition of income tax in article 5. But actually, article 6 is just an -exception of article 5. In the law, it is implicit that if article 6 is -applicable, then it takes precedence over article 5. +En effet, la définition d'un impôt sur le revenu à l'article 6 entre en +conflit avec la définition de l'article 5. Mais en réalité, l'article 6 +est une simple exception à l'article 5. Dans la loi, il est implicite que +si l'article 6 est applicable, alors son application est prioritaire +sur l'article 5. -@Fixing the computation@ +@Régler correctement le calcul@ -This implicit precedence has to be explicitely declared in Catala. Here is a -fixed version of the NewIncomeTaxComputation scope: +Cette priorité implicite doit être explicitement déclaré en Catala. Voici une +version correcte du champ d'application NouveauCalculImpotRevenu : /* -declaration scope NewIncomeTaxComputationFixed: - context two_brackets scope TwoBracketsTaxComputation - context individual content Individual - context income_tax content money +déclaration champ d'application NouveauCalculImpotRevenuCorrect: + contexte deux_tranches champ d'application CalculImpotDeuxTranches + contexte personne contenu Personne + contexte impot_revenu contenu argent -scope NewIncomeTaxComputationFixed : - definition two_brackets.brackets equals TwoBrackets { - -- breakpoint: $100,000 - -- rate1: 20% - -- rate2: 40% +champ d'application NouveauCalculImpotRevenuCorrect : + définition deux_tranches.tranches égal à DeuxTranches { + -- seuil: $100,000 + -- taux1: 20% + -- taux2: 40% } - # To define an exception to a rule, you have to first label the rule that - # you want to attach to exception to. You can put any snake_case identifier - # for the label - label article_5 - definition income_tax equals two_brackets.tax_formula of individual.income - # Then, you can declare the exception by referring back to the label + # Pour définir une exception à une règle, vous devez d'abord étiquetter + # la règle à laquelle vous voulez attacher l'exception. Vous pouvez mettre + # n'importe quel identifiant en snake_case pour l'étiquette. + étiquette article_5 + définition impot_revenu égal à deux_tranches.formule_imposition de personne.revenu + + # Puis, vous pouvez déclarez l'exception par référence à l'étiquette exception article_5 - definition income_tax under condition - individual.income <=$ $10,000 - consequence equals $0 + définition impot_revenu sous condition + personne.revenu <=$ $10,000 + conséquence égal à $0 */ -And the test that should now work: +Le test devrait désormais fonctionner : /* -declaration scope Test3: - context tax_computation scope NewIncomeTaxComputationFixed +déclaration champ d'application Test3: + contexte calcul_impot champ d'application NouveauCalculImpotRevenuCorrect -scope Test3: - definition tax_computation.individual equals Individual { - -- income: $4,000 - -- number_of_children: 0 +champ d'application Test3: + définition calcul_impot.personne égal à Personne { + -- revenu: $4,000 + -- nombre_enfants: 0 } - assertion tax_computation.income_tax = $0 + assertion calcul_impot.impot_revenu = $0 */ @@Conclusion@@+ -This tutorial present the basic concepts and syntax of the Catala language -features. It is then up to you tu use them to annotate legislative texts -with their algorithmic translation. +Ce tutoriel présente les concepts de base et la syntaxe des fonctionnalités +du langage Catala. C'est à vous de les utiliser pour annoter du texte +législatif avec leur traduction algorithmique. -There is no single way to write Catala programs, as the program style should be -adapted to the legislation it annotates. However, Catala is a functional -language at heart, so following standard functional programming design patterns -should help achieve concise and readable code. \ No newline at end of file +Il n'y pas une seule bonne façon d'écrire des programmes Catala car le style de +programmation doit être adapté au texte de loi annoté. Cependant, Catala est un +langage fonctionnel au fond, alors suivre les patrons de conception fonctionnels +devrait aider à obtenir du code concis et lisible. \ No newline at end of file From 34094be3634849696fab2d39b8155f4510436e15 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Wed, 23 Dec 2020 11:39:23 +0100 Subject: [PATCH 118/142] create seperate folders for English and French tutorials --- examples/{tutorial => tutorial_en}/.gitignore | 0 examples/{tutorial => tutorial_en}/Makefile | 0 .../tests/test_tutorial.catala_en | 0 .../{tutorial => tutorial_en}/tutorial_en.catala_en | 0 examples/tutoriel_fr/.gitignore | 13 +++++++++++++ examples/tutoriel_fr/Makefile | 4 ++++ .../{tutorial => tutoriel_fr}/tutorial_fr.catala_fr | 0 7 files changed, 17 insertions(+) rename examples/{tutorial => tutorial_en}/.gitignore (100%) rename examples/{tutorial => tutorial_en}/Makefile (100%) rename examples/{tutorial => tutorial_en}/tests/test_tutorial.catala_en (100%) rename examples/{tutorial => tutorial_en}/tutorial_en.catala_en (100%) create mode 100644 examples/tutoriel_fr/.gitignore create mode 100644 examples/tutoriel_fr/Makefile rename examples/{tutorial => tutoriel_fr}/tutorial_fr.catala_fr (100%) diff --git a/examples/tutorial/.gitignore b/examples/tutorial_en/.gitignore similarity index 100% rename from examples/tutorial/.gitignore rename to examples/tutorial_en/.gitignore diff --git a/examples/tutorial/Makefile b/examples/tutorial_en/Makefile similarity index 100% rename from examples/tutorial/Makefile rename to examples/tutorial_en/Makefile diff --git a/examples/tutorial/tests/test_tutorial.catala_en b/examples/tutorial_en/tests/test_tutorial.catala_en similarity index 100% rename from examples/tutorial/tests/test_tutorial.catala_en rename to examples/tutorial_en/tests/test_tutorial.catala_en diff --git a/examples/tutorial/tutorial_en.catala_en b/examples/tutorial_en/tutorial_en.catala_en similarity index 100% rename from examples/tutorial/tutorial_en.catala_en rename to examples/tutorial_en/tutorial_en.catala_en diff --git a/examples/tutoriel_fr/.gitignore b/examples/tutoriel_fr/.gitignore new file mode 100644 index 00000000..cbfb2606 --- /dev/null +++ b/examples/tutoriel_fr/.gitignore @@ -0,0 +1,13 @@ +*.aux +*.dvi +*.fdb_latexmk +*.fls +*.log +*.out +*.fls +*.tex +*.pdf +_minted* +*.toc +*.pyg +*.d diff --git a/examples/tutoriel_fr/Makefile b/examples/tutoriel_fr/Makefile new file mode 100644 index 00000000..785fb75a --- /dev/null +++ b/examples/tutoriel_fr/Makefile @@ -0,0 +1,4 @@ +CATALA_LANG=fr +SRC=tutorial_fr.catala_fr + +include ../Makefile.common.mk diff --git a/examples/tutorial/tutorial_fr.catala_fr b/examples/tutoriel_fr/tutorial_fr.catala_fr similarity index 100% rename from examples/tutorial/tutorial_fr.catala_fr rename to examples/tutoriel_fr/tutorial_fr.catala_fr From f0cfe89d2b74ea7e76cdf6ac70c6a04751a10508 Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Thu, 24 Dec 2020 11:11:24 +0100 Subject: [PATCH 119/142] =?UTF-8?q?Use=20French=20number=20notation=20and?= =?UTF-8?q?=20=E2=82=AC=20symbol=20for=20monetary=20ops?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/tutoriel_fr/tutorial_fr.catala_fr | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/examples/tutoriel_fr/tutorial_fr.catala_fr b/examples/tutoriel_fr/tutorial_fr.catala_fr index 7963d4f8..09ec3f8e 100644 --- a/examples/tutoriel_fr/tutorial_fr.catala_fr +++ b/examples/tutoriel_fr/tutorial_fr.catala_fr @@ -131,7 +131,7 @@ des revenus de la personne pour une année. /* champ d'application IncomeTaxComputation: définition impot_revenu égal à - personne.revenu *$ pourcentage_fixe + personne.revenu *€ pourcentage_fixe */ Dans le code, nous définissons à l'intérieur de notre champ d'application @@ -140,14 +140,14 @@ Quand nous définissons des fomules, vous avez accès à tous les opérateurs arithmétiques habituels : addition "+", soustraction "-", multiplication "*" et division (slash). -Toutefois, dans le code Catala, vous pouvez voir que nous utilisons "*$" +Toutefois, dans le code Catala, vous pouvez voir que nous utilisons "*€" pour multiplier les revenus d'une personne par le pourcentage fixe. Le -suffixe $ inique que nous effectuons une multiplication sur une somme d'argent. +suffixe € inique que nous effectuons une multiplication sur une somme d'argent. En effet, en Catala, vous devez rester conscient de la donnée manipulée : est-ce de l'argent ? est-ce un entier ? Utiliser simple "+" ou "*" est ambigu en termes d'arrondis car l'argent est habituellement arrondi au centime. Ainsi, afin d'être clair, nous suffixons ces opérations avec quelque chose -qui indique le type de donnée manipulé. Les suffixes sont "$" pour de l'argent, +qui indique le type de donnée manipulé. Les suffixes sont "€" pour de l'argent, "." pour les décimales, arobase (comme dans les adresses mail) pour les dates et le symbole chapeau pour les durées. Si vous oubliez le suffixe, le vérificateur de type Catala va afficher une message d'erreur afin de vous aider à le placer @@ -229,11 +229,11 @@ par le taux de chaque branche. /* champ d'application CalculImpotDeuxTranches : définition formule_imposition de revenu égal à - si revenu <=$ tranches.seuil then - revenu *$ tranches.taux1 + si revenu <=€ tranches.seuil alors + revenu *€ tranches.taux1 sinon ( - tranches.seuil *$ tranches.taux1 +$ - (revenu -$ tranches.seuil) *$ tranches.taux2 + tranches.seuil *€ tranches.taux1 +€ + (revenu -€ tranches.seuil) *€ tranches.taux2 ) */ @@ -243,9 +243,9 @@ Maintenant que nous avons défini notre champ d'application utilitaire pour calculer un impôt à deux tranches, nous voulons l'utiliser dans notre champ d'application principal de calcul de l'impôt. -@Article 5@ Pour les individus dont le revenu est supérieur à $100 000, +@Article 5@ Pour les individus dont le revenu est supérieur à 100 000€, l'impôt sur le revenu de l'article 1 est de 40% du revenu au-dessus de -$100 000. En dessous de $100 000, l'impôt sur le revenu est de 20% du revenu. +100 000€. En dessous de 100 000€, l'impôt sur le revenu est de 20% du revenu. /* déclaration champ d'application NouveauCalculImpotRevenu: @@ -259,7 +259,7 @@ déclaration champ d'application NouveauCalculImpotRevenu: champ d'application NouveauCalculImpotRevenu : définition deux_tranches.tranches égal à DeuxTranches { - -- seuil: $100,000 + -- seuil: 100 000€ -- taux1: 20% -- taux2: 40% } @@ -267,20 +267,20 @@ champ d'application NouveauCalculImpotRevenu : */ @Article 6@ -Les personnes ayant moins de $10 000 de revenus sont exemptés de l'impôt sur le revenu +Les personnes ayant moins de 10 000€ de revenus sont exemptés de l'impôt sur le revenu prévu à l'article 1. /* champ d'application NouveauCalculImpotRevenu: définition impot_revenu sous condition - personne.revenu <=$ $10,000 - conséquence égal à $0 + personne.revenu <=€ 10 000€ + conséquence égal à 0€ */ Et voilà ! Nous avons défini un calcul d'impôt à deux tranches en annotant tout simplement un texte législatif par des bouts de code Catala. Cependant, les lecteurs attentifs auront vu quelque chose de curieux dans les articles 5 et 6. Que se passe-t-il si le revenu d'une personne se situe entre -$10 000 et $100 000 ? +10 000€ et 100 000€ ? La loi ne le précise pas; nos articles sont clairement mal rédigés. Mais Catala vous aide à trouver ce genre d'erreur par de simples tests ou @@ -307,16 +307,16 @@ champ d'application Test1: # Les quatre lignes ci-dessous définissent une structure entière # en valorisant chacun des champs Personne { - -- revenu: $230,000 + -- revenu: 230 000€ -- nombre_enfants: 0 } # Ensuite, nous récupérons le montant d'impôt, calculé par # sous-champ d'application et nous assertons qu'il vaut bien # la valeur attendue : - # ($230,000-$100,00)*40%+$100,000*20% = $72,000 + # (230 000€ - 100 000€) * 40% + 100 000€ * 20% = 72 000€ - assertion calcul_impot.impot_revenu = $72,000 + assertion calcul_impot.impot_revenu = 72 000€ */ Ce test devrait être bon. Maintenant étudions un test en échec : @@ -326,14 +326,14 @@ déclaration champ d'application Test2: champ d'application Test2: définition calcul_impot.personne égal à Personne { - -- revenu: $4,000 + -- revenu: 4 000€ -- nombre_enfants: 0 } - assertion calcul_impot.revenu = $0 + assertion calcul_impot.revenu = 0€ */ -Ce cas de test devrait calculer un impôt sur le revenu de $0, +Ce cas de test devrait calculer un impôt sur le revenu de 0€, en raison de l'article 6. Mais au lieu de cela, l'exécution produira une erreur car il y a un conflit entre les règles. @@ -358,7 +358,7 @@ déclaration champ d'application NouveauCalculImpotRevenuCorrect: champ d'application NouveauCalculImpotRevenuCorrect : définition deux_tranches.tranches égal à DeuxTranches { - -- seuil: $100,000 + -- seuil: 100 000€ -- taux1: 20% -- taux2: 40% } @@ -373,8 +373,8 @@ champ d'application NouveauCalculImpotRevenuCorrect : # Puis, vous pouvez déclarez l'exception par référence à l'étiquette exception article_5 définition impot_revenu sous condition - personne.revenu <=$ $10,000 - conséquence égal à $0 + personne.revenu <=€ 10 000€ + conséquence égal à 0€ */ Le test devrait désormais fonctionner : @@ -385,10 +385,10 @@ déclaration champ d'application Test3: champ d'application Test3: définition calcul_impot.personne égal à Personne { - -- revenu: $4,000 + -- revenu: 4 000€ -- nombre_enfants: 0 } - assertion calcul_impot.impot_revenu = $0 + assertion calcul_impot.impot_revenu = 0€ */ @@Conclusion@@+ From f7bd47c38dc8dd4841e25b8ea80c642565f0e24d Mon Sep 17 00:00:00 2001 From: James Barnes <> Date: Thu, 24 Dec 2020 11:37:11 +0100 Subject: [PATCH 120/142] Adapt general makefile for dual language tutorials --- Makefile | 14 ++++++++++---- ...tutorial_fr.catala_fr => tutoriel_fr.catala_fr} | 0 2 files changed, 10 insertions(+), 4 deletions(-) rename examples/tutoriel_fr/{tutorial_fr.catala_fr => tutoriel_fr.catala_fr} (100%) diff --git a/Makefile b/Makefile index eba1f55b..11483110 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,9 @@ EXAMPLES_DIR=examples ALLOCATIONS_FAMILIALES_DIR=$(EXAMPLES_DIR)/allocations_familiales CODE_GENERAL_IMPOTS_DIR=$(EXAMPLES_DIR)/code_general_impots US_TAX_CODE_DIR=$(EXAMPLES_DIR)/us_tax_code -TUTORIAL_DIR=$(EXAMPLES_DIR)/tutorial +TUTORIAL_EN_DIR=$(EXAMPLES_DIR)/tutorial_en +TUTORIEL_FR_DIR=$(EXAMPLES_DIR)/tutoriel_fr + literate_allocations_familiales: pygments build $(MAKE) -C $(ALLOCATIONS_FAMILIALES_DIR) allocations_familiales.tex @@ -124,11 +126,15 @@ literate_us_tax_code: pygments build $(MAKE) -C $(US_TAX_CODE_DIR) us_tax_code.html literate_tutorial_en: pygments build - $(MAKE) -C $(TUTORIAL_DIR) tutorial_en.tex - $(MAKE) -C $(TUTORIAL_DIR) tutorial_en.html + $(MAKE) -C $(TUTORIAL_EN_DIR) tutorial_en.tex + $(MAKE) -C $(TUTORIAL_EN_DIR) tutorial_en.html + +literate_tutoriel_fr: pygments build + $(MAKE) -C $(TUTORIEL_FR_DIR) tutoriel_fr.tex + $(MAKE) -C $(TUTORIEL_FR_DIR) tutoriel_fr.html literate_examples: literate_allocations_familiales literate_code_general_impots \ - literate_us_tax_code literate_tutorial_en + literate_us_tax_code literate_tutorial_en literate_tutoriel_fr ########################################## # Execute test suite diff --git a/examples/tutoriel_fr/tutorial_fr.catala_fr b/examples/tutoriel_fr/tutoriel_fr.catala_fr similarity index 100% rename from examples/tutoriel_fr/tutorial_fr.catala_fr rename to examples/tutoriel_fr/tutoriel_fr.catala_fr From 3e12e85b61742345281fbfda3ea0c408694721c4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 24 Dec 2020 11:41:29 +0100 Subject: [PATCH 121/142] Copy JS version of executable to website --- generate_website_assets.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_website_assets.sh b/generate_website_assets.sh index 0a27a06a..a483f2d9 100755 --- a/generate_website_assets.sh +++ b/generate_website_assets.sh @@ -15,4 +15,4 @@ scp examples/us_tax_code/us_tax_code.html $1/ scp examples/tutorial/tutorial_en.html $1/ scp grammar.html $1/ scp catala.html $1/ -scp legifrance_catala.html $1/ +scp _build/default/src/catala.bc.js $1/playground/ \ No newline at end of file From ae0cb80a25923b4b25d342a0fd00f898299073dc Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 24 Dec 2020 16:09:40 +0100 Subject: [PATCH 122/142] Various fixes for French tutorial --- examples/Makefile | 2 +- .../tutoriel_fr/tests/test_tutoriel.catala_fr | 29 ++++ examples/tutoriel_fr/tutoriel_fr.catala_fr | 150 +++++++++--------- generate_website_assets.sh | 3 +- .../fr/atom/grammars/catala_fr.cson | 10 +- syntax_highlighting/fr/catala_fr.iro | 4 +- syntax_highlighting/fr/pygments/catala_fr.py | 8 +- .../fr/vscode/syntaxes/catalavs.xml | 11 +- 8 files changed, 125 insertions(+), 92 deletions(-) create mode 100644 examples/tutoriel_fr/tests/test_tutoriel.catala_fr diff --git a/examples/Makefile b/examples/Makefile index 28e12340..3dd08560 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -39,7 +39,7 @@ TEST_FILES_SCOPES_EN=$(foreach TEST_FILE,$(TEST_FILES),\ TEST_FILES_SCOPES_FR=$(foreach TEST_FILE,$(TEST_FILES),\ $(foreach TEST_SCOPE,\ - $(shell grep -Po "déclaration champ d'application [^:]*" $(TEST_FILE) | cut -d " " -f 3), \ + $(shell grep -Po "déclaration champ d'application [^:]*" $(TEST_FILE) | cut -d " " -f 4), \ $(word 1,$(subst /, ,$(TEST_FILE))).$(word 1,$(subst ., ,$(word 3,$(subst /, ,$(TEST_FILE))))).$(TEST_SCOPE).run \ ) \ ) diff --git a/examples/tutoriel_fr/tests/test_tutoriel.catala_fr b/examples/tutoriel_fr/tests/test_tutoriel.catala_fr new file mode 100644 index 00000000..d46a8a22 --- /dev/null +++ b/examples/tutoriel_fr/tests/test_tutoriel.catala_fr @@ -0,0 +1,29 @@ +@@Inclusion: ../tutoriel_fr.catala_fr@@ + +@Test@ + +/* +déclaration champ d'application TestUnitaire1: + contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu + +champ d'application TestUnitaire1: + définition + calcul_impôt.personne + égal à + Personne { + -- revenu: 230 000€ + -- nombre_enfants: 0 + } + assertion calcul_impôt.impôt_revenu = 72 000€ + +déclaration champ d'application TestUnitaire2: + contexte calcul_impôt champ d'application NouveauCalculImpôtRevenuCorrect + +champ d'application TestUnitaire2: + définition calcul_impôt.personne égal à Personne { + -- revenu: 4 000 € + -- nombre_enfants: 0 + } + + assertion calcul_impôt.impôt_revenu = 0,00 € +*/ \ No newline at end of file diff --git a/examples/tutoriel_fr/tutoriel_fr.catala_fr b/examples/tutoriel_fr/tutoriel_fr.catala_fr index 09ec3f8e..d91320e6 100644 --- a/examples/tutoriel_fr/tutoriel_fr.catala_fr +++ b/examples/tutoriel_fr/tutoriel_fr.catala_fr @@ -22,12 +22,11 @@ en de courtes lignes, cela apparaîtera comme un seul paragraphe dans la sortie. Si vous voulez créer un nouveau paragraphe laisser une ligne vierge dans la source. Catala vous permet de déclarer des entêtes de section ou de sous-section, -comme c'est le cas ici, acec la répétition deux fois de l'arobase. Vous pouvez +en les précédant et les suivant de deux arobases. Vous pouvez diminuer l'importance du titre en augmentant le nombre de "+" après le titre de l'entête. -L'unité de division fondamentale est l'article, commencé par un simple -arobase. +L'unité de division fondamentale est l'article, encadré par un simple arobase. Étudions un exemple ficitif qui définit un impôt sur le revenu. @Article 1@ @@ -35,21 +34,21 @@ L'impôt sur le revenu d'un individu est calculé en tant qu'un pourcentage fixe des revenus d'une personne pour une année. /* -# Bienvenue au code Catala. Ceci est un commentaire car la ligne débute par -# le caractère #. +# Bienvenue dans le mode code de Catala. +# Ceci est un commentaire car la ligne débute par le caractère #. # Nous allons bientôt apprendre ce que l'on doit écrire ici pour traduire # le sens d'un article de loi en code Catala. */ -Afin de faire cela, nous allons mélanger de courts bouts de code entre des phrases -d'un texte législatif. Chaque bout de code devra être aussi court que possible +Afin de faire cela, nous allons entremêler courts bouts de code et phrases +du texte législatif. Chaque bout de code devra être aussi court que possible et aussi proche que possible de la phrase qui justifie le code. Ce style s'appelle programmation littéraire, un paradigme de programmation inventé par le célèbre informaticien Donald Knuth dans les années 70. @@Définir un impôt sur le revenu fictif@@+ -Le contenu de l'article 1 utilise beaucoup d'éléments du contexte implicite: +Le contenu de l'article 1 utilise beaucoup d'éléments du contexte implicite : il existe une personne avec un revenu et en même temps un impôt sur le revenu, qu'une personne doit acquitter chaque année. Même si ce contexte implicite n'est pas inscrit en tant que tel dans la loi, nous devons l'expliciter pour le traduire @@ -67,8 +66,9 @@ déclaration structure Personne: donnée revenu contenu argent # A cette ligne, revenu est le nom du champ de la structure et # "argent" est le type de de données de ce champ. - # On peut utiliser d'autres types comme : entier, décimal, argent, date, durée - # ou tout autre structure ou énumération que vous déclarez + # On peut utiliser d'autres types comme : entier, décimal, + # argent, date, durée ou tout autre structure ou énumération + # que vous aurez déclaré donnée nombre_enfants contenu entier # "revenu" and "nombre_enfants" commençent par une lettre minuscule, # ils adhèrent à la convention snake_case @@ -85,40 +85,42 @@ Parfois, la loi donne une énumération de différentes situations. Ces énumér sont modélisés en Catala par le type énumération, comme suit : @@Début métadonnées@@ /* -déclaration énumération CreditImpot: -# Le nom "CreditImpot" s'écrit aussi en CamlCase --- AucunCreditImpot -# Cette ligne indique que "CreditImpot" peut être en situation "AucunCreditImpot" --- CreditImpotEnfants contenu entier -# Cette ligne indique, de manière alternative, que "CreditImpot" peut aussi -# être une situation "CreditImpotEnfants". Cette situation porte un contenu +déclaration énumération CréditImpôt: +# Le nom "CréditImpôt" s'écrit aussi en CamlCase +-- AucunCréditImpôt +# Cette ligne indique que "CréditImpôt" peut être en situation +# "AucunCréditImpôt" +-- CréditImpôtEnfants contenu entier +# Cette ligne indique, de manière alternative, que "CréditImpôt" peut aussi +# être une situation "CréditImpôtEnfants". Cette situation porte un contenu # de type entier qui correspond au nombre d'enfants concernés par le crédit -# d'impôt. Cela signifie que si vous êtes dans la situation "CreditImpotEnfants", -# vous aurez aussi accès à ce nombre d'enfants. +# d'impôt. Cela signifie que si vous êtes dans la situation +# "CréditImpôtEnfants", vous aurez aussi accès à ce nombre d'enfants. */ @@Fin métadonnées@@ -En informatique, une telle énumération est appelée "type somme" ou simplement enum. -La combinaison de structures et d'énumération permet au programmeur Catala de déclarer -toutes les formes possibles de données, car elles sont équivalentes à la notion puissante -de "types de données algébriques". +En informatique, une telle énumération est appelée "type somme" ou simplement +énumération. La combinaison de structures et d'énumération permet au programmeur +Catala de déclarer toutes les formes possibles de données, car cette combinaison +est équivalente à la puissante notion de types de données algébriques. Nous avons défini et typé les données que le programme va manipuler. Maintenant, nous devons définir un contexte logique dans lequel ces données vont évoluer. On effectue cela par la notion de "champs d'application" en Catala. -Les champs d'application sont proches des fonctions en termes de programmation traditionnelle. -Les champs d'application doivent avoir été déclarées préalablement dans les métadonnées, ainsi: +Les champs d'application sont proches des fonctions en termes de programmation +traditionnelle. Les champs d'application doivent avoir été déclarés +préalablement dans les métadonnées, de la manière suivante: @@Début métadonnées@@ /* -déclaration champ d'application CalculImpotRevenu: +déclaration champ d'application CalculImpôtRevenu: # Les champs d'application utilisent le CamlCase contexte personne contenu Personne # Cette ligne déclare un élémént de contexte du champ d'application, # cela ressemble à un paramètre de fonction en informatique. C'est la # donnée sur laquelle le champ d'application va intervenir contexte pourcentage_fixe contenu décimal - contexte impot_revenu contenu décimal + contexte impôt_revenu contenu argent */ @@Fin métadonnées@@ @@ -129,8 +131,8 @@ de l'article 1 qui a été copié ci-dessous. L'impôt sur le revenu pour une personne est défini comme un pourcentage fixe des revenus de la personne pour une année. /* -champ d'application IncomeTaxComputation: - définition impot_revenu égal à +champ d'application CalculImpôtRevenu: + définition impôt_revenu égal à personne.revenu *€ pourcentage_fixe */ @@ -138,7 +140,7 @@ Dans le code, nous définissons à l'intérieur de notre champ d'application le montant d'impôt sur le revenu selon la formule décrit dans l'article. Quand nous définissons des fomules, vous avez accès à tous les opérateurs arithmétiques habituels : addition "+", soustraction "-", multiplication "*" -et division (slash). +et division (barre oblique). Toutefois, dans le code Catala, vous pouvez voir que nous utilisons "*€" pour multiplier les revenus d'une personne par le pourcentage fixe. Le @@ -150,7 +152,7 @@ Ainsi, afin d'être clair, nous suffixons ces opérations avec quelque chose qui indique le type de donnée manipulé. Les suffixes sont "€" pour de l'argent, "." pour les décimales, arobase (comme dans les adresses mail) pour les dates et le symbole chapeau pour les durées. Si vous oubliez le suffixe, le vérificateur -de type Catala va afficher une message d'erreur afin de vous aider à le placer +de types de Catala va afficher une message d'erreur afin de vous aider à le placer comme il le faut. Mais dans l'article 1, une question reste sans réponse: quelle est la valeur @@ -160,8 +162,8 @@ dans les sources législatives. Ici, supposons que nous avons: @Article 2@ Le pourcentage fixe mentionné à l'article 1 est égal à 20%. /* -champ d'application CalculImpotRevenu: - définition pourcentage_fixe égal à 20 % +champ d'application CalculImpôtRevenu: + définition pourcentage_fixe égal à 20% # Ecrire 20% est juste une abbréviation pour 0.20 */ @@ -184,22 +186,22 @@ le pourcentage fixe mentionné à l'article 1 vaut 15 %. Cet article donne en réalité une autre définition pour le pourcentage fixe, préalablement défini à l'article 2. Toutefois, si l'article 3 définit le pourcentage de manière conditionnelle pour la personne ayant plus de deux enfants. -Catala permet de redéfinir précisément uen variable sous une condition : +Catala permet de redéfinir précisément une variable sous une condition : /* -champ d'application CalculImpotRevenu: +champ d'application CalculImpôtRevenu: définition pourcentage_fixe sous condition personne.nombre_enfants >= 2 - conséquence égal à 15 % + conséquence égal à 15% # Ecrire 15% est juste une abbréviation pour 0.15 */ -Quand le programme Catala va s'exécuter, la définition qui est juste sera choisi -dynamiquement en vérifiant quelle condition est vraie. Une source législative -rédigée correctement doit toujours garantir qu'au maximum une seule condition -soit vrai à tout moment. Toutefois si ce n'est pas le cas, Catala vous permettra -de définir un ordre des priorités sur les conditions, qui doit être justifié par -la loi. +Quand le programme Catala va s'exécuter, la juste définition sera choisie +dynamiquement en déterminant laquelle des condition est vraie dans le contexte. +Une source législative rédigée correctement doit toujours garantir qu'au maximum +une seule condition soit vraie à tout moment. Toutefois, si ce n'est pas le cas, +Catala vous permettra de définir un ordre des priorités sur les conditions, +qui doit être justifié par un raisonnement juridique. @@Fonctions@@+ @@ -214,7 +216,7 @@ déclaration structure DeuxTranches: donnée taux1 contenu décimal donnée taux2 contenu décimal -déclaration champ d'application CalculImpotDeuxTranches : +déclaration champ d'application CalculImpôtDeuxTranches : contexte tranches contenu DeuxTranches contexte formule_imposition contenu argent dépend de argent */ @@ -227,7 +229,7 @@ est égal au montant d'impôt dans chaque tranche multiplié par le taux de chaque branche. /* -champ d'application CalculImpotDeuxTranches : +champ d'application CalculImpôtDeuxTranches : définition formule_imposition de revenu égal à si revenu <=€ tranches.seuil alors revenu *€ tranches.taux1 @@ -248,30 +250,31 @@ l'impôt sur le revenu de l'article 1 est de 40% du revenu au-dessus de 100 000€. En dessous de 100 000€, l'impôt sur le revenu est de 20% du revenu. /* -déclaration champ d'application NouveauCalculImpotRevenu: - contexte deux_tranches champ d'application CalculImpotDeuxTranches +déclaration champ d'application NouveauCalculImpôtRevenu: + contexte deux_tranches champ d'application CalculImpôtDeuxTranches # Cette ligne indique que nous ajoutons l'élément deux_tranches au contexte. # Toutefois, les mots clé "champ d'application" indique que l'élément n'est - # pas une donnée mais plutôt un sous-champ d'application qui peut être utiliser - # pour calculer des choses. + # pas une donnée mais plutôt un sous-champ d'application qui peut être + # utilisé pour calculer des choses. contexte personne contenu Personne - contexte impot_revenu contenu argent + contexte impôt_revenu contenu argent -champ d'application NouveauCalculImpotRevenu : +champ d'application NouveauCalculImpôtRevenu : définition deux_tranches.tranches égal à DeuxTranches { -- seuil: 100 000€ -- taux1: 20% -- taux2: 40% } - définition impot_revenu égal à deux_tranches.formule_imposition de personne.revenu + définition impôt_revenu égal à + deux_tranches.formule_imposition de personne.revenu */ @Article 6@ -Les personnes ayant moins de 10 000€ de revenus sont exemptés de l'impôt sur le revenu -prévu à l'article 1. +Les personnes ayant moins de 10 000€ de revenus sont exemptés de l'impôt +sur le revenu prévu à l'article 1. /* -champ d'application NouveauCalculImpotRevenu: - définition impot_revenu sous condition +champ d'application NouveauCalculImpôtRevenu: + définition impôt_revenu sous condition personne.revenu <=€ 10 000€ conséquence égal à 0€ */ @@ -291,17 +294,17 @@ même la vérification formelle. Commençons par les tests. Tester les programmes Catala peut se faire directement en Catala. En effet, écrire des cas de tests pour chaque champ d'application Catala que vous définissez est une bonne pratique appelée "tests unitaires" dans la -communauté du génie logicielle. Un cas de test est défini dans un autre +communauté du génie logicielle. Les cas de test sont définis dans des champ d'application : @Tester NouveauCalculImpotRevenu@ /* déclaration champ d'application Test1: - contexte calcul_impot champ d'application NouveauCalculImpotRevenu + contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu champ d'application Test1: définition - calcul_impot.personne + calcul_impôt.personne # L'on définit le paramètre au sous-champ d'application égal à # Les quatre lignes ci-dessous définissent une structure entière @@ -315,22 +318,21 @@ champ d'application Test1: # sous-champ d'application et nous assertons qu'il vaut bien # la valeur attendue : # (230 000€ - 100 000€) * 40% + 100 000€ * 20% = 72 000€ - - assertion calcul_impot.impot_revenu = 72 000€ + assertion calcul_impôt.impôt_revenu = 72 000€ */ Ce test devrait être bon. Maintenant étudions un test en échec : /* déclaration champ d'application Test2: - contexte calcul_impot champ d'application NouveauCalculImpotRevenu + contexte calcul_impôt champ d'application NouveauCalculImpôtRevenu champ d'application Test2: - définition calcul_impot.personne égal à Personne { + définition calcul_impôt.personne égal à Personne { -- revenu: 4 000€ -- nombre_enfants: 0 } - assertion calcul_impot.revenu = 0€ + assertion calcul_impôt.impôt_revenu = 0€ */ Ce cas de test devrait calculer un impôt sur le revenu de 0€, @@ -351,12 +353,12 @@ Cette priorité implicite doit être explicitement déclaré en Catala. Voici un version correcte du champ d'application NouveauCalculImpotRevenu : /* -déclaration champ d'application NouveauCalculImpotRevenuCorrect: - contexte deux_tranches champ d'application CalculImpotDeuxTranches +déclaration champ d'application NouveauCalculImpôtRevenuCorrect: + contexte deux_tranches champ d'application CalculImpôtDeuxTranches contexte personne contenu Personne - contexte impot_revenu contenu argent + contexte impôt_revenu contenu argent -champ d'application NouveauCalculImpotRevenuCorrect : +champ d'application NouveauCalculImpôtRevenuCorrect : définition deux_tranches.tranches égal à DeuxTranches { -- seuil: 100 000€ -- taux1: 20% @@ -368,11 +370,12 @@ champ d'application NouveauCalculImpotRevenuCorrect : # la règle à laquelle vous voulez attacher l'exception. Vous pouvez mettre # n'importe quel identifiant en snake_case pour l'étiquette. étiquette article_5 - définition impot_revenu égal à deux_tranches.formule_imposition de personne.revenu + définition impôt_revenu égal à + deux_tranches.formule_imposition de personne.revenu # Puis, vous pouvez déclarez l'exception par référence à l'étiquette exception article_5 - définition impot_revenu sous condition + définition impôt_revenu sous condition personne.revenu <=€ 10 000€ conséquence égal à 0€ */ @@ -381,14 +384,14 @@ Le test devrait désormais fonctionner : /* déclaration champ d'application Test3: - contexte calcul_impot champ d'application NouveauCalculImpotRevenuCorrect + contexte calcul_impôt champ d'application NouveauCalculImpôtRevenuCorrect champ d'application Test3: - définition calcul_impot.personne égal à Personne { + définition calcul_impôt.personne égal à Personne { -- revenu: 4 000€ -- nombre_enfants: 0 } - assertion calcul_impot.impot_revenu = 0€ + assertion calcul_impôt.impôt_revenu = 0€ */ @@Conclusion@@+ @@ -399,5 +402,6 @@ législatif avec leur traduction algorithmique. Il n'y pas une seule bonne façon d'écrire des programmes Catala car le style de programmation doit être adapté au texte de loi annoté. Cependant, Catala est un -langage fonctionnel au fond, alors suivre les patrons de conception fonctionnels +langage basé sur la programmation fonctionnelle, donc suivre les +patrons de conception habituels de la programmation fonctionnelle devrait aider à obtenir du code concis et lisible. \ No newline at end of file diff --git a/generate_website_assets.sh b/generate_website_assets.sh index a483f2d9..88f02cf4 100755 --- a/generate_website_assets.sh +++ b/generate_website_assets.sh @@ -12,7 +12,8 @@ make website-assets rsync -a _build/default/_doc/_html/ $1/ocaml_docs/ scp examples/allocations_familiales/allocations_familiales.html $1/ scp examples/us_tax_code/us_tax_code.html $1/ -scp examples/tutorial/tutorial_en.html $1/ +scp examples/tutorial_en/tutorial_en.html $1/ +scp examples/tutoriel_fr/tutoriel_fr.html $1/ scp grammar.html $1/ scp catala.html $1/ scp _build/default/src/catala.bc.js $1/playground/ \ No newline at end of file diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index 89be92a2..21d73c60 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -82,7 +82,7 @@ 'name' : 'comment.line.catala_fr' } { - 'match' : '(contexte)(\\s+)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)' + 'match' : '(contexte)(\\s+)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)' 'captures' : { '1' : { 'name' : 'keyword.other.catala_fr' @@ -128,7 +128,7 @@ 'name' : 'support.type.catala_fr' } { - 'match' : '\\b([A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)(\\.)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' + 'match' : '\\b([A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)(\\.)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' 'captures' : { '1' : { 'name' : 'entity.name.class.catala_fr' @@ -142,7 +142,7 @@ } } { - 'match' : '\\b([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)(\\.)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\'\\.]*)\\b' + 'match' : '\\b([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)(\\.)([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\'\\.]*)\\b' 'captures' : { '1' : { 'name' : 'entity.name.function.catala_fr' @@ -156,11 +156,11 @@ } } { - 'match' : '\\b([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' + 'match' : '\\b([a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' 'name' : 'entity.name.function.catala_fr' } { - 'match' : '\\b([A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' + 'match' : '\\b([A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}][a-z\\x{00e9}\\x{00e8}\\x{00e0}\\x{00e2}\\x{00f9}\\x{00ee}\\x{00f4}\\x{00ea}\\x{0153}\\x{00e7}A-Z\\x{00c9}\\x{00c8}\\x{00c0}\\x{00c2}\\x{00d9}\\x{00ce}\\x{00d4}\\x{00ca}\\x{0152}\\x{00c7}0-9_\\\']*)\\b' 'name' : 'entity.name.class.catala_fr' } ] diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index 9008c4e2..f6322d46 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -132,9 +132,9 @@ styles [] { ## Parse contexts ################################################# -__LOWER_CHARS \= a-zéèàâùîêœç +__LOWER_CHARS \= a-zéèàâùîôêœç -__UPPER_CHARS \= A-ZÉÈÀÂÙÎÊŒÇ +__UPPER_CHARS \= A-ZÉÈÀÂÙÎÔÊŒÇ __SC_ID \= [$${__LOWER_CHARS}][$${__LOWER_CHARS}$${__UPPER_CHARS}0-9_\']* diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 847df392..5e9bc803 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -36,10 +36,10 @@ class CatalaFrLexer(RegexLexer): bygroups(Operator)), (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme|date_aujourd_hui)\\b', bygroups(Keyword.Type)), - (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), - (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), - (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Variable)), - (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class)), + (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), + (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), + (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Variable)), + (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class)), ('(\n|\r|\r\n)', Text), ('.', Text), ], diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index 5f5f12f5..f59d02cd 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -133,7 +133,7 @@ match - (contexte)(\s+)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*) + (contexte)(\s+)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*) captures 1 @@ -203,7 +203,7 @@ match - \b([A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*)(\.)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b + \b([A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*)(\.)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b captures 1 @@ -225,7 +225,7 @@ match - \b([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*)(\.)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\'\.]*)\b + \b([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*)(\.)([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\'\.]*)\b captures 1 @@ -247,13 +247,13 @@ match - \b([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b + \b([a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b name entity.name.function.catala_fr match - \b([A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b + \b([A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}][a-z\x{00e9}\x{00e8}\x{00e0}\x{00e2}\x{00f9}\x{00ee}\x{00f4}\x{00ea}\x{0153}\x{00e7}A-Z\x{00c9}\x{00c8}\x{00c0}\x{00c2}\x{00d9}\x{00ce}\x{00d4}\x{00ca}\x{0152}\x{00c7}0-9_\']*)\b name entity.name.class.catala_fr @@ -286,4 +286,3 @@ - From 8dd95dec42b0a909136a67cdeda83d643988e822 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 24 Dec 2020 17:17:11 +0100 Subject: [PATCH 123/142] Improved error messages --- src/catala/catala_surface/parser.messages | 355 +++++++++++++++---- src/catala/catala_surface/parser_errors.ml | 23 +- syntax_highlighting/fr/pygments/catala_fr.py | 4 +- 3 files changed, 302 insertions(+), 80 deletions(-) diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 417ef673..15c1e058 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,3 +1,15 @@ +source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE LAW_TEXT END_CODE +## +## Ends in an error in state: 323. +## +## metadata_block -> BEGIN_CODE option(law_text) code END_CODE option(law_text) . END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## +## The known suffix of the stack is as follows: +## BEGIN_CODE option(law_text) code END_CODE option(law_text) +## + +expected a metadata-closing tag + source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## ## Ends in an error in state: 322. @@ -8,7 +20,19 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## BEGIN_CODE option(law_text) code END_CODE ## -should not happen, please file an issue at https://github.com/CatalaLang/catala/issues +expected a metadata-closing tag + +source_file_or_master: BEGIN_METADATA BEGIN_CODE LAW_TEXT DECIMAL_LITERAL +## +## Ends in an error in state: 21. +## +## metadata_block -> BEGIN_CODE option(law_text) . code END_CODE option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## +## The known suffix of the stack is as follows: +## BEGIN_CODE option(law_text) +## + +should not happen source_file_or_master: BEGIN_METADATA BEGIN_CODE YEAR ## @@ -22,6 +46,18 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE YEAR expected a declaration or a scope use +source_file_or_master: BEGIN_METADATA LAW_TEXT ASSERTION +## +## Ends in an error in state: 19. +## +## source_file_item -> BEGIN_METADATA option(law_text) . metadata_block [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## +## The known suffix of the stack is as follows: +## BEGIN_METADATA option(law_text) +## + +expected some text or the beginning of a code section + source_file_or_master: BEGIN_METADATA YEAR ## ## Ends in an error in state: 18. @@ -166,7 +202,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLO ## scope_decl_item ## -expected the next context item, or another declaration or scope use +expected another scope context item or the end of the scope declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## @@ -416,16 +452,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> CARDINAL -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 222, spurious reduction of production assertion_base -> expression -## In state 223, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 227, spurious reduction of production scope_item -> ASSERTION assertion +## In state 53, spurious reduction of production primitive_expression -> CARDINAL +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 222, spurious reduction of production assertion_base -> expression +## In state 223, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 227, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item @@ -455,8 +491,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed @@ -498,14 +534,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> CARDINAL -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 216, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 53, spurious reduction of production primitive_expression -> CARDINAL +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 216, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition @@ -535,8 +571,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with @@ -554,8 +590,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item @@ -645,8 +681,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable @@ -663,6 +699,56 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION expected the name of the variable you want to define +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION IDENT DEFINED_AS +## +## Ends in an error in state: 233. +## +## definition -> option(label) option(exception_to) . DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] +## rule -> option(label) option(exception_to) . RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] +## +## The known suffix of the stack is as follows: +## option(label) option(exception_to) +## + +expected a rule or a definition after the exception declaration + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION YEAR +## +## Ends in an error in state: 231. +## +## exception_to -> EXCEPTION . ident [ RULE DEFINITION ] +## +## The known suffix of the stack is as follows: +## EXCEPTION +## + +expected the label to which the exception is referring back + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL IDENT DEFINED_AS +## +## Ends in an error in state: 230. +## +## definition -> option(label) . option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] +## rule -> option(label) . option(exception_to) RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] +## +## The known suffix of the stack is as follows: +## option(label) +## + +expected a rule or a definition after the label declaration + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL YEAR +## +## Ends in an error in state: 200. +## +## label -> LABEL . ident [ RULE EXCEPTION DEFINITION ] +## +## The known suffix of the stack is as follows: +## LABEL +## + +expected the name of the label + source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## ## Ends in an error in state: 213. @@ -736,8 +822,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule @@ -818,6 +904,92 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION expected an expression for the content of this enum case + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL ALT YEAR +## +## Ends in an error in state: 79. +## +## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] +## +## The known suffix of the stack is as follows: +## struct_content_field ALT +## + +expected the name of the structure field + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL THEN +## +## Ends in an error in state: 78. +## +## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RBRACKET ] +## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] +## +## The known suffix of the stack is as follows: +## struct_content_field +## +## WARNING: This example involves spurious reductions. +## This implies that, although the LR(1) items shown above provide an +## accurate view of the past (what has been recognized so far), they +## may provide an INCOMPLETE view of the future (what was expected next). +## In state 53, spurious reduction of production primitive_expression -> CARDINAL +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 142, spurious reduction of production struct_content_field -> ident COLON logical_expression +## + +expected another structure field or the closing bracket + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON YEAR +## +## Ends in an error in state: 82. +## +## struct_content_field -> ident COLON . logical_expression [ RBRACKET ALT ] +## +## The known suffix of the stack is as follows: +## ident COLON +## + +expected the expression for this struct field + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT YEAR +## +## Ends in an error in state: 81. +## +## struct_content_field -> ident . COLON logical_expression [ RBRACKET ALT ] +## +## The known suffix of the stack is as follows: +## ident +## + +expected a colon + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT YEAR +## +## Ends in an error in state: 77. +## +## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## +## The known suffix of the stack is as follows: +## LBRACKET ALT +## + +expected the name of the structure field + +source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET YEAR +## +## Ends in an error in state: 76. +## +## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## +## The known suffix of the stack is as follows: +## LBRACKET +## + +expected structure fields introduced by -- + source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## ## Ends in an error in state: 75. @@ -867,7 +1039,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test @@ -933,7 +1105,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test @@ -999,13 +1171,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete @@ -1035,13 +1207,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete @@ -1095,13 +1267,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here @@ -1131,7 +1303,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression @@ -1149,13 +1321,13 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 141, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 188, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 141, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 188, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete @@ -1306,7 +1478,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate @@ -1384,15 +1556,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 196, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 197, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 120, spurious reduction of production mult_expression -> base_expression +## In state 107, spurious reduction of production sum_expression -> mult_expression +## In state 83, spurious reduction of production compare_expression -> sum_expression +## In state 143, spurious reduction of production logical_expression -> compare_expression +## In state 158, spurious reduction of production expression -> logical_expression +## In state 196, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 197, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition @@ -1435,8 +1607,8 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 62, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left @@ -1517,7 +1689,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 57, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with @@ -1702,6 +1874,30 @@ source_file_or_master: LAW_HEADING YEAR ## source_file_item ## +expected an article title, another heading or some text + +source_file_or_master: LAW_TEXT YEAR +## +## Ends in an error in state: 341. +## +## list(law_intermediate_text) -> law_intermediate_text . list(law_intermediate_text) [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] +## +## The known suffix of the stack is as follows: +## law_intermediate_text +## + +expected a heading, an article title or some text + +source_file_or_master: MASTER_FILE LAW_INCLUDE LAW_TEXT ENUM +## +## Ends in an error in state: 8. +## +## master_file_includes -> master_file_include option(law_text) . master_file_includes [ # ] +## +## The known suffix of the stack is as follows: +## master_file_include option(law_text) +## + expected some text, another heading or a law article source_file_or_master: MASTER_FILE LAW_INCLUDE YEAR @@ -1716,6 +1912,17 @@ source_file_or_master: MASTER_FILE LAW_INCLUDE YEAR expected another inclusion of a Catala file, since this file is a master file which can only contain inclusions of other Catala files +source_file_or_master: MASTER_FILE LAW_TEXT ENUM +## +## Ends in an error in state: 3. +## +## source_file_or_master -> MASTER_FILE option(law_text) . master_file_includes [ # ] +## +## The known suffix of the stack is as follows: +## MASTER_FILE option(law_text) +## + +expected some text or includes only source_file_or_master: MASTER_FILE YEAR ## diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 82d68328..5cb12e2d 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -8,10 +8,13 @@ let message s = | 1 -> "expected an inclusion of a Catala file, since this file is a master file which can only \ contain inclusions of other Catala files\n" + | 3 -> "expected some text or includes only\n" | 7 -> "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" - | 326 -> "expected some text, another heading or a law article\n" + | 8 -> "expected some text, another heading or a law article\n" + | 341 -> "expected a heading, an article title or some text\n" + | 326 -> "expected an article title, another heading or some text\n" | 331 -> "expected a code block, a metadata block, more law text or a heading\n" | 337 -> "expected a code block, a metadata block, more law text or a heading\n" | 332 -> "expected a declaration or a scope use\n" @@ -85,6 +88,12 @@ let message s = | 75 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" + | 76 -> "expected structure fields introduced by --\n" + | 77 -> "expected the name of the structure field\n" + | 81 -> "expected a colon\n" + | 82 -> "expected the expression for this struct field\n" + | 78 -> "expected another structure field or the closing bracket\n" + | 79 -> "expected the name of the structure field\n" | 150 -> "expected an expression for the content of this enum case\n" | 151 -> "the expression for the content of the enum case is already well-formed, expected an \ @@ -101,6 +110,10 @@ let message s = | 235 -> "expected the expression of the rule\n" | 239 -> "expected the filled keyword the this rule \n" | 213 -> "expected a struct field or a sub-scope context item after the dot\n" + | 200 -> "expected the name of the label\n" + | 230 -> "expected a rule or a definition after the label declaration\n" + | 231 -> "expected the label to which the exception is referring back\n" + | 233 -> "expected a rule or a definition after the exception declaration\n" | 246 -> "expected the name of the variable you want to define\n" | 247 -> "expected the defined as keyword to introduce the definition of this variable\n" | 249 -> "expected an expression for the consequence of this definition under condition\n" @@ -138,7 +151,7 @@ let message s = | 294 -> "expected the name of this new context item\n" | 295 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" | 296 -> "expected the name of the subscope for this context item\n" - | 303 -> "expected the next context item, or another declaration or scope use\n" + | 303 -> "expected another scope context item or the end of the scope declaration\n" | 298 -> "expected the type of this context item\n" | 299 -> "expected the next context item or a dependency declaration for this item\n" | 301 -> "expected the next context item or a dependency declaration for this item\n" @@ -150,7 +163,9 @@ let message s = | 311 -> "expected a content type\n" | 316 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" + | 19 -> "expected some text or the beginning of a code section\n" | 20 -> "expected a declaration or a scope use\n" - | 322 -> - "should not happen, please file an issue at https://github.com/CatalaLang/catala/issues\n" + | 21 -> "should not happen\n" + | 322 -> "expected a metadata-closing tag\n" + | 323 -> "expected a metadata-closing tag\n" | _ -> raise Not_found diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 5e9bc803..46cfcee0 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -24,8 +24,8 @@ class CatalaFrLexer(RegexLexer): 'code': [ (u'(\\*\\/)', bygroups(Text), 'root'), (u'(\\s*\\#.*$)', bygroups(Comment.Single)), - (u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)', - bygroups(Keyword.Declaration, Text, Name.Variable)), + (u'(contexte)(\\s+)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)', + bygroups(Keyword.Declaration, String, Name.Variable)), (u'\\b(selon|sous\\s+forme|fix\xe9|par|d\xe9croissante|croissante|varie|avec|on\\s+a|dans|tel\\s+que|existe|pour|tout|de|si|alors|sinon)\\b', bygroups(Keyword.Reserved)), (u'\\b(champ\\s+d\'application|si\\s+et\\s+seulement\\s+si|d\xe9pend\\s+de|d\xe9claration|inclus|collection|contenu|optionnel|structure|\xe9num\xe9ration|contexte|r\xe8gle|sous\\s+condition|condition|donn\xe9e|cons\xe9quence|rempli|\xe9gal\\s+\xe0|assertion|d\xe9finition|\xe9tiquette|exception)\\b', bygroups(Keyword.Declaration)), (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), From c51c8760cb00e73ff6109545fb178ceabc74bac8 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Fri, 25 Dec 2020 17:09:44 +0100 Subject: [PATCH 124/142] New assets for playground --- generate_website_assets.sh | 6 +- syntax_highlighting/en/ace/mode-catala_en.js | 168 ++++++++++++++++++ syntax_highlighting/fr/ace/mode-catala_fr.js | 169 +++++++++++++++++++ 3 files changed, 342 insertions(+), 1 deletion(-) create mode 100644 syntax_highlighting/en/ace/mode-catala_en.js create mode 100644 syntax_highlighting/fr/ace/mode-catala_fr.js diff --git a/generate_website_assets.sh b/generate_website_assets.sh index 88f02cf4..f0ca62ca 100755 --- a/generate_website_assets.sh +++ b/generate_website_assets.sh @@ -16,4 +16,8 @@ scp examples/tutorial_en/tutorial_en.html $1/ scp examples/tutoriel_fr/tutoriel_fr.html $1/ scp grammar.html $1/ scp catala.html $1/ -scp _build/default/src/catala.bc.js $1/playground/ \ No newline at end of file +scp _build/default/src/catala.bc.js $1/playground/ +scp examples/tutorial_en/tutorial_en.catala_en $1/playground/ +scp examples/tutoriel_fr/tutoriel_fr.catala_fr $1/playground/ +scp syntax_highlighting/en/ace/mode-catala_en.js $1/playground/ +scp syntax_highlighting/fr/ace/mode-catala_fr.js $1/playground/ \ No newline at end of file diff --git a/syntax_highlighting/en/ace/mode-catala_en.js b/syntax_highlighting/en/ace/mode-catala_en.js new file mode 100644 index 00000000..1e3a4634 --- /dev/null +++ b/syntax_highlighting/en/ace/mode-catala_en.js @@ -0,0 +1,168 @@ +/* +* To try in Ace editor, copy and paste into the mode creator +* here : http://ace.c9.io/tool/mode_creator.html +*/ + +ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], function (require, exports, module) { + "use strict"; + var oop = require("../lib/oop"); + var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + /* --------------------- START ----------------------------- */ + var CatalaEnHighlightRules = function () { + this.$rules = { + "start": [ + { + "token": "markup.heading.title", + "regex": "(@@)", + "push": "main__1" + }, + { + "token": "markup.heading.subtitle", + "regex": "(@)", + "push": "main__2" + }, + { + "token": "entity.law", + "regex": "([^\\/])" + }, + { + "token": "comment.block.documentation", + "regex": "(\\/\\*)", + "push": "code" + }, + { + defaultToken: "text", + } + ], + "code": [ + { + "token": "comment.block.documentation", + "regex": "(\\*\\/)", + "next": "pop" + }, + { + "token": "comment.line", + "regex": "(\\s*\\#.*$)" + }, + { + "token": ["keyword.other", "text", "entity.name.function"], + "regex": "(context)(\\s+)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)" + }, + { + "token": "keyword.control", + "regex": "\\b(match|with\\s+pattern|fixed|by|decreasing|increasing|varies|with|we\\s+have|in|such\\s+that|exists|for|all|of|if|then|else)\\b" + }, + { + "token": "keyword.other", + "regex": "\\b(scope|depends\\s+on|declaration|includes|collection|content|optional|structure|enumeration|context|rule|under\\s+condition|condition|data|consequence|fulfilled|equals|assertion|definition|label|exception)\\b" + }, + { + "token": "constant.numeric", + "regex": "(\\|[0-9]+/[0-9]+/[0-9]+\\|)" + }, + { + "token": "constant", + "regex": "\\b(true|false)\\b" + }, + { + "token": "constant.numeric", + "regex": "\\b([0-9]+(,[0.9]*|))\\b" + }, + { + "token": "punctuation", + "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))" + }, + { + "token": "keyword.operator", + "regex": "(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)" + }, + { + "token": "support.type", + "regex": "\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b" + }, + { + "token": ["entity.name.class", "punctuation", "entity.name.function"], + "regex": "\\b([A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)(\\.)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + "token": ["entity.name.function", "punctuation", "meta.variable_id"], + "regex": "\\b([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)(\\.)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\'\\.]*)\\b" + }, + { + "token": "entity.name.function", + "regex": "\\b([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + "token": "entity.name.class", + "regex": "\\b([A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + defaultToken: "text", + } + ], + "main__1": [ + { + "token": "markup.heading.title", + "regex": "(@@[\\+]*)", + "next": "pop" + }, + { + "token": "markup.heading.title", + "regex": "(.)" + }, + { + defaultToken: "text", + } + ], + "main__2": [ + { + "token": "markup.heading.subtitle", + "regex": "(@)", + "next": "pop" + }, + { + "token": "markup.heading.subtitle", + "regex": "(.)" + }, + { + defaultToken: "text", + } + ] + }; + this.normalizeRules(); + }; + /* ------------------------ END ------------------------------ */ + oop.inherits(CatalaEnHighlightRules, TextHighlightRules); + exports.CatalaEnHighlightRules = CatalaEnHighlightRules; +}); + +ace.define("ace/mode/catala_en", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/catala_en_highlighting_rules"], function (require, exports, module) { + "use strict"; + + var oop = require("../lib/oop"); + var TextMode = require("./text").Mode; + var CatalaEnHighlightRules = require("./catala_en_highlighting_rules").CatalaEnHighlightRules; + + var Mode = function () { + this.HighlightRules = CatalaEnHighlightRules; + this.$behaviour = this.$defaultBehaviour; + }; + oop.inherits(Mode, TextMode); + + (function () { + + this.lineCommentStart = "#"; + + this.$id = "ace/mode/catala_en"; + this.snippetFileId = "ace/snippets/catala_en"; + }).call(Mode.prototype); + + exports.Mode = Mode; + +}); (function () { + ace.require(["ace/mode/catala_en"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); diff --git a/syntax_highlighting/fr/ace/mode-catala_fr.js b/syntax_highlighting/fr/ace/mode-catala_fr.js new file mode 100644 index 00000000..bae260be --- /dev/null +++ b/syntax_highlighting/fr/ace/mode-catala_fr.js @@ -0,0 +1,169 @@ +/* +* To try in Ace editor, copy and paste into the mode creator +* here : http://ace.c9.io/tool/mode_creator.html +*/ + +ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text_highlight_rules"], function (require, exports, module) { + "use strict"; + var oop = require("../lib/oop"); + var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + /* --------------------- START ----------------------------- */ + var CatalaFrHighlightRules = function () { + this.$rules = { + "start": [ + { + "token": "markup.heading.title", + "regex": "(@@)", + "push": "main__1" + }, + { + "token": "markup.heading.subtitle", + "regex": "(@)", + "push": "main__2" + }, + { + "token": "entity.law", + "regex": "([^\\/])" + }, + { + "token": "comment.block.documentation", + "regex": "(\\/\\*)", + "push": "code" + }, + { + defaultToken: "text", + } + ], + "code": [ + { + "token": "comment.block.documentation", + "regex": "(\\*\\/)", + "next": "pop" + }, + { + "token": "comment.line", + "regex": "(\\s*\\#.*$)" + }, + { + "token": ["keyword.other", "text", "entity.name.function"], + "regex": "(contexte)(\\s+)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)" + }, + { + "token": "keyword.control", + "regex": "\\b(selon|sous\\s+forme|fix\u00e9|par|d\u00e9croissante|croissante|varie|avec|on\\s+a|dans|tel\\s+que|existe|pour|tout|de|si|alors|sinon)\\b" + }, + { + "token": "keyword.other", + "regex": "\\b(champ\\s+d'application|si\\s+et\\s+seulement\\s+si|d\u00e9pend\\s+de|d\u00e9claration|inclus|collection|contenu|optionnel|structure|\u00e9num\u00e9ration|contexte|r\u00e8gle|sous\\s+condition|condition|donn\u00e9e|cons\u00e9quence|rempli|\u00e9gal\\s+\u00e0|assertion|d\u00e9finition|\u00e9tiquette|exception)\\b" + }, + { + "token": "constant.numeric", + "regex": "(\\|[0-9]+/[0-9]+/[0-9]+\\|)" + }, + { + "token": "constant", + "regex": "\\b(vrai|faux)\\b" + }, + { + "token": "constant.numeric", + "regex": "\\b([0-9]+(,[0.9]*|))\\b" + }, + { + "token": "punctuation", + "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))" + }, + { + "token": "keyword.operator", + "regex": "(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\\u20ac|%|an|mois|jour)" + }, + { + "token": "support.type", + "regex": "\\b(entier|bool\u00e9en|date|argent|texte|d\u00e9cimal|d\u00e9cret|loi|nombre|somme|date_aujourd_hui)\\b" + }, + { + "token": ["entity.name.class", "punctuation", "entity.name.function"], + "regex": "\\b([A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)(\\.)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + "token": ["entity.name.function", "punctuation", "meta.variable_id"], + "regex": "\\b([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)(\\.)([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\'\\.]*)\\b" + }, + { + "token": "entity.name.function", + "regex": "\\b([a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + "token": "entity.name.class", + "regex": "\\b([A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c7][a-z\u00e9\u00e8\u00e0\u00e2\u00f9\u00ee\u00f4\u00ea\u0153\u00e7A-Z\u00c9\u00c8\u00c0\u00c2\u00d9\u00ce\u00d4\u00ca\u0152\u00c70-9_\\']*)\\b" + }, + { + defaultToken: "text", + } + ], + "main__1": [ + { + "token": "markup.heading.title", + "regex": "(@@[\\+]*)", + "next": "pop" + }, + { + "token": "markup.heading.title", + "regex": "(.)" + }, + { + defaultToken: "text", + } + ], + "main__2": [ + { + "token": "markup.heading.subtitle", + "regex": "(@)", + "next": "pop" + }, + { + "token": "markup.heading.subtitle", + "regex": "(.)" + }, + { + defaultToken: "text", + } + ] + }; + this.normalizeRules(); + }; + /* ------------------------ END ------------------------------ */ + oop.inherits(CatalaFrHighlightRules, TextHighlightRules); + exports.CatalaFrHighlightRules = CatalaFrHighlightRules; +}); + + +ace.define("ace/mode/catala_fr", ["require", "exports", "module", "ace/lib/oop", "ace/mode/text", "ace/mode/catala_fr_highlighting_rules"], function (require, exports, module) { + "use strict"; + + var oop = require("../lib/oop"); + var TextMode = require("./text").Mode; + var CatalaFrHighlightRules = require("./catala_fr_highlighting_rules").CatalaFrHighlightRules; + + var Mode = function () { + this.HighlightRules = CatalaFrHighlightRules; + this.$behaviour = this.$defaultBehaviour; + }; + oop.inherits(Mode, TextMode); + + (function () { + + this.lineCommentStart = "#"; + + this.$id = "ace/mode/catala_fr"; + this.snippetFileId = "ace/snippets/catala_fr"; + }).call(Mode.prototype); + + exports.Mode = Mode; + +}); (function () { + ace.require(["ace/mode/catala_fr"], function (m) { + if (typeof module == "object" && typeof exports == "object" && module) { + module.exports = m; + } + }); +})(); From f966fc87d008945e996145213c2744299a9730b3 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sat, 26 Dec 2020 17:37:41 +0100 Subject: [PATCH 125/142] Added web-compatible version of the Catala interpreter --- Makefile | 8 +- catala.opam | 1 - dune-project | 3 +- generate_website_assets.sh | 5 +- src/catala/catala_surface/parser_driver.ml | 39 ++++-- src/catala/default_calculus/interpreter.ml | 4 +- src/catala/driver.ml | 28 +++- src/catala/literate_programming/html.ml | 4 +- src/catala/literate_programming/latex.ml | 4 +- src/catala/utils/cli.ml | 11 +- src/catala/utils/dune | 2 +- src/catala/utils/pos.ml | 152 ++++++++++++--------- src/catala/utils/pos.mli | 2 + src/catala_web/catala_web.ml | 16 +++ src/catala_web/dune | 9 ++ src/dune | 2 +- 16 files changed, 177 insertions(+), 113 deletions(-) create mode 100644 src/catala_web/catala_web.ml create mode 100644 src/catala_web/dune diff --git a/Makefile b/Makefile index 11483110..c1c2bf7f 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ dependencies-ocaml: sedlex \ menhir \ menhirLib \ - dune dune-build-info \ + dune \ cmdliner obelisk \ re \ obelisk \ @@ -24,7 +24,7 @@ dependencies-ocaml: bindlib \ zarith zarith_stubs_js \ ocamlgraph \ - js_of_ocaml-compiler \ + js_of_ocaml-compiler js_of_ocaml js_of_ocaml-ppx \ odate init-submodules: @@ -50,7 +50,7 @@ doc: ln -sf $(PWD)/_build/default/_doc/_html/index.html doc/odoc.html install: - dune build @install + dune build --profile release @install ########################################## # Syntax highlighting rules @@ -161,7 +161,7 @@ catala.html: src/catala/utils/cli.ml dune exec src/catala.exe -- --help=groff | man2html | sed -e '1,8d' \ | tac | sed "1,20d" | tac > $@ -website-assets: doc literate_examples grammar.html catala.html +website-assets: doc literate_examples grammar.html catala.html install ########################################## # Misceallenous diff --git a/catala.opam b/catala.opam index 1b87454e..72e77e69 100644 --- a/catala.opam +++ b/catala.opam @@ -19,7 +19,6 @@ depends: [ "menhirLib" {>= "20200211"} "unionFind" {>= "20200320"} "bindlib" {>= "5.0.1"} - "dune-build-info" {>= "2.0.1"} "cmdliner" {>= "1.0.4"} "re" {>= "1.9.0"} "zarith" {>= "1.10"} diff --git a/dune-project b/dune-project index f5180d38..7193583b 100644 --- a/dune-project +++ b/dune-project @@ -27,7 +27,6 @@ (menhirLib (>= 20200211)) (unionFind (>= 20200320)) (bindlib (>= 5.0.1)) - (dune-build-info (>= 2.0.1)) (cmdliner (>= 1.0.4)) (re (>= 1.9.0)) (zarith (>= 1.10)) @@ -38,4 +37,4 @@ ) ) -(using menhir 2.1) +(using menhir 2.1) \ No newline at end of file diff --git a/generate_website_assets.sh b/generate_website_assets.sh index f0ca62ca..faac657e 100755 --- a/generate_website_assets.sh +++ b/generate_website_assets.sh @@ -7,8 +7,6 @@ if [[ $1 == "" ]]; then exit 1 fi -make website-assets - rsync -a _build/default/_doc/_html/ $1/ocaml_docs/ scp examples/allocations_familiales/allocations_familiales.html $1/ scp examples/us_tax_code/us_tax_code.html $1/ @@ -16,7 +14,8 @@ scp examples/tutorial_en/tutorial_en.html $1/ scp examples/tutoriel_fr/tutoriel_fr.html $1/ scp grammar.html $1/ scp catala.html $1/ -scp _build/default/src/catala.bc.js $1/playground/ +scp _build/default/src/catala_web/catala_web.bc.js $1/playground/ +scp bundle.js $1/playground/ scp examples/tutorial_en/tutorial_en.catala_en $1/playground/ scp examples/tutoriel_fr/tutoriel_fr.catala_fr $1/playground/ scp syntax_highlighting/en/ace/mode-catala_en.js $1/playground/ diff --git a/src/catala/catala_surface/parser_driver.ml b/src/catala/catala_surface/parser_driver.ml index a72b6578..343d5145 100644 --- a/src/catala/catala_surface/parser_driver.ml +++ b/src/catala/catala_surface/parser_driver.ml @@ -179,12 +179,22 @@ let sedlex_with_menhir (lexer' : lexbuf -> Parser.token) (token_list : (string * (** {1 API} *) (** Parses a single source file *) -let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) : Ast.program = - Cli.debug_print (Printf.sprintf "Parsing %s" source_file); - let input = try open_in source_file with Sys_error msg -> Errors.raise_error msg in - let lexbuf = Sedlexing.Utf8.from_channel input in - Sedlexing.set_filename lexbuf source_file; - Parse_utils.current_file := source_file; +let rec parse_source_file (source_file : Pos.input_file) (language : Cli.frontend_lang) : + Ast.program = + Cli.debug_print + (Printf.sprintf "Parsing %s" (match source_file with FileName s | Contents s -> s)); + let lexbuf, input = + match source_file with + | FileName source_file -> ( + try + let input = open_in source_file in + (Sedlexing.Utf8.from_channel input, Some input) + with Sys_error msg -> Errors.raise_error msg ) + | Contents contents -> (Sedlexing.Utf8.from_gen (Gen.of_string contents), None) + in + let source_file_name = match source_file with FileName s -> s | Contents _ -> "stdin" in + Sedlexing.set_filename lexbuf source_file_name; + Parse_utils.current_file := source_file_name; let lexer_lang = match language with | `Fr -> Lexer_fr.lexer_fr @@ -200,16 +210,16 @@ let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) let commands_or_includes = sedlex_with_menhir lexer_lang token_list_lang Parser.Incremental.source_file_or_master lexbuf in - close_in input; + (match input with Some input -> close_in input | None -> ()); match commands_or_includes with | Ast.SourceFile commands -> - let program = expand_includes source_file commands language in + let program = expand_includes source_file_name commands language in { program_items = program.Ast.program_items; - program_source_files = source_file :: program.Ast.program_source_files; + program_source_files = source_file_name :: program.Ast.program_source_files; } | Ast.MasterFile includes -> - let current_source_file_dirname = Filename.dirname source_file in + let current_source_file_dirname = Filename.dirname source_file_name in let includes = List.map (fun includ -> @@ -220,7 +230,7 @@ let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) let new_program = List.fold_left (fun acc includ_file -> - let includ_program = parse_source_file includ_file language in + let includ_program = parse_source_file (FileName includ_file) language in { Ast.program_source_files = acc.Ast.program_source_files @ includ_program.program_source_files; @@ -229,7 +239,10 @@ let rec parse_source_file (source_file : string) (language : Cli.frontend_lang) { Ast.program_source_files = []; Ast.program_items = [] } includes in - { new_program with program_source_files = source_file :: new_program.program_source_files } + { + new_program with + program_source_files = source_file_name :: new_program.program_source_files; + } (** Expands the include directives in a parsing result, thus parsing new source files *) and expand_includes (source_file : string) (commands : Ast.program_item list) @@ -240,7 +253,7 @@ and expand_includes (source_file : string) (commands : Ast.program_item list) | Ast.LawStructure (LawInclude (Ast.CatalaFile sub_source)) -> let source_dir = Filename.dirname source_file in let sub_source = Filename.concat source_dir (Pos.unmark sub_source) in - let includ_program = parse_source_file sub_source language in + let includ_program = parse_source_file (FileName sub_source) language in { Ast.program_source_files = acc.Ast.program_source_files @ includ_program.program_source_files; diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index d3402a4b..aff8b1c4 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -152,14 +152,14 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis match entry with | VarDef -> Cli.log_print - (Format.asprintf "%a %a = %a" Print.format_log_entry entry + (Format.asprintf "@[%a@ %a@ =@ %a@]" Print.format_log_entry entry (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) infos Print.format_expr (e', Pos.no_pos)) | _ -> Cli.log_print - (Format.asprintf "%a %a" Print.format_log_entry entry + (Format.asprintf "@[%a@ %a@]" Print.format_log_entry entry (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) diff --git a/src/catala/driver.ml b/src/catala/driver.ml index c0d7bec3..610cb3ba 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -14,17 +14,19 @@ module Cli = Utils.Cli module Errors = Utils.Errors +module Pos = Utils.Pos (** Entry function for the executable. Returns a negative number in case of error. *) -let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_output : bool) - (pygmentize_loc : string option) (backend : string) (language : string option) - (max_prec_digits : int option) (trace : bool) (ex_scope : string option) - (output_file : string option) : int = +let driver (source_file : Pos.input_file) (debug : bool) (unstyled : bool) + (wrap_weaved_output : bool) (pygmentize_loc : string option) (backend : string) + (language : string option) (max_prec_digits : int option) (trace : bool) + (ex_scope : string option) (output_file : string option) : int = try Cli.debug_flag := debug; Cli.style_flag := not unstyled; Cli.trace_flag := trace; Cli.debug_print "Reading files..."; + (match source_file with FileName _ -> () | Contents c -> Cli.contents := c); (match max_prec_digits with None -> () | Some i -> Cli.max_prec_digits := i); let language = match language with @@ -50,6 +52,12 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ match backend with | Cli.Makefile -> let backend_extensions_list = [ ".tex" ] in + let source_file = + match source_file with + | FileName f -> f + | Contents _ -> + Errors.raise_error "The Makefile backend does not work if the input is not a file" + in let output_file = match output_file with | Some f -> f @@ -67,6 +75,13 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ 0 | Cli.Latex | Cli.Html -> let language : Cli.backend_lang = Cli.to_backend_lang language in + let source_file = + match source_file with + | FileName f -> f + | Contents _ -> + Errors.raise_error + "The literate programming backends do not work if the input is not a file" + in Cli.debug_print (Printf.sprintf "Weaving literate program into %s" ( match backend with @@ -144,6 +159,7 @@ let driver (source_file : string) (debug : bool) (unstyled : bool) (wrap_weaved_ 0 with Errors.StructuredError (msg, pos) -> Cli.error_print (Errors.print_structured_error msg pos); - exit (-1) + -1 -let main () = Cmdliner.Term.exit @@ Cmdliner.Term.eval (Cli.catala_t driver, Cli.info) +let main () = + Cmdliner.Term.exit @@ Cmdliner.Term.eval (Cli.catala_t (fun f -> driver (FileName f)), Cli.info) diff --git a/src/catala/literate_programming/html.ml b/src/catala/literate_programming/html.ml index 61bad4fd..1e9f9a08 100644 --- a/src/catala/literate_programming/html.ml +++ b/src/catala/literate_programming/html.ml @@ -76,9 +76,7 @@ let wrap_html (source_files : string list) (custom_pygments : string option) | `Fr -> "Implémentation de texte législatif" | `En -> "Legislative text implementation" ) (match language with `Fr -> "Document généré par" | `En -> "Document generated by") - ( match Build_info.V1.version () with - | None -> "n/a" - | Some v -> Build_info.V1.Version.to_string v ) + Utils.Cli.version ( match language with | `Fr -> "Fichiers sources tissés dans ce document" | `En -> "Source files weaved in this document" ) diff --git a/src/catala/literate_programming/latex.ml b/src/catala/literate_programming/latex.ml index bf3a7e66..44a6189c 100644 --- a/src/catala/literate_programming/latex.ml +++ b/src/catala/literate_programming/latex.ml @@ -89,9 +89,7 @@ let wrap_latex (source_files : string list) (custom_pygments : string option) | `Fr -> "Implémentation de texte législatif" | `En -> "Legislative text implementation" ) (match language with `Fr -> "Document généré par" | `En -> "Document generated by") - ( match Build_info.V1.version () with - | None -> "n/a" - | Some v -> Build_info.V1.Version.to_string v ) + Utils.Cli.version ( match language with | `Fr -> "Fichiers sources tissés dans ce document" | `En -> "Source files weaved in this document" ) diff --git a/src/catala/utils/cli.ml b/src/catala/utils/cli.ml index a8105632..8e4a164c 100644 --- a/src/catala/utils/cli.ml +++ b/src/catala/utils/cli.ml @@ -15,6 +15,8 @@ (** Ssource files to be compiled *) let source_files : string list ref = ref [] +let contents : string ref = ref "" + (** Prints debug information *) let debug_flag = ref false @@ -99,6 +101,8 @@ let catala_t f = const f $ file $ debug $ unstyled $ wrap_weaved_output $ pygmentize_loc $ backend $ language $ max_prec_digits_opt $ trace_opt $ ex_scope $ output) +let version = "0.2.0" + let info = let doc = "Compiler for Catala, a specification language for tax and social benefits computation rules." @@ -120,12 +124,7 @@ let info = ] in let exits = Term.default_exits @ [ Term.exit_info ~doc:"on error." 1 ] in - Term.info "catala" - ~version: - ( match Build_info.V1.version () with - | None -> "n/a" - | Some v -> Build_info.V1.Version.to_string v ) - ~doc ~exits ~man + Term.info "catala" ~version ~doc ~exits ~man (**{1 Terminal formatting}*) diff --git a/src/catala/utils/dune b/src/catala/utils/dune index 6c2f8ca2..43be8405 100644 --- a/src/catala/utils/dune +++ b/src/catala/utils/dune @@ -1,7 +1,7 @@ (library (name utils) (public_name catala.utils) - (libraries cmdliner dune-build-info ANSITerminal)) + (libraries cmdliner ANSITerminal)) (documentation (package catala) diff --git a/src/catala/utils/pos.ml b/src/catala/utils/pos.ml index a0d6470d..ff9d0815 100644 --- a/src/catala/utils/pos.ml +++ b/src/catala/utils/pos.ml @@ -41,6 +41,8 @@ let get_end_column (pos : t) : int = let get_file (pos : t) : string = (fst pos).Lexing.pos_fname +type input_file = FileName of string | Contents of string + let to_string (pos : t) : string = let s, e = pos in Printf.sprintf "in file %s, from %d:%d to %d:%d" s.Lexing.pos_fname s.Lexing.pos_lnum @@ -62,75 +64,89 @@ let indent_number (s : string) : int = with Invalid_argument _ -> String.length s let retrieve_loc_text (pos : t) : string = - let filename = get_file pos in - let blue_style = [ ANSITerminal.Bold; ANSITerminal.blue ] in - if filename = "" then "No position information" - else - let sline = get_start_line pos in - let eline = get_end_line pos in - let oc = - try open_in filename - with Sys_error _ -> - Cli.error_print (Printf.sprintf "File not found : \"%s\"" filename); - exit (-1) - in - let input_line_opt () : string option = try Some (input_line oc) with End_of_file -> None in - 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" + try + let filename = get_file pos in + let blue_style = [ ANSITerminal.Bold; ANSITerminal.blue ] in + if filename = "" then "No position information" + else + let sline = get_start_line pos in + let eline = get_end_line pos in + let oc, input_line_opt = + if filename = "stdin" then + let line_index = ref 0 in + let lines = String.split_on_char '\n' !Cli.contents in + let input_line_opt () : string option = + match List.nth_opt lines !line_index with + | Some l -> + line_index := !line_index + 1; + Some l + | None -> None + in + (None, input_line_opt) + else + let oc = open_in filename in + let input_line_opt () : string option = + try Some (input_line oc) with End_of_file -> None + in + (Some oc, input_line_opt) + in + 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 - Cli.print_with_style error_indicator_style "%*s" - (get_end_column pos - 1) - (String.make (max (get_end_column pos - get_start_column pos) 0) '^') - else if line_no = sline && line_no <> eline then - Cli.print_with_style error_indicator_style "%*s" - (String.length line - 1) - (String.make (max (String.length line - get_start_column pos) 0) '^') - else if line_no <> sline && line_no <> eline then - Cli.print_with_style error_indicator_style "%*s%s" line_indent "" - (String.make (max (String.length line - line_indent) 0) '^') - else if line_no <> sline && line_no = eline then - Cli.print_with_style error_indicator_style "%*s%*s" line_indent "" - (get_end_column pos - 1 - line_indent) - (String.make (max (get_end_column pos - line_indent) 0) '^') - else assert false (* should not happen *) - else "" - in - let include_extra_count = 0 in - let rec get_lines (n : int) : string list = - match input_line_opt () with - | Some line -> - if n < sline - include_extra_count then get_lines (n + 1) - else if n >= sline - include_extra_count && n <= eline + include_extra_count then - print_matched_line line n :: get_lines (n + 1) - else [] - | None -> [] - in - let pos_lines = get_lines 1 in - let spaces = int_of_float (log10 (float_of_int eline)) + 1 in - close_in oc; - Cli.print_with_style blue_style "%*s--> %s\n%s" spaces "" filename - (Cli.add_prefix_to_each_line - (Printf.sprintf "\n%s" (String.concat "\n" pos_lines)) - (fun i -> - let cur_line = sline - include_extra_count + i - 1 in - if - cur_line >= sline - && cur_line <= sline + (2 * (eline - sline)) - && cur_line mod 2 = sline mod 2 - then Cli.print_with_style blue_style "%*d | " spaces (sline + ((cur_line - sline) / 2)) - else if cur_line >= sline - include_extra_count && cur_line < sline then - Cli.print_with_style blue_style "%*d | " spaces cur_line - else if - cur_line <= sline + (2 * (eline - sline)) + 1 + include_extra_count - && cur_line > sline + (2 * (eline - sline)) + 1 - then Cli.print_with_style blue_style "%*d | " spaces (cur_line - (eline - sline + 1)) - else Cli.print_with_style blue_style "%*s | " spaces "")) + if line_no >= sline && line_no <= eline then + "\n" + ^ + if line_no = sline && line_no = eline then + Cli.print_with_style error_indicator_style "%*s" + (get_end_column pos - 1) + (String.make (max (get_end_column pos - get_start_column pos) 0) '^') + else if line_no = sline && line_no <> eline then + Cli.print_with_style error_indicator_style "%*s" + (String.length line - 1) + (String.make (max (String.length line - get_start_column pos) 0) '^') + else if line_no <> sline && line_no <> eline then + Cli.print_with_style error_indicator_style "%*s%s" line_indent "" + (String.make (max (String.length line - line_indent) 0) '^') + else if line_no <> sline && line_no = eline then + Cli.print_with_style error_indicator_style "%*s%*s" line_indent "" + (get_end_column pos - 1 - line_indent) + (String.make (max (get_end_column pos - line_indent) 0) '^') + else assert false (* should not happen *) + else "" + in + let include_extra_count = 0 in + let rec get_lines (n : int) : string list = + match input_line_opt () with + | Some line -> + if n < sline - include_extra_count then get_lines (n + 1) + else if n >= sline - include_extra_count && n <= eline + include_extra_count then + print_matched_line line n :: get_lines (n + 1) + else [] + | None -> [] + in + let pos_lines = get_lines 1 in + let spaces = int_of_float (log10 (float_of_int eline)) + 1 in + (match oc with None -> () | Some oc -> close_in oc); + Cli.print_with_style blue_style "%*s--> %s\n%s" spaces "" filename + (Cli.add_prefix_to_each_line + (Printf.sprintf "\n%s" (String.concat "\n" pos_lines)) + (fun i -> + let cur_line = sline - include_extra_count + i - 1 in + if + cur_line >= sline + && cur_line <= sline + (2 * (eline - sline)) + && cur_line mod 2 = sline mod 2 + then Cli.print_with_style blue_style "%*d | " spaces (sline + ((cur_line - sline) / 2)) + else if cur_line >= sline - include_extra_count && cur_line < sline then + Cli.print_with_style blue_style "%*d | " spaces cur_line + else if + cur_line <= sline + (2 * (eline - sline)) + 1 + include_extra_count + && cur_line > sline + (2 * (eline - sline)) + 1 + then Cli.print_with_style blue_style "%*d | " spaces (cur_line - (eline - sline + 1)) + else Cli.print_with_style blue_style "%*s | " spaces "")) + with Sys_error _ -> "Location:" ^ to_string pos type 'a marked = 'a * t diff --git a/src/catala/utils/pos.mli b/src/catala/utils/pos.mli index 1822988b..a1f41f62 100644 --- a/src/catala/utils/pos.mli +++ b/src/catala/utils/pos.mli @@ -31,6 +31,8 @@ val get_end_column : t -> int val get_file : t -> string +type input_file = FileName of string | Contents of string + (**{2 Formatters}*) val to_string : t -> string diff --git a/src/catala_web/catala_web.ml b/src/catala_web/catala_web.ml new file mode 100644 index 00000000..767254d7 --- /dev/null +++ b/src/catala_web/catala_web.ml @@ -0,0 +1,16 @@ +open Catala.Driver +open Js_of_ocaml + +let _ = + Js.export_all + (object%js + method interpret (contents : Js.js_string Js.t) (scope : Js.js_string Js.t) + (language : Js.js_string Js.t) (trace : bool) = + driver + (Contents (Js.to_string contents)) + false false false None "Interpret" + (Some (Js.to_string language)) + None trace + (Some (Js.to_string scope)) + None + end) diff --git a/src/catala_web/dune b/src/catala_web/dune new file mode 100644 index 00000000..32e7056e --- /dev/null +++ b/src/catala_web/dune @@ -0,0 +1,9 @@ +(executable + (name catala_web) + (modes byte js) + (package catala) + (public_name catala_web) + (modules catala_web) + (preprocess + (pps js_of_ocaml-ppx)) + (libraries catala js_of_ocaml)) diff --git a/src/dune b/src/dune index 65b5a0fd..f681b599 100644 --- a/src/dune +++ b/src/dune @@ -1,6 +1,6 @@ (executable (name catala) - (modes native js) + (modes native) (package catala) (modules catala) (public_name catala) From 92c0c58c9ba51dbe1aa8029744aa91ccf23fcab9 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sat, 26 Dec 2020 18:54:28 +0100 Subject: [PATCH 126/142] Cleaned script --- generate_website_assets.sh | 1 - src/catala/driver.ml | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/generate_website_assets.sh b/generate_website_assets.sh index faac657e..7b313211 100755 --- a/generate_website_assets.sh +++ b/generate_website_assets.sh @@ -15,7 +15,6 @@ scp examples/tutoriel_fr/tutoriel_fr.html $1/ scp grammar.html $1/ scp catala.html $1/ scp _build/default/src/catala_web/catala_web.bc.js $1/playground/ -scp bundle.js $1/playground/ scp examples/tutorial_en/tutorial_en.catala_en $1/playground/ scp examples/tutoriel_fr/tutoriel_fr.catala_fr $1/playground/ scp syntax_highlighting/en/ace/mode-catala_en.js $1/playground/ diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 610cb3ba..501bac7c 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -129,7 +129,7 @@ let driver (source_file : Pos.input_file) (debug : bool) (unstyled : bool) match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with | None -> Errors.raise_error - (Printf.sprintf "There is no scope %s inside the program." name) + (Printf.sprintf "There is no scope \"%s\" inside the program." name) | Some uid -> uid ) in Cli.debug_print "Desugaring..."; From 53e74bfcf81440b38000f277476bd99e163b50e4 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 27 Dec 2020 23:53:02 +0100 Subject: [PATCH 127/142] Added arrays to dcalc and scope --- src/catala/default_calculus/ast.ml | 8 +++++- src/catala/default_calculus/interpreter.ml | 17 +++++++++++-- src/catala/default_calculus/print.ml | 17 +++++++++++-- src/catala/default_calculus/typing.ml | 27 ++++++++++++++++++++- src/catala/scope_language/ast.ml | 3 +++ src/catala/scope_language/print.ml | 7 ++++++ src/catala/scope_language/scope_to_dcalc.ml | 6 ++++- 7 files changed, 78 insertions(+), 7 deletions(-) diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 78f8165c..ec135fff 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -26,6 +26,7 @@ type typ = | TTuple of typ Pos.marked list | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked + | TArray of typ Pos.marked type date = ODate.Unix.t @@ -48,6 +49,8 @@ type op_kind = | KDate | KDuration (** All ops don't have a Kdate and KDuration *) +type ternop = Fold + type binop = | And | Or @@ -61,6 +64,7 @@ type binop = | Gte of op_kind | Eq | Neq + | Map type log_entry = VarDef | BeginCall | EndCall @@ -69,8 +73,9 @@ type unop = | Minus of op_kind | ErrorOnEmpty | Log of log_entry * Utils.Uid.MarkedString.info list + | Length -type operator = Binop of binop | Unop of unop +type operator = Ternop of ternop | Binop of binop | Unop of unop (** The expressions use the {{:https://lepigre.fr/ocaml-bindlib/} Bindlib} library, based on higher-order abstract syntax*) @@ -84,6 +89,7 @@ type expr = (** The [MarkedString.info] is the former enum case name *) | EMatch of expr Pos.marked * (expr Pos.marked * Uid.MarkedString.info) list (** The [MarkedString.info] is the former enum case name *) + | EArray of expr Pos.marked list | ELit of lit | EAbs of Pos.t * (expr, expr Pos.marked) Bindlib.mbinder * typ Pos.marked list | EApp of expr Pos.marked * expr Pos.marked list diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index aff8b1c4..383e2a0c 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -36,10 +36,16 @@ let empty_thunked_term : Ast.expr Pos.marked = (** {1 Evaluation} *) -let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked list) : +let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked list) : A.expr Pos.marked = Pos.same_pos_as ( match (Pos.unmark op, List.map Pos.unmark args) with + | A.Ternop A.Fold, [ _; _; EArray es ] -> + Pos.unmark + (List.fold_left + (fun acc e' -> + evaluate_expr (Pos.same_pos_as (A.EApp (List.nth args 0, [ acc; e' ])) e')) + (List.nth args 1) es) | A.Binop A.And, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 && b2)) | A.Binop A.Or, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 || b2)) | A.Binop (A.Add KInt), [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LInt (Z.add i1 i2)) @@ -136,10 +142,16 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) + | A.Binop A.Map, [ _; A.EArray es ] -> + A.EArray + (List.map + (fun e' -> evaluate_expr (Pos.same_pos_as (A.EApp (List.nth args 0, [ e' ])) e')) + es) | A.Binop _, ([ ELit LEmptyError; _ ] | [ _; ELit LEmptyError ]) -> A.ELit LEmptyError | A.Unop (A.Minus KInt), [ ELit (LInt i) ] -> A.ELit (LInt (Z.sub Z.zero i)) | A.Unop (A.Minus KRat), [ ELit (LRat i) ] -> A.ELit (LRat (Q.sub Q.zero i)) | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) + | A.Unop A.Length, [ EArray es ] -> A.ELit (LInt (Z.of_int (List.length es))) | A.Unop A.ErrorOnEmpty, [ e' ] -> if e' = A.ELit LEmptyError then Errors.raise_spanned_error @@ -178,7 +190,7 @@ let evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked lis args ) ) op -let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = +and evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = match Pos.unmark e with | EVar _ -> Errors.raise_spanned_error @@ -282,6 +294,7 @@ let rec evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = "Expected a boolean literal for the result of this condition (should not happen if the \ term was well-typed)" (Pos.get_position cond) ) + | EArray es -> Pos.same_pos_as (A.EArray (List.map evaluate_expr es)) e | EAssert e' -> ( match Pos.unmark (evaluate_expr e') with | ELit (LBool true) -> Pos.same_pos_as (Ast.ELit LUnit) e' diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index e4c1c601..0ad08c29 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -16,7 +16,7 @@ module Pos = Utils.Pos open Ast let typ_needs_parens (e : typ Pos.marked) : bool = - match Pos.unmark e with TArrow _ -> true | _ -> false + match Pos.unmark e with TArrow _ | TArray _ -> true | _ -> false let format_tlit (fmt : Format.formatter) (l : typ_lit) : unit = match l with @@ -45,6 +45,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = ts | TArrow (t1, t2) -> Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 + | TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ t1 let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with @@ -111,6 +112,10 @@ let format_binop (fmt : Format.formatter) (op : binop Pos.marked) : unit = | Lte k -> Format.fprintf fmt "%s%a" "<=" format_op_kind k | Gt k -> Format.fprintf fmt "%s%a" ">" format_op_kind k | Gte k -> Format.fprintf fmt "%s%a" ">=" format_op_kind k + | Map -> Format.fprintf fmt "map" + +let format_ternop (fmt : Format.formatter) (op : ternop Pos.marked) : unit = + match Pos.unmark op with Fold -> Format.fprintf fmt "fold" let format_log_entry (fmt : Format.formatter) (entry : log_entry) : unit = Format.fprintf fmt "%s" @@ -130,7 +135,8 @@ let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) - infos ) + infos + | Length -> "length" ) let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ | EApp _ -> true | _ -> false @@ -156,6 +162,12 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = struct_field format_expr e | None -> Format.fprintf fmt "@[%a@]" format_expr e)) es + | EArray es -> + Format.fprintf fmt "[%a]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ";") + (fun fmt e -> Format.fprintf fmt "@[%a@]" format_expr e)) + es | ETupleAccess (e1, n, i) -> ( match i with | None -> Format.fprintf fmt "%a.%d" format_expr e1 n @@ -200,6 +212,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EIfThenElse (e1, e2, e3) -> Format.fprintf fmt "if@ @[%a@]@ then@ @[%a@]@ else@ @[%a@]" format_expr e1 format_expr e2 format_expr e3 + | EOp (Ternop op) -> Format.fprintf fmt "%a" format_ternop (op, Pos.no_pos) | EOp (Binop op) -> Format.fprintf fmt "%a" format_binop (op, Pos.no_pos) | EOp (Unop op) -> Format.fprintf fmt "%a" format_unop (op, Pos.no_pos) | EDefault (exceptions, just, cons) -> diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index c150ce95..e2b6e913 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -29,6 +29,7 @@ type typ = | TArrow of typ Pos.marked UnionFind.elem * typ Pos.marked UnionFind.elem | TTuple of typ Pos.marked UnionFind.elem list | TEnum of typ Pos.marked UnionFind.elem list + | TArray of typ Pos.marked UnionFind.elem | TAny let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = @@ -45,6 +46,7 @@ let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " + ") format_typ) ts | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 + | TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ t1 (** Raises an error if unification cannot be performed *) let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = @@ -93,8 +95,11 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = let dut = UnionFind.make (TLit TDuration, pos) in let dat = UnionFind.make (TLit TDate, pos) in let any = UnionFind.make (TAny, pos) in + let array_any = UnionFind.make (TArray any, pos) in + let any2 = UnionFind.make (TAny, pos) in let arr x y = UnionFind.make (TArrow (x, y), pos) in match Pos.unmark op with + | A.Ternop A.Fold -> arr (arr any2 (arr any any2)) (arr array_any any2) | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) | A.Binop (A.Add KInt | A.Sub KInt | A.Mult KInt | A.Div KInt) -> arr it (arr it it) | A.Binop (A.Add KRat | A.Sub KRat | A.Mult KRat | A.Div KRat) -> arr rt (arr rt rt) @@ -111,6 +116,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Binop (A.Lt KDuration | A.Lte KDuration | A.Gt KDuration | A.Gte KDuration) -> arr dut (arr dut bt) | A.Binop (A.Eq | A.Neq) -> arr any (arr any bt) + | A.Binop A.Map -> arr (arr any any2) (arr array_any any2) | A.Unop (A.Minus KInt) -> arr it it | A.Unop (A.Minus KRat) -> arr rt rt | A.Unop (A.Minus KMoney) -> arr mt mt @@ -118,6 +124,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Unop A.Not -> arr bt bt | A.Unop A.ErrorOnEmpty -> arr any any | A.Unop (A.Log _) -> arr any any + | A.Unop A.Length -> arr array_any it | Binop (Mult (KDate | KDuration)) | Binop (Div (KDate | KDuration)) | Unop (Minus KDate) -> Errors.raise_spanned_error "This operator is not available!" pos @@ -130,6 +137,7 @@ let rec ast_to_typ (ty : A.typ) : typ = UnionFind.make (Pos.map_under_mark ast_to_typ t2) ) | A.TTuple ts -> TTuple (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) | A.TEnum ts -> TEnum (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) + | A.TArray t -> TArray (UnionFind.make (Pos.map_under_mark ast_to_typ t)) let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = Pos.map_under_mark @@ -139,7 +147,8 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TEnum ts -> A.TEnum (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) - | TAny -> A.TLit A.TUnit) + | TAny -> A.TLit A.TUnit + | TArray t1 -> A.TArray (typ_to_ast t1)) (UnionFind.get (UnionFind.find ty)) (** {1 Double-directed typing} *) @@ -254,6 +263,14 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | EAssert e' -> typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); UnionFind.make (Pos.same_pos_as (TLit TUnit) e') + | EArray es -> + let cell_type = UnionFind.make (Pos.same_pos_as TAny e) in + List.iter + (fun e' -> + let t_e' = typecheck_expr_bottom_up env e' in + unify cell_type t_e') + es; + UnionFind.make (Pos.same_pos_as (TArray cell_type) e) (** Checks whether the expression can be typed with the provided type *) and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) @@ -383,6 +400,14 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | EAssert e' -> typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e')) + | EArray es -> + let cell_type = UnionFind.make (Pos.same_pos_as TAny e) in + List.iter + (fun e' -> + let t_e' = typecheck_expr_bottom_up env e' in + unify cell_type t_e') + es; + unify tau (UnionFind.make (Pos.same_pos_as (TArray cell_type) e)) (** {1 API} *) diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 17ef90e5..68e855a9 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -96,6 +96,7 @@ type expr = | EOp of Dcalc.Ast.operator | EDefault of expr Pos.marked list * expr Pos.marked * expr Pos.marked | EIfThenElse of expr Pos.marked * expr Pos.marked * expr Pos.marked + | EArray of expr Pos.marked list let rec locations_used (e : expr Pos.marked) : LocationSet.t = match Pos.unmark e with @@ -126,6 +127,8 @@ let rec locations_used (e : expr Pos.marked) : LocationSet.t = (fun acc except -> LocationSet.union (locations_used except) acc) (LocationSet.union (locations_used just) (locations_used cons)) excepts + | EArray es -> + List.fold_left (fun acc e' -> LocationSet.union acc (locations_used e')) LocationSet.empty es type rule = | Definition of location Pos.marked * typ Pos.marked * expr Pos.marked diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 3510fb6a..2210f769 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -104,6 +104,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EIfThenElse (e1, e2, e3) -> Format.fprintf fmt "if@ @[%a@]@ then@ @[%a@]@ else@ @[%a@]" format_expr e1 format_expr e2 format_expr e3 + | EOp (Ternop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_ternop (op, Pos.no_pos) | EOp (Binop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_binop (op, Pos.no_pos) | EOp (Unop op) -> Format.fprintf fmt "%a" Dcalc.Print.format_unop (op, Pos.no_pos) | EDefault (excepts, just, cons) -> @@ -113,3 +114,9 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = Format.fprintf fmt "@[⟨%a@ |@ %a ⊢ %a⟩@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) excepts format_expr just format_expr cons + | EArray es -> + Format.fprintf fmt "[%a]" + (Format.pp_print_list + ~pp_sep:(fun fmt () -> Format.fprintf fmt ";") + (fun fmt e -> Format.fprintf fmt "@[%a@]" format_expr e)) + es diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 33356632..e150c517 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -236,7 +236,11 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po Bindlib.box_apply3 (fun c t f -> Dcalc.Ast.EIfThenElse (c, t, f)) (translate_expr ctx cond) (translate_expr ctx et) (translate_expr ctx ef) - | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) ) + | EOp op -> Bindlib.box (Dcalc.Ast.EOp op) + | EArray es -> + Bindlib.box_apply + (fun es -> Dcalc.Ast.EArray es) + (Bindlib.box_list (List.map (translate_expr ctx) es)) ) let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) ((sigma_name, pos_sigma) : Utils.Uid.MarkedString.info) : From a37357bb56914a101383371a924a4b2656b0ce25 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 29 Dec 2020 22:26:10 +0100 Subject: [PATCH 128/142] Array type is beginning to work --- src/catala/catala_surface/ast.ml | 6 +- src/catala/catala_surface/desugaring.ml | 53 ++ src/catala/catala_surface/lexer.ml | 24 +- src/catala/catala_surface/lexer_en.ml | 13 +- src/catala/catala_surface/lexer_fr.ml | 13 +- src/catala/catala_surface/name_resolution.ml | 8 +- src/catala/catala_surface/parser.messages | 555 +++++++++--------- src/catala/catala_surface/parser.mly | 13 +- src/catala/catala_surface/parser_errors.ml | 253 ++++---- src/catala/default_calculus/ast.ml | 1 + src/catala/default_calculus/interpreter.ml | 60 +- src/catala/default_calculus/print.ml | 18 +- src/catala/default_calculus/typing.ml | 297 +++++----- src/catala/scope_language/ast.ml | 2 + src/catala/scope_language/dependency.ml | 3 +- src/catala/scope_language/print.ml | 2 + src/catala/scope_language/scope_to_dcalc.ml | 4 +- syntax_highlighting/en/ace/mode-catala_en.js | 2 +- .../en/atom/grammars/catala_en.cson | 2 +- syntax_highlighting/en/catala_en.iro | 2 +- syntax_highlighting/en/pygments/catala_en.py | 3 +- .../en/vscode/syntaxes/catalavs.xml | 2 +- syntax_highlighting/fr/ace/mode-catala_fr.js | 2 +- .../fr/atom/grammars/catala_fr.cson | 2 +- syntax_highlighting/fr/catala_fr.iro | 2 +- syntax_highlighting/fr/pygments/catala_fr.py | 3 +- .../fr/vscode/syntaxes/catalavs.xml | 2 +- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 2 +- .../nv/vscode/syntaxes/catalavs.xml | 2 +- tests/test_array/simple.catala | 18 + tests/test_array/simple.catala.A.out | 2 + tests/test_array/simple.catala.B.out | 3 + tests/test_bool/test_bool.catala | 4 +- tests/test_default/conflict.catala | 4 +- tests/test_default/conflict.catala.A.out | 8 +- tests/test_default/empty_with_rules.catala | 6 +- tests/test_func/func.catala | 4 +- tests/test_func/func.catala.S.out | 8 +- tests/test_money/no_mingle.catala.A.out | 24 - tests/test_scope/cycle_in_scope.catala | 8 +- tests/test_scope/cycle_in_scope.catala.A.out | 8 +- tests/test_scope/scope.catala | 8 +- tests/test_scope/scope.catala.A.out | 8 +- tests/test_scope/sub_scope.catala | 2 +- tests/test_scope/sub_sub_scope.catala | 6 +- tests/test_scope/sub_sub_scope.catala.B.out | 8 +- 48 files changed, 806 insertions(+), 678 deletions(-) create mode 100644 tests/test_array/simple.catala create mode 100644 tests/test_array/simple.catala.A.out create mode 100644 tests/test_array/simple.catala.B.out diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 131b2cbe..56ad1471 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -34,10 +34,7 @@ type primitive_typ = | Date | Named of constructor -type base_typ_data = - | Primitive of primitive_typ - | Collection of base_typ_data Pos.marked - | Optional of base_typ_data Pos.marked +type base_typ_data = Primitive of primitive_typ | Collection of base_typ_data Pos.marked type base_typ = Condition | Data of base_typ_data @@ -136,6 +133,7 @@ and expression = | EnumInject of constructor Pos.marked * expression Pos.marked option | EnumProject of expression Pos.marked * constructor Pos.marked | StructLit of constructor Pos.marked * (ident Pos.marked * expression Pos.marked) list + | ArrayLit of expression Pos.marked list | Ident of ident | Dotted of expression Pos.marked * ident Pos.marked (** Dotted is for both struct field projection and sub-scope variables *) diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index c554239e..b222499f 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -336,6 +336,59 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti (fun e1 cases_d -> (Scopelang.Ast.EMatch (e1, Option.get e_uid, cases_d), pos)) e1 (LiftEnumConstructorMap.lift_box cases_d) + | ArrayLit es -> + Bindlib.box_apply + (fun es -> (Scopelang.Ast.EArray es, pos)) + (Bindlib.box_list (List.map rec_helper es)) + | CollectionOp (op, param, collection, predicate) -> + let ctxt, param = Name_resolution.add_def_local_var ctxt param in + let collection = rec_helper collection in + let init = + match Pos.unmark op with + | Ast.Exists -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos) + | Ast.Forall -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), pos) + | _ -> + Name_resolution.raise_unsupported_feature "operator not supported" (Pos.get_position op) + in + let acc_var = Scopelang.Ast.Var.make ("acc", pos) in + let acc = Scopelang.Ast.make_var (acc_var, pos) in + let f_body = + match Pos.unmark op with + | Ast.Exists -> + Bindlib.box_apply2 + (fun predicate acc -> + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.Or), pos), [ acc; predicate ]), + pos )) + (translate_expr scope ctxt predicate) + acc + | Ast.Forall -> + Bindlib.box_apply2 + (fun predicate acc -> + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.And), pos), [ acc; predicate ]), + pos )) + (translate_expr scope ctxt predicate) + acc + | _ -> + Name_resolution.raise_unsupported_feature "operator not supported" (Pos.get_position op) + in + let f = + Bindlib.box_apply + (fun binder -> + ( Scopelang.Ast.EAbs + ( pos, + binder, + [ (Scopelang.Ast.TLit Dcalc.Ast.TBool, pos); (Scopelang.Ast.TAny, pos) ] ), + pos )) + (Bindlib.bind_mvar [| acc_var; param |] f_body) + in + Bindlib.box_apply3 + (fun f collection init -> + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Ternop Dcalc.Ast.Fold), pos), [ f; init; collection ]), + pos )) + f collection init | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented for this expression" pos diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index 8f297440..a656cbbf 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -53,12 +53,15 @@ let token_list_language_agnostic : (string * token) list = (")", RPAREN); ("{", LBRACKET); ("}", RBRACKET); + ("{", LSQUARE); + ("}", RSQUARE); ("+", PLUS); ("-", MINUS); ("*", MULT); ("/", DIV); ("|", VERTICAL); (":", COLON); + (";", SEMICOLON); ("--", ALT); ] @@ -67,7 +70,7 @@ let token_list_language_agnostic : (string * token) list = let token_list : (string * token) list = [ ("scope", SCOPE); - ("]", CONSEQUENCE); + ("|]", CONSEQUENCE); ("data", DATA); ("fun of", DEPENDS); ("new", DECLARATION); @@ -92,13 +95,12 @@ let token_list : (string * token) list = ("equals", DEFINED_AS); ("match", MATCH); ("with", WITH); - ("[", UNDER_CONDITION); + ("[|", UNDER_CONDITION); ("if", IF); ("then", THEN); ("else", ELSE); ("content", CONTENT); ("struct", STRUCT); - ("option", OPTIONAL); ("assert", ASSERTION); ("varies", VARIES); ("with parameter", WITH_V); @@ -222,7 +224,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "with" -> update_acc lexbuf; WITH - | "[" -> + | "[|" -> update_acc lexbuf; UNDER_CONDITION | "if" -> @@ -243,9 +245,6 @@ let rec lex_code (lexbuf : lexbuf) : token = | "struct" -> update_acc lexbuf; STRUCT - | "option" -> - update_acc lexbuf; - OPTIONAL | "assert" -> update_acc lexbuf; ASSERTION @@ -292,7 +291,7 @@ let rec lex_code (lexbuf : lexbuf) : token = | "not" -> update_acc lexbuf; NOT - | "]" -> + | "|]" -> update_acc lexbuf; CONSEQUENCE | "number" -> @@ -464,12 +463,21 @@ let rec lex_code (lexbuf : lexbuf) : token = | '}' -> update_acc lexbuf; RBRACKET + | '[' -> + update_acc lexbuf; + LSQUARE + | ']' -> + update_acc lexbuf; + RSQUARE | '|' -> update_acc lexbuf; VERTICAL | ':' -> update_acc lexbuf; COLON + | ';' -> + update_acc lexbuf; + SEMICOLON | "--" -> update_acc lexbuf; ALT diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 5bed98d7..2952626f 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -55,7 +55,6 @@ let token_list_en : (string * token) list = ("else", ELSE); ("content", CONTENT); ("structure", STRUCT); - ("optional", OPTIONAL); ("assertion", ASSERTION); ("varies", VARIES); ("with", WITH_V); @@ -197,9 +196,6 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "structure" -> L.update_acc lexbuf; STRUCT - | "optional" -> - L.update_acc lexbuf; - OPTIONAL | "assertion" -> L.update_acc lexbuf; ASSERTION @@ -421,12 +417,21 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | '}' -> L.update_acc lexbuf; RBRACKET + | '[' -> + L.update_acc lexbuf; + LSQUARE + | ']' -> + L.update_acc lexbuf; + RSQUARE | '|' -> L.update_acc lexbuf; VERTICAL | ':' -> L.update_acc lexbuf; COLON + | ';' -> + L.update_acc lexbuf; + SEMICOLON | "--" -> L.update_acc lexbuf; ALT diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index f132c356..4107bccd 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -53,7 +53,6 @@ let token_list_fr : (string * token) list = ("sinon", ELSE); ("contenu", CONTENT); ("structure", STRUCT); - ("optionnel", OPTIONAL); ("assertion", ASSERTION); ("varie", VARIES); ("avec", WITH_V); @@ -200,9 +199,6 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "structure" -> L.update_acc lexbuf; STRUCT - | "optionnel" -> - L.update_acc lexbuf; - OPTIONAL | "assertion" -> L.update_acc lexbuf; ASSERTION @@ -428,12 +424,21 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | '}' -> L.update_acc lexbuf; RBRACKET + | '[' -> + L.update_acc lexbuf; + LSQUARE + | ']' -> + L.update_acc lexbuf; + RSQUARE | '|' -> L.update_acc lexbuf; VERTICAL | ':' -> L.update_acc lexbuf; COLON + | ';' -> + L.update_acc lexbuf; + SEMICOLON | "--" -> L.update_acc lexbuf; ALT diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index 4ed47408..c47dcbc6 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -151,12 +151,14 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } (** Process a basic type (all types except function types) *) -let process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : +let rec process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : Scopelang.Ast.typ Pos.marked = match typ with | Ast.Condition -> (Scopelang.Ast.TLit TBool, typ_pos) - | Ast.Data (Ast.Collection _) -> raise_unsupported_feature "collection type" typ_pos - | Ast.Data (Ast.Optional _) -> raise_unsupported_feature "option type" typ_pos + | Ast.Data (Ast.Collection t) -> + ( Scopelang.Ast.TArray + (Pos.unmark (process_base_typ ctxt (Ast.Data (Pos.unmark t), Pos.get_position t))), + typ_pos ) | Ast.Data (Ast.Primitive prim) -> ( match prim with | Ast.Integer -> (Scopelang.Ast.TLit TInt, typ_pos) diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 15c1e058..6f6ef366 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE LAW_TEXT END_CODE ## -## Ends in an error in state: 323. +## Ends in an error in state: 327. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE option(law_text) . END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -12,7 +12,7 @@ expected a metadata-closing tag source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 322. +## Ends in an error in state: 326. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -72,7 +72,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 316. +## Ends in an error in state: 320. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -85,7 +85,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 311. +## Ends in an error in state: 315. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -97,7 +97,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 310. +## Ends in an error in state: 314. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -109,7 +109,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 309. +## Ends in an error in state: 313. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -121,7 +121,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 308. +## Ends in an error in state: 312. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -133,7 +133,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 307. +## Ends in an error in state: 311. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -145,7 +145,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 306. +## Ends in an error in state: 310. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -157,7 +157,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 301. +## Ends in an error in state: 305. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -169,7 +169,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 303. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -181,7 +181,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 302. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -193,7 +193,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 303. +## Ends in an error in state: 307. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -206,7 +206,7 @@ expected another scope context item or the end of the scope declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 296. +## Ends in an error in state: 300. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -218,7 +218,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 295. +## Ends in an error in state: 299. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -232,7 +232,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 294. +## Ends in an error in state: 298. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -246,7 +246,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 293. +## Ends in an error in state: 297. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -258,7 +258,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 292. +## Ends in an error in state: 296. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -270,7 +270,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 291. +## Ends in an error in state: 295. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 278. +## Ends in an error in state: 282. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -292,21 +292,10 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COL expected a new struct data, or another declaration or scope use -source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS OPTIONAL YEAR -## -## Ends in an error in state: 275. -## -## typ -> optional_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] -## -## The known suffix of the stack is as follows: -## optional_marked -## - -expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 290. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -318,7 +307,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 286. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -330,7 +319,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 281. +## Ends in an error in state: 285. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -342,7 +331,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 288. +## Ends in an error in state: 292. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -354,7 +343,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 263. +## Ends in an error in state: 270. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -366,7 +355,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 262. +## Ends in an error in state: 269. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -378,7 +367,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 261. +## Ends in an error in state: 268. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -390,7 +379,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 260. +## Ends in an error in state: 267. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -402,7 +391,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 259. +## Ends in an error in state: 266. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -414,7 +403,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 258. +## Ends in an error in state: 265. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -426,7 +415,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 257. +## Ends in an error in state: 264. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -440,7 +429,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 228. +## Ends in an error in state: 235. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -452,23 +441,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> CARDINAL -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 222, spurious reduction of production assertion_base -> expression -## In state 223, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 227, spurious reduction of production scope_item -> ASSERTION assertion +## In state 54, spurious reduction of production primitive_expression -> CARDINAL +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression +## In state 229, spurious reduction of production assertion_base -> expression +## In state 230, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 234, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 226. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -480,7 +469,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 218. +## Ends in an error in state: 225. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -491,15 +480,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 217. +## Ends in an error in state: 224. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -511,7 +500,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 221. +## Ends in an error in state: 228. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -523,9 +512,9 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 225. +## Ends in an error in state: 232. ## -## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## condition @@ -534,21 +523,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> CARDINAL -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 216, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 54, spurious reduction of production primitive_expression -> CARDINAL +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression +## In state 223, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 222. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -560,7 +549,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 205. +## Ends in an error in state: 212. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -571,15 +560,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 207. +## Ends in an error in state: 214. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -590,15 +579,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 206. +## Ends in an error in state: 213. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -610,7 +599,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 203. +## Ends in an error in state: 210. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -622,7 +611,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 202. +## Ends in an error in state: 209. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -634,7 +623,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 257. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -646,7 +635,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 248. +## Ends in an error in state: 255. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -658,7 +647,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 249. +## Ends in an error in state: 256. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -670,7 +659,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 247. +## Ends in an error in state: 254. ## ## definition -> option(label) option(exception_to) DEFINITION qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -681,15 +670,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 246. +## Ends in an error in state: 253. ## ## definition -> option(label) option(exception_to) DEFINITION . qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -701,7 +690,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION IDENT DEFINED_AS ## -## Ends in an error in state: 233. +## Ends in an error in state: 240. ## ## definition -> option(label) option(exception_to) . DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) option(exception_to) . RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -714,7 +703,7 @@ expected a rule or a definition after the exception declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION YEAR ## -## Ends in an error in state: 231. +## Ends in an error in state: 238. ## ## exception_to -> EXCEPTION . ident [ RULE DEFINITION ] ## @@ -726,7 +715,7 @@ expected the label to which the exception is referring back source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL IDENT DEFINED_AS ## -## Ends in an error in state: 230. +## Ends in an error in state: 237. ## ## definition -> option(label) . option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) . option(exception_to) RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -739,7 +728,7 @@ expected a rule or a definition after the label declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL YEAR ## -## Ends in an error in state: 200. +## Ends in an error in state: 207. ## ## label -> LABEL . ident [ RULE EXCEPTION DEFINITION ] ## @@ -751,7 +740,7 @@ expected the name of the label source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 213. +## Ends in an error in state: 220. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -763,7 +752,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 239. +## Ends in an error in state: 246. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -775,7 +764,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 235. +## Ends in an error in state: 242. ## ## rule -> option(label) option(exception_to) RULE rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -787,7 +776,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 242. +## Ends in an error in state: 249. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -799,7 +788,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 236. +## Ends in an error in state: 243. ## ## rule -> option(label) option(exception_to) RULE rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -811,7 +800,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 241. +## Ends in an error in state: 248. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -822,15 +811,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 212, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 204, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 212. +## Ends in an error in state: 219. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -843,7 +832,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 234. +## Ends in an error in state: 241. ## ## rule -> option(label) option(exception_to) RULE . rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -855,7 +844,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 206. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -867,10 +856,10 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 53. +## Ends in an error in state: 54. ## ## aggregate_func -> CARDINAL . [ FOR ] -## primitive_expression -> CARDINAL . [ WITH THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## primitive_expression -> CARDINAL . [ WITH THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CARDINAL @@ -880,11 +869,11 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 151. +## Ends in an error in state: 152. ## -## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT small_expression @@ -894,9 +883,9 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 150. +## Ends in an error in state: 151. ## -## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## CONTENT @@ -907,7 +896,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL ALT YEAR ## -## Ends in an error in state: 79. +## Ends in an error in state: 80. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] ## @@ -919,7 +908,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL THEN ## -## Ends in an error in state: 78. +## Ends in an error in state: 79. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RBRACKET ] ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] @@ -931,20 +920,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 53, spurious reduction of production primitive_expression -> CARDINAL -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 142, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 54, spurious reduction of production primitive_expression -> CARDINAL +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 143, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another structure field or the closing bracket source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON YEAR ## -## Ends in an error in state: 82. +## Ends in an error in state: 83. ## ## struct_content_field -> ident COLON . logical_expression [ RBRACKET ALT ] ## @@ -956,7 +945,7 @@ expected the expression for this struct field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT YEAR ## -## Ends in an error in state: 81. +## Ends in an error in state: 82. ## ## struct_content_field -> ident . COLON logical_expression [ RBRACKET ALT ] ## @@ -968,9 +957,9 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT YEAR ## -## Ends in an error in state: 77. +## Ends in an error in state: 78. ## -## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## LBRACKET ALT @@ -980,9 +969,9 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET YEAR ## -## Ends in an error in state: 76. +## Ends in an error in state: 77. ## -## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## LBRACKET @@ -992,9 +981,9 @@ expected structure fields introduced by -- source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 75. +## Ends in an error in state: 76. ## -## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## constructor @@ -1004,9 +993,9 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 166. +## Ends in an error in state: 167. ## -## expression -> exists_prefix . expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> exists_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## exists_prefix @@ -1016,9 +1005,9 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 172. +## Ends in an error in state: 173. ## -## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression SUCH @@ -1028,9 +1017,9 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 171. +## Ends in an error in state: 172. ## -## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression @@ -1039,16 +1028,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 170. +## Ends in an error in state: 171. ## -## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN @@ -1058,9 +1047,9 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 170. ## -## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident @@ -1070,9 +1059,9 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 168. +## Ends in an error in state: 169. ## -## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked @@ -1082,9 +1071,9 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 159. +## Ends in an error in state: 160. ## -## expression -> forall_prefix . expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> forall_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## forall_prefix @@ -1094,9 +1083,9 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 163. +## Ends in an error in state: 164. ## -## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN primitive_expression @@ -1105,16 +1094,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 162. +## Ends in an error in state: 163. ## -## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN @@ -1124,9 +1113,9 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 162. ## -## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident @@ -1136,9 +1125,9 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 161. ## -## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked @@ -1148,7 +1137,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 48. +## Ends in an error in state: 49. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -1160,9 +1149,9 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 174. +## Ends in an error in state: 175. ## -## expression -> IF expression . THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression . THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression @@ -1171,22 +1160,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 177. +## Ends in an error in state: 178. ## -## expression -> IF expression THEN expression ELSE . base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN expression ELSE . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN expression ELSE @@ -1196,9 +1185,9 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 176. +## Ends in an error in state: 177. ## -## expression -> IF expression THEN expression . ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN expression . ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN expression @@ -1207,22 +1196,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 175. +## Ends in an error in state: 176. ## -## expression -> IF expression THEN . expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF expression THEN . expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF expression THEN @@ -1232,9 +1221,9 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 46. +## Ends in an error in state: 47. ## -## expression -> IF . expression THEN expression ELSE base_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> IF . expression THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## IF @@ -1244,9 +1233,9 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 66. +## Ends in an error in state: 67. ## -## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## num_literal @@ -1256,9 +1245,9 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 179. +## Ends in an error in state: 180. ## -## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN expression @@ -1267,22 +1256,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 44. +## Ends in an error in state: 45. ## -## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## LPAREN @@ -1292,9 +1281,9 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 181. +## Ends in an error in state: 188. ## -## expression -> MATCH primitive_expression . WITH match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH primitive_expression . WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH primitive_expression @@ -1303,16 +1292,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 184. +## Ends in an error in state: 191. ## -## match_arms -> ALT match_arm . match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## match_arms -> ALT match_arm . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## ALT match_arm @@ -1321,22 +1310,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 141, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 188, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 142, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 195, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 187. +## Ends in an error in state: 194. ## -## match_arm -> constructor_binding COLON . logical_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## match_arm -> constructor_binding COLON . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## constructor_binding COLON @@ -1346,7 +1335,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 192. +## Ends in an error in state: 199. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1358,9 +1347,9 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 186. +## Ends in an error in state: 193. ## -## match_arm -> constructor_binding . COLON logical_expression [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## match_arm -> constructor_binding . COLON logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## constructor_binding @@ -1370,7 +1359,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 190. +## Ends in an error in state: 197. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1383,7 +1372,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 189. +## Ends in an error in state: 196. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1395,9 +1384,9 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 183. +## Ends in an error in state: 190. ## -## match_arms -> ALT . match_arm match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## match_arms -> ALT . match_arm match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## ALT @@ -1407,9 +1396,9 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 182. +## Ends in an error in state: 189. ## -## expression -> MATCH primitive_expression WITH . match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH primitive_expression WITH . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH primitive_expression WITH @@ -1421,7 +1410,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 43. ## -## expression -> MATCH . primitive_expression WITH match_arms [ THEN SCOPE RULE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] +## expression -> MATCH . primitive_expression WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## ## The known suffix of the stack is as follows: ## MATCH @@ -1431,9 +1420,9 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 54. +## Ends in an error in state: 55. ## -## sum_expression -> sum_unop . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> sum_unop . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_unop @@ -1443,9 +1432,9 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 140. +## Ends in an error in state: 141. ## -## logical_expression -> logical_unop . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> logical_unop . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## logical_unop @@ -1455,9 +1444,9 @@ expected an expression to take the negation of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR ## -## Ends in an error in state: 136. +## Ends in an error in state: 137. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression OF @@ -1467,9 +1456,9 @@ expected an expression to compute its aggregation over the set source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH ## -## Ends in an error in state: 135. +## Ends in an error in state: 136. ## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN primitive_expression @@ -1478,16 +1467,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression ## expected the "for" keyword and the expression to compute the aggregate source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR ## -## Ends in an error in state: 133. +## Ends in an error in state: 134. ## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident IN @@ -1497,9 +1486,9 @@ expected an expression standing for the set over which to compute the aggregatio source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR ## -## Ends in an error in state: 132. +## Ends in an error in state: 133. ## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR ident @@ -1509,9 +1498,9 @@ expected the "in" keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR ## -## Ends in an error in state: 131. +## Ends in an error in state: 132. ## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func FOR @@ -1521,9 +1510,9 @@ expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 130. +## Ends in an error in state: 131. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## aggregate_func @@ -1533,9 +1522,9 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 60. +## Ends in an error in state: 61. ## -## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression ARROW @@ -1545,7 +1534,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 198. +## Ends in an error in state: 205. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1556,24 +1545,24 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression -## In state 120, spurious reduction of production mult_expression -> base_expression -## In state 107, spurious reduction of production sum_expression -> mult_expression -## In state 83, spurious reduction of production compare_expression -> sum_expression -## In state 143, spurious reduction of production logical_expression -> compare_expression -## In state 158, spurious reduction of production expression -> logical_expression -## In state 196, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 197, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 121, spurious reduction of production mult_expression -> base_expression +## In state 108, spurious reduction of production sum_expression -> mult_expression +## In state 84, spurious reduction of production compare_expression -> sum_expression +## In state 144, spurious reduction of production logical_expression -> compare_expression +## In state 159, spurious reduction of production expression -> logical_expression +## In state 203, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 204, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 58. +## Ends in an error in state: 59. ## -## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression DOT @@ -1583,9 +1572,9 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 156. +## Ends in an error in state: 157. ## -## base_expression -> primitive_expression IN . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression IN . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression IN @@ -1595,10 +1584,10 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 120. +## Ends in an error in state: 121. ## -## mult_expression -> base_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## mult_expression -> base_expression . mult_op mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression . mult_op mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression @@ -1607,17 +1596,17 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression -## In state 62, spurious reduction of production base_expression -> primitive_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 63, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 127. +## Ends in an error in state: 128. ## -## mult_expression -> base_expression mult_op . mult_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## mult_expression -> base_expression mult_op . mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## base_expression mult_op @@ -1627,9 +1616,9 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 106. +## Ends in an error in state: 107. ## -## compare_expression -> sum_expression compare_op . compare_expression [ THEN SCOPE RULE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## compare_expression -> sum_expression compare_op . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## sum_expression compare_op @@ -1639,9 +1628,9 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 65. +## Ends in an error in state: 66. ## -## base_expression -> primitive_expression OF . base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression OF @@ -1651,9 +1640,9 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 146. +## Ends in an error in state: 147. ## -## logical_expression -> compare_expression logical_op . logical_expression [ THEN SCOPE RULE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] +## logical_expression -> compare_expression logical_op . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## ## The known suffix of the stack is as follows: ## compare_expression logical_op @@ -1663,9 +1652,9 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 118. +## Ends in an error in state: 119. ## -## sum_expression -> mult_expression sum_op . sum_expression [ THEN SCOPE RULE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## sum_expression -> mult_expression sum_op . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## mult_expression sum_op @@ -1675,12 +1664,12 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 62. +## Ends in an error in state: 63. ## -## base_expression -> primitive_expression . [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . OF base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . WITH constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## base_expression -> primitive_expression . IN base_expression [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . WITH constructor [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression . IN base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression @@ -1689,16 +1678,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 57, spurious reduction of production primitive_expression -> small_expression +## In state 58, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 63. +## Ends in an error in state: 64. ## -## base_expression -> primitive_expression WITH . constructor [ THEN SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## base_expression -> primitive_expression WITH . constructor [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## ## The known suffix of the stack is as follows: ## primitive_expression WITH @@ -1708,11 +1697,11 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 57. +## Ends in an error in state: 58. ## -## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] -## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## small_expression -> small_expression . DOT ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## small_expression @@ -1724,7 +1713,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 32. ## -## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV date_int . VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV date_int @@ -1736,7 +1725,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 31. ## -## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int DIV . date_int VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int DIV @@ -1748,7 +1737,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 30. ## -## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV date_int . DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV date_int @@ -1760,7 +1749,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 29. ## -## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int DIV . date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int DIV @@ -1772,7 +1761,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 28. ## -## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL date_int . DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL date_int @@ -1784,7 +1773,7 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## ## Ends in an error in state: 26. ## -## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SCOPE RULE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] +## literal -> VERTICAL . date_int DIV date_int DIV date_int VERTICAL [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## ## The known suffix of the stack is as follows: ## VERTICAL @@ -1830,7 +1819,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 332. +## Ends in an error in state: 336. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1842,7 +1831,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 337. +## Ends in an error in state: 341. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1854,7 +1843,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 331. +## Ends in an error in state: 335. ## ## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1866,7 +1855,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 326. +## Ends in an error in state: 330. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## @@ -1878,7 +1867,7 @@ expected an article title, another heading or some text source_file_or_master: LAW_TEXT YEAR ## -## Ends in an error in state: 341. +## Ends in an error in state: 345. ## ## list(law_intermediate_text) -> law_intermediate_text . list(law_intermediate_text) [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index acd797d1..16fb76a3 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -48,7 +48,7 @@ %token LESSER_DATE GREATER_DATE LESSER_EQUAL_DATE GREATER_EQUAL_DATE %token LESSER_DURATION GREATER_DURATION LESSER_EQUAL_DURATION GREATER_EQUAL_DURATION %token EXISTS IN SUCH THAT NOW -%token DOT AND OR LPAREN RPAREN OPTIONAL EQUAL +%token DOT AND OR LPAREN RPAREN EQUAL %token CARDINAL ASSERTION FIXED BY YEAR MONTH DAY %token PLUS MINUS MULT DIV %token PLUSDEC MINUSDEC MULTDEC DIVDEC @@ -62,7 +62,7 @@ %token CONTEXT ENUM ELSE DATE SUM %token BEGIN_METADATA END_METADATA MONEY DECIMAL %token UNDER_CONDITION CONSEQUENCE LBRACKET RBRACKET -%token LABEL EXCEPTION +%token LABEL EXCEPTION LSQUARE RSQUARE SEMICOLON %type source_file_or_master @@ -86,18 +86,12 @@ typ_base: collection_marked: | COLLECTION { $sloc } -optional_marked: -| OPTIONAL { $sloc } - typ: | t = typ_base { let t, loc = t in (Primitive t, loc) } | collection_marked t = typ { - (Optional t, $sloc) -} -| optional_marked t = typ { (Collection t, $sloc) } @@ -150,6 +144,9 @@ primitive_expression: | e = struct_or_enum_inject { e } +| LSQUARE l = separated_list(SEMICOLON, expression) RSQUARE { + (ArrayLit l, $sloc) +} num_literal: | d = INT_LITERAL { (Int d, $sloc) } diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 5cb12e2d..f7fe0ed8 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -13,11 +13,11 @@ let message s = "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" | 8 -> "expected some text, another heading or a law article\n" - | 341 -> "expected a heading, an article title or some text\n" - | 326 -> "expected an article title, another heading or some text\n" - | 331 -> "expected a code block, a metadata block, more law text or a heading\n" - | 337 -> "expected a code block, a metadata block, more law text or a heading\n" - | 332 -> "expected a declaration or a scope use\n" + | 345 -> "expected a heading, an article title or some text\n" + | 330 -> "expected an article title, another heading or some text\n" + | 335 -> "expected a code block, a metadata block, more law text or a heading\n" + | 341 -> "expected a code block, a metadata block, more law text or a heading\n" + | 336 -> "expected a declaration or a scope use\n" | 22 -> "expected the name of the scope you want to use\n" | 24 -> "expected a scope use precondition or a colon\n" | 25 -> "expected an expression which will act as the condition\n" @@ -27,145 +27,144 @@ let message s = | 30 -> "expected a \"/\"\n" | 31 -> "expected the third component of the date literal\n" | 32 -> "expected a delimiter to finish the date literal\n" - | 57 -> "expected an operator to compose the expression on the left with\n" - | 63 -> "expected an enum constructor to test if the expression on the left\n" - | 62 -> "expected an operator to compose the expression on the left with\n" - | 118 -> "expected an expression on the right side of the sum or minus operator\n" - | 146 -> "expected an expression on the right side of the logical operator\n" - | 65 -> "expected an expression for the argument of this function call\n" - | 106 -> "expected an expression on the right side of the comparison operator\n" - | 127 -> "expected an expression on the right side of the multiplication or division operator\n" - | 120 -> "expected an operator to compose the expression on the left\n" - | 156 -> "expected an expression standing for the set you want to test for membership\n" - | 58 -> "expected an identifier standing for a struct field or a subscope name\n" - | 198 -> "expected a colon after the scope use precondition\n" - | 60 -> "expected a constructor, to get the payload of this enum case\n" - | 130 -> "expected the \"for\" keyword to spell the aggregation\n" - | 131 -> "expected an identifier for the aggregation bound variable\n" - | 132 -> "expected the \"in\" keyword\n" - | 133 -> + | 58 -> "expected an operator to compose the expression on the left with\n" + | 64 -> "expected an enum constructor to test if the expression on the left\n" + | 63 -> "expected an operator to compose the expression on the left with\n" + | 119 -> "expected an expression on the right side of the sum or minus operator\n" + | 147 -> "expected an expression on the right side of the logical operator\n" + | 66 -> "expected an expression for the argument of this function call\n" + | 107 -> "expected an expression on the right side of the comparison operator\n" + | 128 -> "expected an expression on the right side of the multiplication or division operator\n" + | 121 -> "expected an operator to compose the expression on the left\n" + | 157 -> "expected an expression standing for the set you want to test for membership\n" + | 59 -> "expected an identifier standing for a struct field or a subscope name\n" + | 205 -> "expected a colon after the scope use precondition\n" + | 61 -> "expected a constructor, to get the payload of this enum case\n" + | 131 -> "expected the \"for\" keyword to spell the aggregation\n" + | 132 -> "expected an identifier for the aggregation bound variable\n" + | 133 -> "expected the \"in\" keyword\n" + | 134 -> "expected an expression standing for the set over which to compute the aggregation operation\n" - | 135 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 136 -> "expected an expression to compute its aggregation over the set\n" - | 140 -> "expected an expression to take the negation of\n" - | 54 -> "expected an expression to take the opposite of\n" + | 136 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" + | 137 -> "expected an expression to compute its aggregation over the set\n" + | 141 -> "expected an expression to take the negation of\n" + | 55 -> "expected an expression to take the opposite of\n" | 43 -> "expected an expression to match with\n" - | 182 -> "expected a pattern matching case\n" - | 183 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 189 -> + | 189 -> "expected a pattern matching case\n" + | 190 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 196 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 190 -> "expected an identifier for this enum case binding\n" - | 186 -> "expected a colon and then the expression for this matching case\n" - | 192 -> "expected a colon or a binding for the enum constructor payload\n" - | 187 -> "expected an expression for this pattern matching case\n" - | 184 -> + | 197 -> "expected an identifier for this enum case binding\n" + | 193 -> "expected a colon and then the expression for this matching case\n" + | 199 -> "expected a colon or a binding for the enum constructor payload\n" + | 194 -> "expected an expression for this pattern matching case\n" + | 191 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 181 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 44 -> "expected an expression inside the parenthesis\n" - | 179 -> "unmatched parenthesis that should have been closed by here\n" - | 66 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 46 -> "expected an expression for the test of the conditional\n" - | 175 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 176 -> + | 188 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 45 -> "expected an expression inside the parenthesis\n" + | 180 -> "unmatched parenthesis that should have been closed by here\n" + | 67 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 47 -> "expected an expression for the test of the conditional\n" + | 176 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 177 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 177 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 174 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 48 -> + | 178 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 175 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 49 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 160 -> "expected an identifier for the bound variable of the universal test\n" - | 161 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 162 -> "expected the expression designating the set on which to perform the universal test\n" - | 163 -> "expected the \"we have\" keyword for this universal test\n" - | 159 -> "expected an expression for the universal test\n" - | 168 -> "expected an identifier that will designate the existential witness for the test\n" - | 169 -> "expected the \"in\" keyword to continue this existential test\n" - | 170 -> "expected an expression that designates the set subject to the existential test\n" - | 171 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 172 -> "expected a keyword to complete the \"such that\" construction\n" - | 166 -> "expected an expression for the existential test\n" - | 75 -> + | 161 -> "expected an identifier for the bound variable of the universal test\n" + | 162 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 163 -> "expected the expression designating the set on which to perform the universal test\n" + | 164 -> "expected the \"we have\" keyword for this universal test\n" + | 160 -> "expected an expression for the universal test\n" + | 169 -> "expected an identifier that will designate the existential witness for the test\n" + | 170 -> "expected the \"in\" keyword to continue this existential test\n" + | 171 -> "expected an expression that designates the set subject to the existential test\n" + | 172 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 173 -> "expected a keyword to complete the \"such that\" construction\n" + | 167 -> "expected an expression for the existential test\n" + | 76 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 76 -> "expected structure fields introduced by --\n" - | 77 -> "expected the name of the structure field\n" - | 81 -> "expected a colon\n" - | 82 -> "expected the expression for this struct field\n" - | 78 -> "expected another structure field or the closing bracket\n" - | 79 -> "expected the name of the structure field\n" - | 150 -> "expected an expression for the content of this enum case\n" - | 151 -> + | 77 -> "expected structure fields introduced by --\n" + | 78 -> "expected the name of the structure field\n" + | 82 -> "expected a colon\n" + | 83 -> "expected the expression for this struct field\n" + | 79 -> "expected another structure field or the closing bracket\n" + | 80 -> "expected the name of the structure field\n" + | 151 -> "expected an expression for the content of this enum case\n" + | 152 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 53 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 199 -> "expected a scope use item: a rule, definition or assertion\n" - | 234 -> "expected the name of the variable subject to the rule\n" - | 212 -> + | 54 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 206 -> "expected a scope use item: a rule, definition or assertion\n" + | 241 -> "expected the name of the variable subject to the rule\n" + | 219 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 241 -> "expected a condition or a consequence for this rule\n" - | 236 -> "expected filled or not filled for a rule consequence\n" - | 242 -> "expected the name of the parameter for this dependent variable \n" - | 235 -> "expected the expression of the rule\n" - | 239 -> "expected the filled keyword the this rule \n" - | 213 -> "expected a struct field or a sub-scope context item after the dot\n" - | 200 -> "expected the name of the label\n" - | 230 -> "expected a rule or a definition after the label declaration\n" - | 231 -> "expected the label to which the exception is referring back\n" - | 233 -> "expected a rule or a definition after the exception declaration\n" - | 246 -> "expected the name of the variable you want to define\n" - | 247 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 249 -> "expected an expression for the consequence of this definition under condition\n" - | 248 -> + | 248 -> "expected a condition or a consequence for this rule\n" + | 243 -> "expected filled or not filled for a rule consequence\n" + | 249 -> "expected the name of the parameter for this dependent variable \n" + | 242 -> "expected the expression of the rule\n" + | 246 -> "expected the filled keyword the this rule \n" + | 220 -> "expected a struct field or a sub-scope context item after the dot\n" + | 207 -> "expected the name of the label\n" + | 237 -> "expected a rule or a definition after the label declaration\n" + | 238 -> "expected the label to which the exception is referring back\n" + | 240 -> "expected a rule or a definition after the exception declaration\n" + | 253 -> "expected the name of the variable you want to define\n" + | 254 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 256 -> "expected an expression for the consequence of this definition under condition\n" + | 255 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 250 -> "expected an expression for the definition\n" - | 202 -> "expected an expression that shoud be asserted during execution\n" - | 203 -> "expecting the name of the varying variable\n" - | 206 -> "the variable varies with an expression that was expected here\n" - | 207 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 205 -> "expected an indication about what this variable varies with\n" - | 215 -> "expected an expression for this condition\n" - | 225 -> "expected a consequence for this definition under condition\n" - | 221 -> "expected an expression for this definition under condition\n" - | 217 -> "expected the name of the variable that should be fixed\n" - | 218 -> "expected the legislative text by which the value of the variable is fixed\n" - | 219 -> "expected the legislative text by which the value of the variable is fixed\n" - | 228 -> "expected a new scope use item \n" - | 257 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 258 -> "expected the struct name\n" - | 259 -> "expected a colon\n" - | 260 -> "expected struct data or condition\n" - | 261 -> "expected the name of this struct data \n" - | 262 -> "expected the type of this struct data, introduced by the content keyword\n" - | 263 -> "expected the type of this struct data\n" - | 288 -> "expected the name of this struct condition\n" - | 281 -> "expected a new struct data, or another declaration or scope use\n" - | 282 -> "expected the type of the parameter of this struct data function\n" - | 286 -> "expected a new struct data, or another declaration or scope use\n" - | 275 -> "expected a new struct data, or another declaration or scope use\n" - | 278 -> "expected a new struct data, or another declaration or scope use\n" - | 291 -> "expected the name of the scope you are declaring\n" - | 292 -> "expected a colon followed by the list of context items of this scope\n" - | 293 -> "expected a context item introduced by \"context\"\n" - | 294 -> "expected the name of this new context item\n" - | 295 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 296 -> "expected the name of the subscope for this context item\n" - | 303 -> "expected another scope context item or the end of the scope declaration\n" - | 298 -> "expected the type of this context item\n" - | 299 -> "expected the next context item or a dependency declaration for this item\n" - | 301 -> "expected the next context item or a dependency declaration for this item\n" - | 306 -> "expected the name of your enum\n" - | 307 -> "expected a colon\n" - | 308 -> "expected an enum case\n" - | 309 -> "expected the name of an enum case \n" - | 310 -> "expected a payload for your enum case, or another case or declaration \n" - | 311 -> "expected a content type\n" - | 316 -> "expected another enum case, or a new declaration or scope use\n" + | 257 -> "expected an expression for the definition\n" + | 209 -> "expected an expression that shoud be asserted during execution\n" + | 210 -> "expecting the name of the varying variable\n" + | 213 -> "the variable varies with an expression that was expected here\n" + | 214 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 212 -> "expected an indication about what this variable varies with\n" + | 222 -> "expected an expression for this condition\n" + | 232 -> "expected a consequence for this definition under condition\n" + | 228 -> "expected an expression for this definition under condition\n" + | 224 -> "expected the name of the variable that should be fixed\n" + | 225 -> "expected the legislative text by which the value of the variable is fixed\n" + | 226 -> "expected the legislative text by which the value of the variable is fixed\n" + | 235 -> "expected a new scope use item \n" + | 264 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 265 -> "expected the struct name\n" + | 266 -> "expected a colon\n" + | 267 -> "expected struct data or condition\n" + | 268 -> "expected the name of this struct data \n" + | 269 -> "expected the type of this struct data, introduced by the content keyword\n" + | 270 -> "expected the type of this struct data\n" + | 292 -> "expected the name of this struct condition\n" + | 285 -> "expected a new struct data, or another declaration or scope use\n" + | 286 -> "expected the type of the parameter of this struct data function\n" + | 290 -> "expected a new struct data, or another declaration or scope use\n" + | 282 -> "expected a new struct data, or another declaration or scope use\n" + | 295 -> "expected the name of the scope you are declaring\n" + | 296 -> "expected a colon followed by the list of context items of this scope\n" + | 297 -> "expected a context item introduced by \"context\"\n" + | 298 -> "expected the name of this new context item\n" + | 299 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 300 -> "expected the name of the subscope for this context item\n" + | 307 -> "expected another scope context item or the end of the scope declaration\n" + | 302 -> "expected the type of this context item\n" + | 303 -> "expected the next context item or a dependency declaration for this item\n" + | 305 -> "expected the next context item or a dependency declaration for this item\n" + | 310 -> "expected the name of your enum\n" + | 311 -> "expected a colon\n" + | 312 -> "expected an enum case\n" + | 313 -> "expected the name of an enum case \n" + | 314 -> "expected a payload for your enum case, or another case or declaration \n" + | 315 -> "expected a content type\n" + | 320 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" | 19 -> "expected some text or the beginning of a code section\n" | 20 -> "expected a declaration or a scope use\n" | 21 -> "should not happen\n" - | 322 -> "expected a metadata-closing tag\n" - | 323 -> "expected a metadata-closing tag\n" + | 326 -> "expected a metadata-closing tag\n" + | 327 -> "expected a metadata-closing tag\n" | _ -> raise Not_found diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index ec135fff..2e4a77a7 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -27,6 +27,7 @@ type typ = | TEnum of typ Pos.marked list | TArrow of typ Pos.marked * typ Pos.marked | TArray of typ Pos.marked + | TAny type date = ODate.Unix.t diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 383e2a0c..5e5b5ef7 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -34,13 +34,22 @@ let empty_thunked_term : Ast.expr Pos.marked = [ (Ast.TLit Ast.TUnit, Pos.no_pos) ] Pos.no_pos) +let rec type_eq (t1 : A.typ Pos.marked) (t2 : A.typ Pos.marked) : bool = + match (Pos.unmark t1, Pos.unmark t2) with + | A.TLit tl1, A.TLit tl2 -> tl1 = tl2 + | A.TTuple ts1, A.TTuple ts2 | A.TEnum ts1, A.TEnum ts2 -> ( + try List.for_all2 type_eq ts1 ts2 with Invalid_argument _ -> false ) + | A.TArray t1, A.TArray t2 -> type_eq t1 t2 + | A.TArrow (t11, t12), A.TArrow (t21, t22) -> type_eq t11 t12 && type_eq t21 t22 + | _, _ -> false + (** {1 Evaluation} *) let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked list) : A.expr Pos.marked = Pos.same_pos_as ( match (Pos.unmark op, List.map Pos.unmark args) with - | A.Ternop A.Fold, [ _; _; EArray es ] -> + | A.Ternop A.Fold, [ _f; _init; EArray es ] -> Pos.unmark (List.fold_left (fun acc e' -> @@ -133,15 +142,46 @@ let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked | A.Binop A.Eq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 = i2)) | A.Binop A.Eq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 = b2)) - | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing functions return false *) - | A.Binop A.Neq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 <> i2)) - | A.Binop A.Neq, [ ELit (LDate i1); ELit (LDate i2) ] -> - A.ELit (LBool (ODate.Unix.compare i1 i2 <> 0)) - | A.Binop A.Neq, [ ELit (LMoney i1); ELit (LMoney i2) ] -> A.ELit (LBool (i1 <> i2)) - | A.Binop A.Neq, [ ELit (LRat i1); ELit (LRat i2) ] -> A.ELit (LBool Q.(i1 <> i2)) - | A.Binop A.Neq, [ ELit (LInt i1); ELit (LInt i2) ] -> A.ELit (LBool (i1 <> i2)) - | A.Binop A.Neq, [ ELit (LBool b1); ELit (LBool b2) ] -> A.ELit (LBool (b1 <> b2)) - | A.Binop A.Neq, [ _; _ ] -> A.ELit (LBool true) + | A.Binop A.Eq, [ EArray es1; EArray es2 ] -> + A.ELit + (LBool + ( try + List.for_all2 + (fun e1 e2 -> + match Pos.unmark (evaluate_operator op [ e1; e2 ]) with + | A.ELit (LBool b) -> b + | _ -> assert false + (* should not happen *)) + es1 es2 + with Invalid_argument _ -> false )) + | A.Binop A.Eq, [ ETuple es1; ETuple es2 ] -> + A.ELit + (LBool + ( try + List.for_all2 + (fun (e1, _) (e2, _) -> + match Pos.unmark (evaluate_operator op [ e1; e2 ]) with + | A.ELit (LBool b) -> b + | _ -> assert false + (* should not happen *)) + es1 es2 + with Invalid_argument _ -> false )) + | A.Binop A.Eq, [ EInj (e1, i1, _, ts1); EInj (e2, i2, _, ts2) ] -> + A.ELit + (LBool + ( try + List.for_all2 type_eq ts1 ts2 && i1 == i2 + && + match Pos.unmark (evaluate_operator op [ e1; e2 ]) with + | A.ELit (LBool b) -> b + | _ -> assert false + (* should not happen *) + with Invalid_argument _ -> false )) + | A.Binop A.Eq, [ _; _ ] -> A.ELit (LBool false) (* comparing anything else return false *) + | A.Binop A.Neq, [ _; _ ] -> ( + match Pos.unmark (evaluate_operator (Pos.same_pos_as (A.Binop A.Eq) op) args) with + | A.ELit (A.LBool b) -> A.ELit (A.LBool (not b)) + | _ -> assert false (*should not happen *) ) | A.Binop A.Map, [ _; A.EArray es ] -> A.EArray (List.map diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 0ad08c29..69bf375e 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -46,6 +46,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = | TArrow (t1, t2) -> Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 | TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ t1 + | TAny -> Format.fprintf fmt "any" let format_lit (fmt : Format.formatter) (l : lit Pos.marked) : unit = match Pos.unmark l with @@ -165,7 +166,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EArray es -> Format.fprintf fmt "[%a]" (Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt ";") + ~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ") (fun fmt e -> Format.fprintf fmt "@[%a@]" format_expr e)) es | ETupleAccess (e1, n, i) -> ( @@ -198,15 +199,16 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = Format.fprintf fmt "@[λ@ %a@ →@ %a@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") - (fun fmt (x, tau) -> Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau)) + (fun fmt (x, tau) -> + Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau)) xs_tau format_expr body | EApp ((EOp (Binop op), _), [ arg1; arg2 ]) -> - Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 format_binop (op, Pos.no_pos) - format_with_parens arg2 + Format.fprintf fmt "@[%a@ %a@ %a@]" format_with_parens arg1 format_binop + (op, Pos.no_pos) format_with_parens arg2 | EApp ((EOp (Unop op), _), [ arg1 ]) -> - Format.fprintf fmt "@[%a@ %a@]" format_unop (op, Pos.no_pos) format_with_parens arg1 + Format.fprintf fmt "@[%a@ %a@]" format_unop (op, Pos.no_pos) format_with_parens arg1 | EApp (f, args) -> - Format.fprintf fmt "@[%a@ %a@]" format_expr f + Format.fprintf fmt "@[%a@ %a@]" format_expr f (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") format_with_parens) args | EIfThenElse (e1, e2, e3) -> @@ -217,9 +219,9 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EOp (Unop op) -> Format.fprintf fmt "%a" format_unop (op, Pos.no_pos) | EDefault (exceptions, just, cons) -> if List.length exceptions = 0 then - Format.fprintf fmt "@[⟨%a ⊢ %a⟩@]" format_expr just format_expr cons + Format.fprintf fmt "@[⟨%a@ ⊢@ %a⟩@]" format_expr just format_expr cons else - Format.fprintf fmt "@[⟨%a@ |@ %a ⊢ %a ⟩@]" + Format.fprintf fmt "@[⟨%a@ |@ @[%a ⊢ %a@]@ ⟩@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) exceptions format_expr just format_expr cons | EAssert e' -> Format.fprintf fmt "@[assert@ (%a)@]" format_expr e' diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index e2b6e913..f0194527 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -22,6 +22,15 @@ module Cli = Utils.Cli (** {1 Types and unification} *) +module Any = + Utils.Uid.Make + (struct + type info = unit + + let format_info fmt () = Format.fprintf fmt "any" + end) + () + (** We do not reuse {!type: Dcalc.Ast.typ} because we have to include a new [TAny] variant. Indeed, error terms can have any type and this has to be captured by the type sytem. *) type typ = @@ -30,23 +39,32 @@ type typ = | TTuple of typ Pos.marked UnionFind.elem list | TEnum of typ Pos.marked UnionFind.elem list | TArray of typ Pos.marked UnionFind.elem - | TAny + | TAny of Any.t -let rec format_typ (fmt : Format.formatter) (ty : typ Pos.marked UnionFind.elem) : unit = - let ty_repr = UnionFind.get (UnionFind.find ty) in - match Pos.unmark ty_repr with +let typ_needs_parens (t : typ Pos.marked UnionFind.elem) : bool = + let t = UnionFind.get (UnionFind.find t) in + match Pos.unmark t with TArrow _ | TArray _ -> true | _ -> false + +let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked UnionFind.elem) : unit = + let format_typ_with_parens (fmt : Format.formatter) (t : typ Pos.marked UnionFind.elem) = + if typ_needs_parens t then Format.fprintf fmt "(%a)" format_typ t + else Format.fprintf fmt "%a" format_typ t + in + let typ = UnionFind.get (UnionFind.find typ) in + match Pos.unmark typ with | TLit l -> Format.fprintf fmt "%a" Print.format_tlit l - | TAny -> Format.fprintf fmt "any type" | TTuple ts -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " * ") format_typ) + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " *@ ") format_typ) ts | TEnum ts -> Format.fprintf fmt "(%a)" - (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " + ") format_typ) + (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt " +@ ") format_typ) ts - | TArrow (t1, t2) -> Format.fprintf fmt "%a → %a" format_typ t1 format_typ t2 + | TArrow (t1, t2) -> + Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 | TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ t1 + | TAny d -> Format.fprintf fmt "any[%d]" (Any.hash d) (** Raises an error if unification cannot be performed *) let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = @@ -55,21 +73,14 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin let t2_repr = UnionFind.get (UnionFind.find t2) in match (t1_repr, t2_repr) with | (TLit tl1, _), (TLit tl2, _) when tl1 = tl2 -> () - | (TArrow (t11, t12), t1_pos), (TArrow (t21, t22), t2_pos) -> ( - try - unify t11 t21; - unify t12 t22 - with Errors.StructuredError (msg, err_pos) -> - Errors.raise_multispanned_error msg - ( err_pos - @ [ - (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); - (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); - ] ) ) + | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> + unify t11 t21; + unify t12 t22 | (TTuple ts1, _), (TTuple ts2, _) -> List.iter2 unify ts1 ts2 | (TEnum ts1, _), (TEnum ts2, _) -> List.iter2 unify ts1 ts2 - | (TAny, _), (TAny, _) -> ignore (UnionFind.union t1 t2) - | (TAny, _), t_repr | t_repr, (TAny, _) -> + | (TArray t1', _), (TArray t2', _) -> unify t1' t2' + | (TAny _, _), (TAny _, _) -> ignore (UnionFind.union t1 t2) + | (TAny _, _), t_repr | t_repr, (TAny _, _) -> let t_union = UnionFind.union t1 t2 in ignore (UnionFind.set t_union t_repr) | (_, t1_pos), (_, t2_pos) -> @@ -94,12 +105,12 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = let mt = UnionFind.make (TLit TMoney, pos) in let dut = UnionFind.make (TLit TDuration, pos) in let dat = UnionFind.make (TLit TDate, pos) in - let any = UnionFind.make (TAny, pos) in + let any = UnionFind.make (TAny (Any.fresh ()), pos) in let array_any = UnionFind.make (TArray any, pos) in - let any2 = UnionFind.make (TAny, pos) in + let any2 = UnionFind.make (TAny (Any.fresh ()), pos) in let arr x y = UnionFind.make (TArrow (x, y), pos) in match Pos.unmark op with - | A.Ternop A.Fold -> arr (arr any2 (arr any any2)) (arr array_any any2) + | A.Ternop A.Fold -> arr (arr any2 (arr any any2)) (arr any2 (arr array_any any2)) | A.Binop (A.And | A.Or) -> arr bt (arr bt bt) | A.Binop (A.Add KInt | A.Sub KInt | A.Mult KInt | A.Div KInt) -> arr it (arr it it) | A.Binop (A.Add KRat | A.Sub KRat | A.Mult KRat | A.Div KRat) -> arr rt (arr rt rt) @@ -138,6 +149,7 @@ let rec ast_to_typ (ty : A.typ) : typ = | A.TTuple ts -> TTuple (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) | A.TEnum ts -> TEnum (List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts) | A.TArray t -> TArray (UnionFind.make (Pos.map_under_mark ast_to_typ t)) + | A.TAny -> TAny (Any.fresh ()) let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = Pos.map_under_mark @@ -147,7 +159,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = | TTuple ts -> A.TTuple (List.map typ_to_ast ts) | TEnum ts -> A.TEnum (List.map typ_to_ast ts) | TArrow (t1, t2) -> A.TArrow (typ_to_ast t1, typ_to_ast t2) - | TAny -> A.TLit A.TUnit + | TAny _ -> A.TAny | TArray t1 -> A.TArray (typ_to_ast t1)) (UnionFind.get (UnionFind.find ty)) @@ -158,123 +170,130 @@ type env = typ Pos.marked A.VarMap.t (** Infers the most permissive type from an expression *) let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem = - match Pos.unmark e with - | EVar v -> ( - match A.VarMap.find_opt (Pos.unmark v) env with - | Some t -> UnionFind.make t - | None -> - Errors.raise_spanned_error "Variable not found in the current context" - (Pos.get_position e) ) - | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as (TLit TBool) e) - | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as (TLit TInt) e) - | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as (TLit TRat) e) - | ELit (LMoney _) -> UnionFind.make (Pos.same_pos_as (TLit TMoney) e) - | ELit (LDate _) -> UnionFind.make (Pos.same_pos_as (TLit TDate) e) - | ELit (LDuration _) -> UnionFind.make (Pos.same_pos_as (TLit TDuration) e) - | ELit LUnit -> UnionFind.make (Pos.same_pos_as (TLit TUnit) e) - | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as TAny e) - | ETuple es -> - let ts = List.map (fun (e, _) -> typecheck_expr_bottom_up env e) es in - UnionFind.make (Pos.same_pos_as (TTuple ts) e) - | ETupleAccess (e1, n, _) -> ( - let t1 = typecheck_expr_bottom_up env e1 in - match Pos.unmark (UnionFind.get (UnionFind.find t1)) with - | TTuple ts -> ( + let out = + match Pos.unmark e with + | EVar v -> ( + match A.VarMap.find_opt (Pos.unmark v) env with + | Some t -> UnionFind.make t + | None -> + Errors.raise_spanned_error "Variable not found in the current context" + (Pos.get_position e) ) + | ELit (LBool _) -> UnionFind.make (Pos.same_pos_as (TLit TBool) e) + | ELit (LInt _) -> UnionFind.make (Pos.same_pos_as (TLit TInt) e) + | ELit (LRat _) -> UnionFind.make (Pos.same_pos_as (TLit TRat) e) + | ELit (LMoney _) -> UnionFind.make (Pos.same_pos_as (TLit TMoney) e) + | ELit (LDate _) -> UnionFind.make (Pos.same_pos_as (TLit TDate) e) + | ELit (LDuration _) -> UnionFind.make (Pos.same_pos_as (TLit TDuration) e) + | ELit LUnit -> UnionFind.make (Pos.same_pos_as (TLit TUnit) e) + | ELit LEmptyError -> UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) + | ETuple es -> + let ts = List.map (fun (e, _) -> typecheck_expr_bottom_up env e) es in + UnionFind.make (Pos.same_pos_as (TTuple ts) e) + | ETupleAccess (e1, n, _) -> ( + let t1 = typecheck_expr_bottom_up env e1 in + match Pos.unmark (UnionFind.get (UnionFind.find t1)) with + | TTuple ts -> ( + match List.nth_opt ts n with + | Some t' -> t' + | None -> + Errors.raise_spanned_error + (Format.asprintf + "Expression should have a tuple type with at least %d elements but only has %d" + n (List.length ts)) + (Pos.get_position e1) ) + | _ -> + Errors.raise_spanned_error + (Format.asprintf "Expected a tuple, got a %a" format_typ t1) + (Pos.get_position e1) ) + | EInj (e1, n, _, ts) -> + let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in + let ts_n = match List.nth_opt ts n with - | Some t' -> t' + | Some ts_n -> ts_n | None -> Errors.raise_spanned_error (Format.asprintf - "Expression should have a tuple type with at least %d elements but only has %d" n + "Expression should have a sum type with at least %d cases but only has %d" n (List.length ts)) - (Pos.get_position e1) ) - | _ -> - Errors.raise_spanned_error - (Format.asprintf "Expected a tuple, got a %a" format_typ t1) - (Pos.get_position e1) ) - | EInj (e1, n, _, ts) -> - let ts = List.map (fun t -> UnionFind.make (Pos.map_under_mark ast_to_typ t)) ts in - let ts_n = - match List.nth_opt ts n with - | Some ts_n -> ts_n - | None -> - Errors.raise_spanned_error - (Format.asprintf - "Expression should have a sum type with at least %d cases but only has %d" n - (List.length ts)) - (Pos.get_position e) - in - typecheck_expr_top_down env e1 ts_n; - UnionFind.make (Pos.same_pos_as (TEnum ts) e) - | EMatch (e1, es) -> - let enum_cases = List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as TAny e')) es in - let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in - typecheck_expr_top_down env e1 t_e1; - let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in - List.iteri - (fun i (es', _) -> - let enum_t = List.nth enum_cases i in - let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in - typecheck_expr_top_down env es' t_es') - es; - t_ret - | EAbs (pos_binder, binder, taus) -> - let xs, body = Bindlib.unmbind binder in - if Array.length xs = List.length taus then - let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - let env = - List.fold_left - (fun env (x, tau) -> - A.VarMap.add x (ast_to_typ (Pos.unmark tau), Pos.get_position tau) env) - env xstaus + (Pos.get_position e) in - List.fold_right - (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> - UnionFind.make - (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) - taus - (typecheck_expr_bottom_up env body) - else - Errors.raise_spanned_error - (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) - (List.length taus)) - pos_binder - | EApp (e1, args) -> - let t_args = List.map (typecheck_expr_bottom_up env) args in - let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in - let t_app = - List.fold_right - (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) - t_args t_ret - in - typecheck_expr_top_down env e1 t_app; - t_ret - | EOp op -> op_type (Pos.same_pos_as op e) - | EDefault (excepts, just, cons) -> - typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); - let tcons = typecheck_expr_bottom_up env cons in - List.iter (fun except -> typecheck_expr_top_down env except tcons) excepts; - tcons - | EIfThenElse (cond, et, ef) -> - typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); - let tt = typecheck_expr_bottom_up env et in - typecheck_expr_top_down env ef tt; - tt - | EAssert e' -> - typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); - UnionFind.make (Pos.same_pos_as (TLit TUnit) e') - | EArray es -> - let cell_type = UnionFind.make (Pos.same_pos_as TAny e) in - List.iter - (fun e' -> - let t_e' = typecheck_expr_bottom_up env e' in - unify cell_type t_e') - es; - UnionFind.make (Pos.same_pos_as (TArray cell_type) e) + typecheck_expr_top_down env e1 ts_n; + UnionFind.make (Pos.same_pos_as (TEnum ts) e) + | EMatch (e1, es) -> + let enum_cases = + List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e')) es + in + let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in + typecheck_expr_top_down env e1 t_e1; + let t_ret = UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) in + List.iteri + (fun i (es', _) -> + let enum_t = List.nth enum_cases i in + let t_es' = UnionFind.make (Pos.same_pos_as (TArrow (enum_t, t_ret)) es') in + typecheck_expr_top_down env es' t_es') + es; + t_ret + | EAbs (pos_binder, binder, taus) -> + let xs, body = Bindlib.unmbind binder in + if Array.length xs = List.length taus then + let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in + let env = + List.fold_left + (fun env (x, tau) -> + A.VarMap.add x (ast_to_typ (Pos.unmark tau), Pos.get_position tau) env) + env xstaus + in + List.fold_right + (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> + UnionFind.make + (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) + taus + (typecheck_expr_bottom_up env body) + else + Errors.raise_spanned_error + (Format.asprintf "function has %d variables but was supplied %d types" (Array.length xs) + (List.length taus)) + pos_binder + | EApp (e1, args) -> + let t_args = List.map (typecheck_expr_bottom_up env) args in + let t_ret = UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) in + let t_app = + List.fold_right + (fun t_arg acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + t_args t_ret + in + typecheck_expr_top_down env e1 t_app; + t_ret + | EOp op -> op_type (Pos.same_pos_as op e) + | EDefault (excepts, just, cons) -> + typecheck_expr_top_down env just (UnionFind.make (Pos.same_pos_as (TLit TBool) just)); + let tcons = typecheck_expr_bottom_up env cons in + List.iter (fun except -> typecheck_expr_top_down env except tcons) excepts; + tcons + | EIfThenElse (cond, et, ef) -> + typecheck_expr_top_down env cond (UnionFind.make (Pos.same_pos_as (TLit TBool) cond)); + let tt = typecheck_expr_bottom_up env et in + typecheck_expr_top_down env ef tt; + tt + | EAssert e' -> + typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); + UnionFind.make (Pos.same_pos_as (TLit TUnit) e') + | EArray es -> + let cell_type = UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) in + List.iter + (fun e' -> + let t_e' = typecheck_expr_bottom_up env e' in + unify cell_type t_e') + es; + UnionFind.make (Pos.same_pos_as (TArray cell_type) e) + in + (* Cli.debug_print (Format.asprintf "Found type of %a: %a" Print.format_expr e format_typ out); *) + out (** Checks whether the expression can be typed with the provided type *) and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = + (* Cli.debug_print (Format.asprintf "Typechecking %a : %a" Print.format_expr e format_typ tau); *) match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt (Pos.unmark v) env with @@ -289,12 +308,12 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | ELit (LDate _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TDate) e)) | ELit (LDuration _) -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TDuration) e)) | ELit LUnit -> unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e)) - | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as TAny e)) + | ELit LEmptyError -> unify tau (UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e)) | ETuple es -> ( let tau' = UnionFind.get (UnionFind.find tau) in match Pos.unmark tau' with | TTuple ts -> List.iter2 (fun (e, _) t -> typecheck_expr_top_down env e t) es ts - | TAny -> + | TAny _ -> unify tau (UnionFind.make (Pos.same_pos_as @@ -316,7 +335,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) "expression should have a tuple type with at least %d elements but only has %d" n (List.length t1s)) (Pos.get_position e1) ) - | TAny -> + | TAny _ -> (* Include total number of cases in ETupleAccess to continue typechecking at this point *) Errors.raise_spanned_error "The precise type of this expression cannot be inferred.\n\ @@ -341,10 +360,12 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env e1 ts_n; unify (UnionFind.make (Pos.same_pos_as (TEnum ts) e)) tau | EMatch (e1, es) -> - let enum_cases = List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as TAny e')) es in + let enum_cases = + List.map (fun (e', _) -> UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e')) es + in let t_e1 = UnionFind.make (Pos.same_pos_as (TEnum enum_cases) e1) in typecheck_expr_top_down env e1 t_e1; - let t_ret = UnionFind.make (Pos.same_pos_as TAny e) in + let t_ret = UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) in List.iteri (fun i (es', _) -> let enum_t = List.nth enum_cases i in @@ -401,7 +422,7 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) typecheck_expr_top_down env e' (UnionFind.make (Pos.same_pos_as (TLit TBool) e')); unify tau (UnionFind.make (Pos.same_pos_as (TLit TUnit) e')) | EArray es -> - let cell_type = UnionFind.make (Pos.same_pos_as TAny e) in + let cell_type = UnionFind.make (Pos.same_pos_as (TAny (Any.fresh ())) e) in List.iter (fun e' -> let t_e' = typecheck_expr_bottom_up env e' in diff --git a/src/catala/scope_language/ast.ml b/src/catala/scope_language/ast.ml index 68e855a9..ceada7c1 100644 --- a/src/catala/scope_language/ast.ml +++ b/src/catala/scope_language/ast.ml @@ -80,6 +80,8 @@ type typ = | TStruct of StructName.t | TEnum of EnumName.t | TArrow of typ Pos.marked * typ Pos.marked + | TArray of typ + | TAny (** The expressions use the {{:https://lepigre.fr/ocaml-bindlib/} Bindlib} library, based on higher-order abstract syntax*) diff --git a/src/catala/scope_language/dependency.ml b/src/catala/scope_language/dependency.ml index 3e960080..da5f23be 100644 --- a/src/catala/scope_language/dependency.ml +++ b/src/catala/scope_language/dependency.ml @@ -149,7 +149,8 @@ let rec get_structs_or_enums_in_type (t : Ast.typ Pos.marked) : TVertexSet.t = | Ast.TEnum e -> TVertexSet.singleton (TVertex.Enum e) | Ast.TArrow (t1, t2) -> TVertexSet.union (get_structs_or_enums_in_type t1) (get_structs_or_enums_in_type t2) - | Ast.TLit _ -> TVertexSet.empty + | Ast.TLit _ | Ast.TAny -> TVertexSet.empty + | Ast.TArray t1 -> get_structs_or_enums_in_type (Pos.same_pos_as t1 t) let build_type_graph (structs : Ast.struct_ctx) (enums : Ast.enum_ctx) : TDependencies.t = let g = TDependencies.empty in diff --git a/src/catala/scope_language/print.ml b/src/catala/scope_language/print.ml index 2210f769..2489644e 100644 --- a/src/catala/scope_language/print.ml +++ b/src/catala/scope_language/print.ml @@ -42,6 +42,8 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked) : unit = | TEnum e -> Format.fprintf fmt "%a" Ast.EnumName.format_t e | TArrow (t1, t2) -> Format.fprintf fmt "@[%a →@ %a@]" format_typ_with_parens t1 format_typ t2 + | TArray t1 -> Format.fprintf fmt "@[%a@ array@]" format_typ (Pos.same_pos_as t1 typ) + | TAny -> Format.fprintf fmt "any" let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index e150c517..0f12cec1 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -54,7 +54,9 @@ let rec translate_typ (ctx : ctx) (t : Ast.typ Pos.marked) : Dcalc.Ast.typ Pos.m Dcalc.Ast.TTuple (List.map (fun (_, t) -> translate_typ ctx t) s_fields) | Ast.TEnum e_uid -> let e_cases = Ast.EnumMap.find e_uid ctx.enums in - Dcalc.Ast.TEnum (List.map (fun (_, t) -> translate_typ ctx t) e_cases) ) + Dcalc.Ast.TEnum (List.map (fun (_, t) -> translate_typ ctx t) e_cases) + | Ast.TArray t1 -> Dcalc.Ast.TArray (translate_typ ctx (Pos.same_pos_as t1 t)) + | Ast.TAny -> Dcalc.Ast.TAny ) t let merge_defaults (caller : Dcalc.Ast.expr Pos.marked Bindlib.box) diff --git a/syntax_highlighting/en/ace/mode-catala_en.js b/syntax_highlighting/en/ace/mode-catala_en.js index 1e3a4634..fabc647f 100644 --- a/syntax_highlighting/en/ace/mode-catala_en.js +++ b/syntax_highlighting/en/ace/mode-catala_en.js @@ -70,7 +70,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu }, { "token": "punctuation", - "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))" + "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})" }, { "token": "keyword.operator", diff --git a/syntax_highlighting/en/atom/grammars/catala_en.cson b/syntax_highlighting/en/atom/grammars/catala_en.cson index 7172279c..03ce04fc 100644 --- a/syntax_highlighting/en/atom/grammars/catala_en.cson +++ b/syntax_highlighting/en/atom/grammars/catala_en.cson @@ -116,7 +116,7 @@ 'name' : 'constant.numeric.catala_en' } { - 'match' : '(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))' + 'match' : '(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})' 'name' : 'punctuation.catala_en' } { diff --git a/syntax_highlighting/en/catala_en.iro b/syntax_highlighting/en/catala_en.iro index 39d58e32..12bd5838 100644 --- a/syntax_highlighting/en/catala_en.iro +++ b/syntax_highlighting/en/catala_en.iro @@ -235,7 +235,7 @@ code : context { : pattern { - regex \= (\-\-|\;|\.|\,|\:|\(|\)) + regex \= (\-\-|\;|\.|\,|\:|\(|\)|\[|\]|\{|\}) styles [] = .punctuation; } diff --git a/syntax_highlighting/en/pygments/catala_en.py b/syntax_highlighting/en/pygments/catala_en.py index d9beca5a..24096add 100644 --- a/syntax_highlighting/en/pygments/catala_en.py +++ b/syntax_highlighting/en/pygments/catala_en.py @@ -31,7 +31,8 @@ class CatalaEnLexer(RegexLexer): (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), - (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))', bygroups(Operator)), + (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})', bygroups( + Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)', bygroups(Operator)), (u'\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b', diff --git a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml index 12a41eae..70ae06b5 100644 --- a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml @@ -185,7 +185,7 @@ match - (\-\-|\;|\.|\,|\:|\(|\)) + (\-\-|\;|\.|\,|\:|\(|\)|\[|\]|\{|\}) name punctuation.catala_en diff --git a/syntax_highlighting/fr/ace/mode-catala_fr.js b/syntax_highlighting/fr/ace/mode-catala_fr.js index bae260be..08df1403 100644 --- a/syntax_highlighting/fr/ace/mode-catala_fr.js +++ b/syntax_highlighting/fr/ace/mode-catala_fr.js @@ -70,7 +70,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu }, { "token": "punctuation", - "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))" + "regex": "(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})" }, { "token": "keyword.operator", diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index 21d73c60..d1afa088 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -116,7 +116,7 @@ 'name' : 'constant.numeric.catala_fr' } { - 'match' : '(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))' + 'match' : '(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})' 'name' : 'punctuation.catala_fr' } { diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index f6322d46..fab64f5e 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -235,7 +235,7 @@ code : context { : pattern { - regex \= (\-\-|\;|\.|\,|\:|\(|\)) + regex \= (\-\-|\;|\.|\,|\:|\(|\)|\[|\]|\{|\}) styles [] = .punctuation; } diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 46cfcee0..10d29754 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -31,7 +31,8 @@ class CatalaFrLexer(RegexLexer): (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(vrai|faux)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), - (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\))', bygroups(Operator)), + (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})', bygroups( + Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour)', bygroups(Operator)), (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme|date_aujourd_hui)\\b', diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index f59d02cd..69d8b3ad 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -185,7 +185,7 @@ match - (\-\-|\;|\.|\,|\:|\(|\)) + (\-\-|\;|\.|\,|\:|\(|\)|\[|\]|\{|\}) name punctuation.catala_fr diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index c8f99b2d..d2da1dc6 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -116,7 +116,7 @@ 'name' : 'constant.numeric.catala_nv' } { - 'match' : '(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[|\\])' + 'match' : '(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[\\||\\|\\]|\\[|\\]|\\{|\\})' 'name' : 'punctuation.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index 8e3cfd80..f4da4f9c 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -235,7 +235,7 @@ code : context { : pattern { - regex \= (\-\-|\;|\.|\,|\:=|\:|\(|\)|\[|\]) + regex \= (\-\-|\;|\.|\,|\:=|\:|\(|\)|\[\||\|\]|\[|\]|\{|\}) styles [] = .punctuation; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index 68895aee..80d00de3 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -31,7 +31,7 @@ class CatalaNvLexer(RegexLexer): (u'(\\|[0-9]+/[0-9]+/[0-9]+\\|)', bygroups(Number.Integer)), (u'\\b(true|false)\\b', bygroups(Keyword.Constant)), (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), - (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[|\\])', + (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[\\||\\|\\]|\\[|\\]|\\{|\\})', bygroups(Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)', bygroups(Operator)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index 4688d65f..b89a62d4 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -185,7 +185,7 @@ match - (\-\-|\;|\.|\,|\:=|\:|\(|\)|\[|\]) + (\-\-|\;|\.|\,|\:=|\:|\(|\)|\[\||\|\]|\[|\]|\{|\}) name punctuation.catala_nv diff --git a/tests/test_array/simple.catala b/tests/test_array/simple.catala new file mode 100644 index 00000000..9f600ef6 --- /dev/null +++ b/tests/test_array/simple.catala @@ -0,0 +1,18 @@ +@Article@ + +/* +new scope A: + param x content set int + +scope A: + def x := [0; 4+5; 8*8] + +new scope B: + param a scope A + param y content bool + param z content bool + +scope B: + def y := exists m in a.x such that m = 9 + def z := for all m in a.x we have m > 0 +*/ \ No newline at end of file diff --git a/tests/test_array/simple.catala.A.out b/tests/test_array/simple.catala.A.out new file mode 100644 index 00000000..5a826abe --- /dev/null +++ b/tests/test_array/simple.catala.A.out @@ -0,0 +1,2 @@ +[RESULT] Computation successful! Results: +[RESULT] x = [0;9;64] diff --git a/tests/test_array/simple.catala.B.out b/tests/test_array/simple.catala.B.out new file mode 100644 index 00000000..18ca5c8d --- /dev/null +++ b/tests/test_array/simple.catala.B.out @@ -0,0 +1,3 @@ +[RESULT] Computation successful! Results: +[RESULT] y = true +[RESULT] z = false diff --git a/tests/test_bool/test_bool.catala b/tests/test_bool/test_bool.catala index 0e40650f..ba6459bd 100644 --- a/tests/test_bool/test_bool.catala +++ b/tests/test_bool/test_bool.catala @@ -7,6 +7,6 @@ new scope TestBool : scope TestBool : def bar := 1 - def foo [ bar >= 0 ] := true - def foo [ bar < 0 ] := false + def foo [| bar >= 0 |] := true + def foo [| bar < 0 |] := false */ diff --git a/tests/test_default/conflict.catala b/tests/test_default/conflict.catala index 6b5c588f..b3109a37 100644 --- a/tests/test_default/conflict.catala +++ b/tests/test_default/conflict.catala @@ -5,6 +5,6 @@ new scope A: param x content int scope A: - def x [true] := 1 - def x [true] := 0 + def x [|true|] := 1 + def x [|true|] := 0 */ \ No newline at end of file diff --git a/tests/test_default/conflict.catala.A.out b/tests/test_default/conflict.catala.A.out index 50a09b66..054b9726 100644 --- a/tests/test_default/conflict.catala.A.out +++ b/tests/test_default/conflict.catala.A.out @@ -3,11 +3,11 @@ [ERROR] This justification is true: [ERROR] --> test_default/conflict.catala [ERROR] | -[ERROR] 8 | def x [true] := 1 -[ERROR] | ^^^^ +[ERROR] 8 | def x [|true|] := 1 +[ERROR] | ^^^^ [ERROR] [ERROR] This justification is true: [ERROR] --> test_default/conflict.catala [ERROR] | -[ERROR] 9 | def x [true] := 0 -[ERROR] | ^^^^ +[ERROR] 9 | def x [|true|] := 0 +[ERROR] | ^^^^ diff --git a/tests/test_default/empty_with_rules.catala b/tests/test_default/empty_with_rules.catala index 355136ba..c3ed6a27 100644 --- a/tests/test_default/empty_with_rules.catala +++ b/tests/test_default/empty_with_rules.catala @@ -7,7 +7,7 @@ new scope A: scope A: def y := 1 - def x [y = 2] := 1 - def x [y = 3] := 1 - def x [y = 4] := 1 + def x [|y = 2|] := 1 + def x [|y = 3|] := 1 + def x [|y = 4|] := 1 */ \ No newline at end of file diff --git a/tests/test_func/func.catala b/tests/test_func/func.catala index 084549f7..9f2b5d82 100644 --- a/tests/test_func/func.catala +++ b/tests/test_func/func.catala @@ -11,8 +11,8 @@ new scope R: param r content int scope S: - def f of x [ (x >= x) ] := x + x - def f of x [ not b ] := x * x + def f of x [| (x >= x) |] := x + x + def f of x [| not b |] := x * x def b := false def out := f of 5 diff --git a/tests/test_func/func.catala.S.out b/tests/test_func/func.catala.S.out index f2799c4a..4ed95d4d 100644 --- a/tests/test_func/func.catala.S.out +++ b/tests/test_func/func.catala.S.out @@ -3,11 +3,11 @@ [ERROR] This justification is true: [ERROR] --> test_func/func.catala [ERROR] | -[ERROR] 14 | def f of x [ (x >= x) ] := x + x -[ERROR] | ^^^^^^ +[ERROR] 14 | def f of x [| (x >= x) |] := x + x +[ERROR] | ^^^^^^ [ERROR] [ERROR] This justification is true: [ERROR] --> test_func/func.catala [ERROR] | -[ERROR] 15 | def f of x [ not b ] := x * x -[ERROR] | ^^^^^ +[ERROR] 15 | def f of x [| not b |] := x * x +[ERROR] | ^^^^^ diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out index c4eefbc9..54266e36 100644 --- a/tests/test_money/no_mingle.catala.A.out +++ b/tests/test_money/no_mingle.catala.A.out @@ -11,27 +11,3 @@ [ERROR] | [ERROR] 4 | new scope A: [ERROR] | ^ -[ERROR] -[ERROR] Type decimal → money coming from expression: -[ERROR] --> test_money/no_mingle.catala -[ERROR] | -[ERROR] 12 | def z := (x *$ y) -[ERROR] | ^^ -[ERROR] -[ERROR] Type money → any type coming from expression: -[ERROR] --> test_money/no_mingle.catala -[ERROR] | -[ERROR] 12 | def z := (x *$ y) -[ERROR] | ^^^^^^ -[ERROR] -[ERROR] Type money → decimal → money coming from expression: -[ERROR] --> test_money/no_mingle.catala -[ERROR] | -[ERROR] 12 | def z := (x *$ y) -[ERROR] | ^^ -[ERROR] -[ERROR] Type money → money → any type coming from expression: -[ERROR] --> test_money/no_mingle.catala -[ERROR] | -[ERROR] 12 | def z := (x *$ y) -[ERROR] | ^^^^^^ diff --git a/tests/test_scope/cycle_in_scope.catala b/tests/test_scope/cycle_in_scope.catala index 94b1bb43..6b8fe3e6 100644 --- a/tests/test_scope/cycle_in_scope.catala +++ b/tests/test_scope/cycle_in_scope.catala @@ -7,9 +7,9 @@ new scope A : param z content int scope A: - def y [x < 0] := - x - def y [x >= 0] := x - def z [y >= 1] := 10 / y - def z [y < 1] := y + def y [|x < 0|] := - x + def y [|x >= 0|] := x + def z [|y >= 1|] := 10 / y + def z [|y < 1|] := y def x := z */ \ No newline at end of file diff --git a/tests/test_scope/cycle_in_scope.catala.A.out b/tests/test_scope/cycle_in_scope.catala.A.out index 8514de34..7124761d 100644 --- a/tests/test_scope/cycle_in_scope.catala.A.out +++ b/tests/test_scope/cycle_in_scope.catala.A.out @@ -21,8 +21,8 @@ [ERROR] Used here in the definition of another cycle variable z: [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | -[ERROR] 13 | def z [y < 1] := y -[ERROR] | ^ +[ERROR] 13 | def z [|y < 1|] := y +[ERROR] | ^ [ERROR] [ERROR] Cycle variable x, declared: [ERROR] --> test_scope/cycle_in_scope.catala @@ -33,5 +33,5 @@ [ERROR] Used here in the definition of another cycle variable y: [ERROR] --> test_scope/cycle_in_scope.catala [ERROR] | -[ERROR] 11 | def y [x >= 0] := x -[ERROR] | ^ +[ERROR] 11 | def y [|x >= 0|] := x +[ERROR] | ^ diff --git a/tests/test_scope/scope.catala b/tests/test_scope/scope.catala index 10e3ddcd..01dc1e3f 100644 --- a/tests/test_scope/scope.catala +++ b/tests/test_scope/scope.catala @@ -8,8 +8,8 @@ new scope A: scope A: def c := false - def a [ c ] := 42 - def a [ not c ] := 0 - def b [ not c ] := 1337 - def b [ not c ] := 0 + def a [| c |] := 42 + def a [| not c |] := 0 + def b [| not c |] := 1337 + def b [| not c |] := 0 */ diff --git a/tests/test_scope/scope.catala.A.out b/tests/test_scope/scope.catala.A.out index da0d117b..8c1b2af2 100644 --- a/tests/test_scope/scope.catala.A.out +++ b/tests/test_scope/scope.catala.A.out @@ -3,11 +3,11 @@ [ERROR] This justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | -[ERROR] 13 | def b [ not c ] := 1337 -[ERROR] | ^^^^^ +[ERROR] 13 | def b [| not c |] := 1337 +[ERROR] | ^^^^^ [ERROR] [ERROR] This justification is true: [ERROR] --> test_scope/scope.catala [ERROR] | -[ERROR] 14 | def b [ not c ] := 0 -[ERROR] | ^^^^^ +[ERROR] 14 | def b [| not c |] := 0 +[ERROR] | ^^^^^ diff --git a/tests/test_scope/sub_scope.catala b/tests/test_scope/sub_scope.catala index 2d58c3d5..b3154543 100644 --- a/tests/test_scope/sub_scope.catala +++ b/tests/test_scope/sub_scope.catala @@ -20,5 +20,5 @@ scope A: scope B: def a := 42 def b := scopeA.b - def scopeA.a [ a > 0 ] := scopeAbis.a_base + def scopeA.a [| a > 0 |] := scopeAbis.a_base */ diff --git a/tests/test_scope/sub_sub_scope.catala b/tests/test_scope/sub_sub_scope.catala index 18517730..c439689f 100644 --- a/tests/test_scope/sub_sub_scope.catala +++ b/tests/test_scope/sub_sub_scope.catala @@ -20,9 +20,9 @@ scope A: def u := true scope B: - def a2.x [ a1.u ] := 1 - def y [ a2.x = 1 ] := 1 - def y [ a2.x + 1 = 2 ] := 1 + def a2.x [| a1.u |] := 1 + def y [| a2.x = 1 |] := 1 + def y [| a2.x + 1 = 2 |] := 1 scope C: def a.x := 2 diff --git a/tests/test_scope/sub_sub_scope.catala.B.out b/tests/test_scope/sub_sub_scope.catala.B.out index 2c583348..a7a20a00 100644 --- a/tests/test_scope/sub_sub_scope.catala.B.out +++ b/tests/test_scope/sub_sub_scope.catala.B.out @@ -3,11 +3,11 @@ [ERROR] This justification is true: [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | -[ERROR] 24 | def y [ a2.x = 1 ] := 1 -[ERROR] | ^^^^^^^^ +[ERROR] 24 | def y [| a2.x = 1 |] := 1 +[ERROR] | ^^^^^^^^ [ERROR] [ERROR] This justification is true: [ERROR] --> test_scope/sub_sub_scope.catala [ERROR] | -[ERROR] 25 | def y [ a2.x + 1 = 2 ] := 1 -[ERROR] | ^^^^^^^^^^^^ +[ERROR] 25 | def y [| a2.x + 1 = 2 |] := 1 +[ERROR] | ^^^^^^^^^^^^ From 5f58e93c6eaaec0a0a4308416dd10c417f4abca7 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 29 Dec 2020 23:43:00 +0100 Subject: [PATCH 129/142] Implemented all aggregate desugaring --- .../allocations_familiales/metadata.catala_fr | 6 +- .../securite_sociale_R.catala_fr | 2 +- examples/us_tax_code/section_1015.catala_en | 2 +- src/catala/catala_surface/ast.ml | 2 +- src/catala/catala_surface/desugaring.ml | 106 ++-- src/catala/catala_surface/parser.messages | 465 ++++++++---------- src/catala/catala_surface/parser.mly | 2 +- src/catala/catala_surface/parser_errors.ml | 248 +++++----- src/catala/catala_surface/print.ml | 26 + tests/test_array/aggregation.catala | 18 + tests/test_array/aggregation.catala.A.out | 2 + tests/test_array/aggregation.catala.B.out | 3 + tests/test_array/simple.catala.A.out | 2 +- tests/test_dec/simple.catala.A.out | 4 +- 14 files changed, 455 insertions(+), 433 deletions(-) create mode 100644 src/catala/catala_surface/print.ml create mode 100644 tests/test_array/aggregation.catala create mode 100644 tests/test_array/aggregation.catala.A.out create mode 100644 tests/test_array/aggregation.catala.B.out diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index 1f78de53..e9d2a45b 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -35,10 +35,10 @@ déclaration énumération Collectivité : déclaration structure Ménage : donnée enfants contenu collection Enfant donnée parent_en_charge contenu Personne dépend de Enfant - donnée enfant_plus_âgé contenu optionnel Enfant + donnée enfant_plus_âgé contenu Enfant donnée parents contenu collection Personne donnée parent1 contenu Personne - donnée parent2 contenu optionnel Personne + donnée parent2 contenu Personne donnée résidence contenu Collectivité # Le mot optionnel permet de prévoir le cas où le # ménage n'a pas d'enfants @@ -131,7 +131,7 @@ déclaration énumération ChoixParentAllocataire : -- DeuxParents déclaration structure AllocationsGardeAlternée : - donnée choix_allocataire contenu optionnel ChoixParentAllocataire + donnée choix_allocataire contenu ChoixParentAllocataire dépend de Enfant condition unique_allocataire dépend de Enfant condition allocataire_double dépend de Enfant diff --git a/examples/allocations_familiales/securite_sociale_R.catala_fr b/examples/allocations_familiales/securite_sociale_R.catala_fr index 44c4c983..e515f1d7 100644 --- a/examples/allocations_familiales/securite_sociale_R.catala_fr +++ b/examples/allocations_familiales/securite_sociale_R.catala_fr @@ -135,7 +135,7 @@ du nombre d'enfants à charge dans les conditions suivantes : /* champ d'application CalculAllocationsFamiliales : définition allocations_familiales.nombre_moyen_enfants égal à - somme pour enfant dans ménage.enfants de ( + somme entier pour enfant dans ménage.enfants de ( selon enfant.prise_en_charge sous forme -- Complète : 1 -- GardeAlternée de parents : 0,5 diff --git a/examples/us_tax_code/section_1015.catala_en b/examples/us_tax_code/section_1015.catala_en index 8ff4bbfa..cb7e0a9d 100644 --- a/examples/us_tax_code/section_1015.catala_en +++ b/examples/us_tax_code/section_1015.catala_en @@ -19,7 +19,7 @@ declaration structure Value: declaration structure Transferor: data basis content money - data basis_known content optional money + data basis_known content money data acquisition content Acquisition data gain_or_loss content money depends on date diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 56ad1471..c99771ae 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -89,7 +89,7 @@ type unop = Not | Minus of op_kind type builtin_expression = Cardinal | Now -type aggregate_func = AggregateSum | AggregateCount +type aggregate_func = AggregateSum of primitive_typ | AggregateCount type literal_date = { literal_date_day : int Pos.marked; diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index b222499f..9a252ba8 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -89,7 +89,10 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti | Number ((Int i, _), Some (Percent, _)) -> Scopelang.Ast.ELit (Dcalc.Ast.LRat (Q.div (Q.of_bigint i) (Q.of_int 100))) | Number ((Dec (i, f), _), None) -> - let digits_f = int_of_float (ceil (float_of_int (Z.log2up f) *. log 2.0 /. log 10.0)) in + let digits_f = + try int_of_float (ceil (float_of_int (Z.log2 f) *. log 2.0 /. log 10.0)) + with Invalid_argument _ -> 0 + in Scopelang.Ast.ELit (Dcalc.Ast.LRat Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) @@ -340,48 +343,85 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti Bindlib.box_apply (fun es -> (Scopelang.Ast.EArray es, pos)) (Bindlib.box_list (List.map rec_helper es)) - | CollectionOp (op, param, collection, predicate) -> - let ctxt, param = Name_resolution.add_def_local_var ctxt param in + | CollectionOp (op', param', collection, predicate) -> + let ctxt, param = Name_resolution.add_def_local_var ctxt param' in let collection = rec_helper collection in let init = - match Pos.unmark op with - | Ast.Exists -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos) - | Ast.Forall -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), pos) - | _ -> - Name_resolution.raise_unsupported_feature "operator not supported" (Pos.get_position op) - in - let acc_var = Scopelang.Ast.Var.make ("acc", pos) in - let acc = Scopelang.Ast.make_var (acc_var, pos) in - let f_body = - match Pos.unmark op with + match Pos.unmark op' with | Ast.Exists -> + Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), Pos.get_position op') + | Ast.Forall -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), Pos.get_position op') + | Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> + Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LInt Z.zero), Pos.get_position op') + | Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> + Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LRat Q.zero), Pos.get_position op') + | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> + Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LMoney Z.zero), Pos.get_position op') + | Ast.Aggregate (Ast.AggregateSum t) -> + Errors.raise_spanned_error + (Format.asprintf "It is impossible to sum two values of type %a together" + Print.format_primitive_typ t) + pos + | Ast.Aggregate Ast.AggregateCount -> + Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LInt Z.zero), Pos.get_position op') + in + let acc_var = Scopelang.Ast.Var.make ("acc", Pos.get_position param') in + let acc = Scopelang.Ast.make_var (acc_var, Pos.get_position param') in + let f_body = + let make_body (op : Dcalc.Ast.binop) = + Bindlib.box_apply2 + (fun predicate acc -> + ( Scopelang.Ast.EApp + ( (Scopelang.Ast.EOp (Dcalc.Ast.Binop op), Pos.get_position op'), + [ acc; predicate ] ), + pos )) + (translate_expr scope ctxt predicate) + acc + in + match Pos.unmark op' with + | Ast.Exists -> make_body Dcalc.Ast.Or + | Ast.Forall -> make_body Dcalc.Ast.And + | Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> make_body (Dcalc.Ast.Add Dcalc.Ast.KInt) + | Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> make_body (Dcalc.Ast.Add Dcalc.Ast.KRat) + | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> make_body (Dcalc.Ast.Add Dcalc.Ast.KMoney) + | Ast.Aggregate (Ast.AggregateSum _) -> assert false (* should not happen *) + | Ast.Aggregate Ast.AggregateCount -> Bindlib.box_apply2 (fun predicate acc -> - ( Scopelang.Ast.EApp - ((Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.Or), pos), [ acc; predicate ]), + ( Scopelang.Ast.EIfThenElse + ( predicate, + ( Scopelang.Ast.EApp + ( ( Scopelang.Ast.EOp (Dcalc.Ast.Binop (Dcalc.Ast.Add Dcalc.Ast.KInt)), + Pos.get_position op' ), + [ + acc; + (Scopelang.Ast.ELit (Dcalc.Ast.LInt Z.one), Pos.get_position predicate); + ] ), + pos ), + acc ), pos )) (translate_expr scope ctxt predicate) acc - | Ast.Forall -> - Bindlib.box_apply2 - (fun predicate acc -> - ( Scopelang.Ast.EApp - ((Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.And), pos), [ acc; predicate ]), - pos )) - (translate_expr scope ctxt predicate) - acc - | _ -> - Name_resolution.raise_unsupported_feature "operator not supported" (Pos.get_position op) in let f = - Bindlib.box_apply - (fun binder -> - ( Scopelang.Ast.EAbs - ( pos, - binder, - [ (Scopelang.Ast.TLit Dcalc.Ast.TBool, pos); (Scopelang.Ast.TAny, pos) ] ), - pos )) - (Bindlib.bind_mvar [| acc_var; param |] f_body) + let make_f (t : Dcalc.Ast.typ_lit) = + Bindlib.box_apply + (fun binder -> + ( Scopelang.Ast.EAbs + ( pos, + binder, + [ (Scopelang.Ast.TLit t, Pos.get_position op'); (Scopelang.Ast.TAny, pos) ] ), + pos )) + (Bindlib.bind_mvar [| acc_var; param |] f_body) + in + match Pos.unmark op' with + | Ast.Exists -> make_f Dcalc.Ast.TBool + | Ast.Forall -> make_f Dcalc.Ast.TBool + | Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> make_f Dcalc.Ast.TInt + | Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> make_f Dcalc.Ast.TRat + | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> make_f Dcalc.Ast.TMoney + | Ast.Aggregate (Ast.AggregateSum _) -> assert false (* should not happen *) + | Ast.Aggregate Ast.AggregateCount -> make_f Dcalc.Ast.TInt in Bindlib.box_apply3 (fun f collection init -> diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 6f6ef366..93d3ee2d 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE LAW_TEXT END_CODE ## -## Ends in an error in state: 327. +## Ends in an error in state: 328. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE option(law_text) . END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -12,7 +12,7 @@ expected a metadata-closing tag source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 326. +## Ends in an error in state: 327. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -72,7 +72,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 320. +## Ends in an error in state: 321. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -85,7 +85,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 315. +## Ends in an error in state: 316. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -97,7 +97,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 314. +## Ends in an error in state: 315. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -109,7 +109,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 313. +## Ends in an error in state: 314. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -121,7 +121,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 312. +## Ends in an error in state: 313. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -133,7 +133,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 311. +## Ends in an error in state: 312. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -145,7 +145,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 310. +## Ends in an error in state: 311. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -157,7 +157,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 305. +## Ends in an error in state: 306. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -169,7 +169,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 303. +## Ends in an error in state: 304. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -181,7 +181,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 302. +## Ends in an error in state: 303. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -193,7 +193,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 307. +## Ends in an error in state: 308. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -206,7 +206,7 @@ expected another scope context item or the end of the scope declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 300. +## Ends in an error in state: 301. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -218,7 +218,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 300. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -232,7 +232,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 299. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -246,7 +246,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 297. +## Ends in an error in state: 298. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -258,7 +258,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 296. +## Ends in an error in state: 297. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -270,7 +270,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 295. +## Ends in an error in state: 296. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 283. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -295,7 +295,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 290. +## Ends in an error in state: 291. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -307,7 +307,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 287. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -319,7 +319,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 286. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -331,7 +331,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 292. +## Ends in an error in state: 293. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -343,7 +343,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 270. +## Ends in an error in state: 279. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -355,7 +355,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 269. +## Ends in an error in state: 278. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -367,7 +367,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 268. +## Ends in an error in state: 277. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -379,7 +379,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 267. +## Ends in an error in state: 276. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -391,7 +391,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 266. +## Ends in an error in state: 275. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -403,7 +403,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 265. +## Ends in an error in state: 274. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -415,7 +415,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 264. +## Ends in an error in state: 273. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -429,7 +429,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 235. +## Ends in an error in state: 244. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -441,23 +441,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 54, spurious reduction of production primitive_expression -> CARDINAL -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression -## In state 229, spurious reduction of production assertion_base -> expression -## In state 230, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 234, spurious reduction of production scope_item -> ASSERTION assertion +## In state 63, spurious reduction of production primitive_expression -> CARDINAL +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression +## In state 238, spurious reduction of production assertion_base -> expression +## In state 239, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 243, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 226. +## Ends in an error in state: 235. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -469,7 +469,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 225. +## Ends in an error in state: 234. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -480,15 +480,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 224. +## Ends in an error in state: 233. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -500,7 +500,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 228. +## Ends in an error in state: 237. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -512,7 +512,7 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 232. +## Ends in an error in state: 241. ## ## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -523,21 +523,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 54, spurious reduction of production primitive_expression -> CARDINAL -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression -## In state 223, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 63, spurious reduction of production primitive_expression -> CARDINAL +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression +## In state 232, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 222. +## Ends in an error in state: 231. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -549,7 +549,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 212. +## Ends in an error in state: 221. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -560,15 +560,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 214. +## Ends in an error in state: 223. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -579,15 +579,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 213. +## Ends in an error in state: 222. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -599,7 +599,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 210. +## Ends in an error in state: 219. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -611,7 +611,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 209. +## Ends in an error in state: 218. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -623,7 +623,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 257. +## Ends in an error in state: 266. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -635,7 +635,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 255. +## Ends in an error in state: 264. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -647,7 +647,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 256. +## Ends in an error in state: 265. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -659,7 +659,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 254. +## Ends in an error in state: 263. ## ## definition -> option(label) option(exception_to) DEFINITION qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -670,15 +670,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 253. +## Ends in an error in state: 262. ## ## definition -> option(label) option(exception_to) DEFINITION . qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -690,7 +690,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION IDENT DEFINED_AS ## -## Ends in an error in state: 240. +## Ends in an error in state: 249. ## ## definition -> option(label) option(exception_to) . DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) option(exception_to) . RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -703,7 +703,7 @@ expected a rule or a definition after the exception declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION YEAR ## -## Ends in an error in state: 238. +## Ends in an error in state: 247. ## ## exception_to -> EXCEPTION . ident [ RULE DEFINITION ] ## @@ -715,7 +715,7 @@ expected the label to which the exception is referring back source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL IDENT DEFINED_AS ## -## Ends in an error in state: 237. +## Ends in an error in state: 246. ## ## definition -> option(label) . option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) . option(exception_to) RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -728,7 +728,7 @@ expected a rule or a definition after the label declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL YEAR ## -## Ends in an error in state: 207. +## Ends in an error in state: 216. ## ## label -> LABEL . ident [ RULE EXCEPTION DEFINITION ] ## @@ -740,7 +740,7 @@ expected the name of the label source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 220. +## Ends in an error in state: 229. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -752,7 +752,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 246. +## Ends in an error in state: 255. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -764,7 +764,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 242. +## Ends in an error in state: 251. ## ## rule -> option(label) option(exception_to) RULE rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -776,7 +776,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 249. +## Ends in an error in state: 258. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -788,7 +788,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 243. +## Ends in an error in state: 252. ## ## rule -> option(label) option(exception_to) RULE rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -800,7 +800,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 248. +## Ends in an error in state: 257. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -811,15 +811,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 219, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 211, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 228. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -832,7 +832,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 241. +## Ends in an error in state: 250. ## ## rule -> option(label) option(exception_to) RULE . rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -844,7 +844,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 206. +## Ends in an error in state: 215. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -856,7 +856,7 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 54. +## Ends in an error in state: 63. ## ## aggregate_func -> CARDINAL . [ FOR ] ## primitive_expression -> CARDINAL . [ WITH THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -869,7 +869,7 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 152. +## Ends in an error in state: 161. ## ## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -883,7 +883,7 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 151. +## Ends in an error in state: 160. ## ## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -896,7 +896,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL ALT YEAR ## -## Ends in an error in state: 80. +## Ends in an error in state: 89. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] ## @@ -908,7 +908,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL THEN ## -## Ends in an error in state: 79. +## Ends in an error in state: 88. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RBRACKET ] ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] @@ -920,20 +920,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 54, spurious reduction of production primitive_expression -> CARDINAL -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 143, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 63, spurious reduction of production primitive_expression -> CARDINAL +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 152, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another structure field or the closing bracket source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON YEAR ## -## Ends in an error in state: 83. +## Ends in an error in state: 92. ## ## struct_content_field -> ident COLON . logical_expression [ RBRACKET ALT ] ## @@ -945,7 +945,7 @@ expected the expression for this struct field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT YEAR ## -## Ends in an error in state: 82. +## Ends in an error in state: 91. ## ## struct_content_field -> ident . COLON logical_expression [ RBRACKET ALT ] ## @@ -957,7 +957,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT YEAR ## -## Ends in an error in state: 78. +## Ends in an error in state: 87. ## ## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -969,7 +969,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET YEAR ## -## Ends in an error in state: 77. +## Ends in an error in state: 86. ## ## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -981,7 +981,7 @@ expected structure fields introduced by -- source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 76. +## Ends in an error in state: 85. ## ## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -993,7 +993,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 167. +## Ends in an error in state: 176. ## ## expression -> exists_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1005,7 +1005,7 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 173. +## Ends in an error in state: 182. ## ## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1017,7 +1017,7 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 172. +## Ends in an error in state: 181. ## ## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1028,14 +1028,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 171. +## Ends in an error in state: 180. ## ## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1047,7 +1047,7 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 170. +## Ends in an error in state: 179. ## ## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1059,7 +1059,7 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 178. ## ## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1071,7 +1071,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 169. ## ## expression -> forall_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1083,7 +1083,7 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 164. +## Ends in an error in state: 173. ## ## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1094,14 +1094,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 163. +## Ends in an error in state: 172. ## ## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1113,7 +1113,7 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 162. +## Ends in an error in state: 171. ## ## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1125,7 +1125,7 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 170. ## ## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## @@ -1137,7 +1137,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 49. +## Ends in an error in state: 58. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -1149,7 +1149,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 175. +## Ends in an error in state: 184. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1160,20 +1160,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 178. +## Ends in an error in state: 187. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1185,7 +1185,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 177. +## Ends in an error in state: 186. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1196,20 +1196,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 176. +## Ends in an error in state: 185. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1221,7 +1221,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 47. +## Ends in an error in state: 56. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1233,7 +1233,7 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 67. +## Ends in an error in state: 76. ## ## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1245,7 +1245,7 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 180. +## Ends in an error in state: 189. ## ## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1256,20 +1256,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 45. +## Ends in an error in state: 54. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1281,7 +1281,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 188. +## Ends in an error in state: 197. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1292,14 +1292,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 191. +## Ends in an error in state: 200. ## ## match_arms -> ALT match_arm . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1310,20 +1310,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 142, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 195, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 151, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 204, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 194. +## Ends in an error in state: 203. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1335,7 +1335,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 208. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1347,7 +1347,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 193. +## Ends in an error in state: 202. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1359,7 +1359,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 197. +## Ends in an error in state: 206. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1372,7 +1372,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 196. +## Ends in an error in state: 205. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1384,7 +1384,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 190. +## Ends in an error in state: 199. ## ## match_arms -> ALT . match_arm match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1396,7 +1396,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 189. +## Ends in an error in state: 198. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1408,7 +1408,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 43. +## Ends in an error in state: 52. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1420,7 +1420,7 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 55. +## Ends in an error in state: 64. ## ## sum_expression -> sum_unop . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1432,7 +1432,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 141. +## Ends in an error in state: 150. ## ## logical_expression -> logical_unop . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1442,87 +1442,26 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION expected an expression to take the negation of -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE OF YEAR -## -## Ends in an error in state: 137. -## -## aggregate -> aggregate_func FOR ident IN primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## aggregate_func FOR ident IN primitive_expression OF -## -expected an expression to compute its aggregation over the set -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN TRUE WITH -## -## Ends in an error in state: 136. -## -## aggregate -> aggregate_func FOR ident IN primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## aggregate_func FOR ident IN primitive_expression -## -## WARNING: This example involves spurious reductions. -## This implies that, although the LR(1) items shown above provide an -## accurate view of the past (what has been recognized so far), they -## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## -expected the "for" keyword and the expression to compute the aggregate -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT IN YEAR -## -## Ends in an error in state: 134. -## -## aggregate -> aggregate_func FOR ident IN . primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## aggregate_func FOR ident IN -## - -expected an expression standing for the set over which to compute the aggregation operation - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR IDENT YEAR -## -## Ends in an error in state: 133. -## -## aggregate -> aggregate_func FOR ident . IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## aggregate_func FOR ident -## - -expected the "in" keyword - -source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM FOR YEAR -## -## Ends in an error in state: 132. -## -## aggregate -> aggregate_func FOR . ident IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] -## -## The known suffix of the stack is as follows: -## aggregate_func FOR -## - -expected an identifier for the aggregation bound variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION SUM YEAR ## -## Ends in an error in state: 131. +## Ends in an error in state: 35. ## -## aggregate -> aggregate_func . FOR ident IN primitive_expression OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] +## aggregate_func -> SUM . typ_base [ FOR ] ## ## The known suffix of the stack is as follows: -## aggregate_func +## SUM ## expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 61. +## Ends in an error in state: 70. ## ## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1534,7 +1473,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 205. +## Ends in an error in state: 214. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1545,22 +1484,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression -## In state 121, spurious reduction of production mult_expression -> base_expression -## In state 108, spurious reduction of production sum_expression -> mult_expression -## In state 84, spurious reduction of production compare_expression -> sum_expression -## In state 144, spurious reduction of production logical_expression -> compare_expression -## In state 159, spurious reduction of production expression -> logical_expression -## In state 203, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 204, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 130, spurious reduction of production mult_expression -> base_expression +## In state 117, spurious reduction of production sum_expression -> mult_expression +## In state 93, spurious reduction of production compare_expression -> sum_expression +## In state 153, spurious reduction of production logical_expression -> compare_expression +## In state 168, spurious reduction of production expression -> logical_expression +## In state 212, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 213, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 59. +## Ends in an error in state: 68. ## ## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1572,7 +1511,7 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 157. +## Ends in an error in state: 166. ## ## base_expression -> primitive_expression IN . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1584,7 +1523,7 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 121. +## Ends in an error in state: 130. ## ## mult_expression -> base_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## mult_expression -> base_expression . mult_op mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1596,15 +1535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression -## In state 63, spurious reduction of production base_expression -> primitive_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 72, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 128. +## Ends in an error in state: 137. ## ## mult_expression -> base_expression mult_op . mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1616,7 +1555,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 107. +## Ends in an error in state: 116. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1628,7 +1567,7 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 66. +## Ends in an error in state: 75. ## ## base_expression -> primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1640,7 +1579,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 147. +## Ends in an error in state: 156. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1652,7 +1591,7 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 119. +## Ends in an error in state: 128. ## ## sum_expression -> mult_expression sum_op . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1664,7 +1603,7 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 63. +## Ends in an error in state: 72. ## ## base_expression -> primitive_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## base_expression -> primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1678,14 +1617,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 58, spurious reduction of production primitive_expression -> small_expression +## In state 67, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 64. +## Ends in an error in state: 73. ## ## base_expression -> primitive_expression WITH . constructor [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1697,7 +1636,7 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 58. +## Ends in an error in state: 67. ## ## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -1819,7 +1758,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 336. +## Ends in an error in state: 337. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1831,7 +1770,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 341. +## Ends in an error in state: 342. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1843,7 +1782,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 335. +## Ends in an error in state: 336. ## ## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1855,7 +1794,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 330. +## Ends in an error in state: 331. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## @@ -1867,7 +1806,7 @@ expected an article title, another heading or some text source_file_or_master: LAW_TEXT YEAR ## -## Ends in an error in state: 345. +## Ends in an error in state: 346. ## ## list(law_intermediate_text) -> law_intermediate_text . list(law_intermediate_text) [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 16fb76a3..ee6eeac6 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -210,7 +210,7 @@ compare_op: | NOT_EQUAL { (Neq, $sloc) } aggregate_func: -| SUM { (Aggregate AggregateSum, $sloc) } +| SUM t = typ_base { (Aggregate (AggregateSum (Pos.unmark t)), $sloc) } | CARDINAL { (Aggregate AggregateCount, $sloc) } aggregate: diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index f7fe0ed8..18e6d119 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -13,11 +13,11 @@ let message s = "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" | 8 -> "expected some text, another heading or a law article\n" - | 345 -> "expected a heading, an article title or some text\n" - | 330 -> "expected an article title, another heading or some text\n" - | 335 -> "expected a code block, a metadata block, more law text or a heading\n" - | 341 -> "expected a code block, a metadata block, more law text or a heading\n" - | 336 -> "expected a declaration or a scope use\n" + | 346 -> "expected a heading, an article title or some text\n" + | 331 -> "expected an article title, another heading or some text\n" + | 336 -> "expected a code block, a metadata block, more law text or a heading\n" + | 342 -> "expected a code block, a metadata block, more law text or a heading\n" + | 337 -> "expected a declaration or a scope use\n" | 22 -> "expected the name of the scope you want to use\n" | 24 -> "expected a scope use precondition or a colon\n" | 25 -> "expected an expression which will act as the condition\n" @@ -27,144 +27,138 @@ let message s = | 30 -> "expected a \"/\"\n" | 31 -> "expected the third component of the date literal\n" | 32 -> "expected a delimiter to finish the date literal\n" - | 58 -> "expected an operator to compose the expression on the left with\n" - | 64 -> "expected an enum constructor to test if the expression on the left\n" - | 63 -> "expected an operator to compose the expression on the left with\n" - | 119 -> "expected an expression on the right side of the sum or minus operator\n" - | 147 -> "expected an expression on the right side of the logical operator\n" - | 66 -> "expected an expression for the argument of this function call\n" - | 107 -> "expected an expression on the right side of the comparison operator\n" - | 128 -> "expected an expression on the right side of the multiplication or division operator\n" - | 121 -> "expected an operator to compose the expression on the left\n" - | 157 -> "expected an expression standing for the set you want to test for membership\n" - | 59 -> "expected an identifier standing for a struct field or a subscope name\n" - | 205 -> "expected a colon after the scope use precondition\n" - | 61 -> "expected a constructor, to get the payload of this enum case\n" - | 131 -> "expected the \"for\" keyword to spell the aggregation\n" - | 132 -> "expected an identifier for the aggregation bound variable\n" - | 133 -> "expected the \"in\" keyword\n" - | 134 -> - "expected an expression standing for the set over which to compute the aggregation operation\n" - | 136 -> "expected the \"for\" keyword and the expression to compute the aggregate\n" - | 137 -> "expected an expression to compute its aggregation over the set\n" - | 141 -> "expected an expression to take the negation of\n" - | 55 -> "expected an expression to take the opposite of\n" - | 43 -> "expected an expression to match with\n" - | 189 -> "expected a pattern matching case\n" - | 190 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 196 -> + | 67 -> "expected an operator to compose the expression on the left with\n" + | 73 -> "expected an enum constructor to test if the expression on the left\n" + | 72 -> "expected an operator to compose the expression on the left with\n" + | 128 -> "expected an expression on the right side of the sum or minus operator\n" + | 156 -> "expected an expression on the right side of the logical operator\n" + | 75 -> "expected an expression for the argument of this function call\n" + | 116 -> "expected an expression on the right side of the comparison operator\n" + | 137 -> "expected an expression on the right side of the multiplication or division operator\n" + | 130 -> "expected an operator to compose the expression on the left\n" + | 166 -> "expected an expression standing for the set you want to test for membership\n" + | 68 -> "expected an identifier standing for a struct field or a subscope name\n" + | 214 -> "expected a colon after the scope use precondition\n" + | 70 -> "expected a constructor, to get the payload of this enum case\n" + | 35 -> "expected the \"for\" keyword to spell the aggregation\n" + | 150 -> "expected an expression to take the negation of\n" + | 64 -> "expected an expression to take the opposite of\n" + | 52 -> "expected an expression to match with\n" + | 198 -> "expected a pattern matching case\n" + | 199 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 205 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 197 -> "expected an identifier for this enum case binding\n" - | 193 -> "expected a colon and then the expression for this matching case\n" - | 199 -> "expected a colon or a binding for the enum constructor payload\n" - | 194 -> "expected an expression for this pattern matching case\n" - | 191 -> + | 206 -> "expected an identifier for this enum case binding\n" + | 202 -> "expected a colon and then the expression for this matching case\n" + | 208 -> "expected a colon or a binding for the enum constructor payload\n" + | 203 -> "expected an expression for this pattern matching case\n" + | 200 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 188 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 45 -> "expected an expression inside the parenthesis\n" - | 180 -> "unmatched parenthesis that should have been closed by here\n" - | 67 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 47 -> "expected an expression for the test of the conditional\n" - | 176 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 177 -> + | 197 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 54 -> "expected an expression inside the parenthesis\n" + | 189 -> "unmatched parenthesis that should have been closed by here\n" + | 76 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 56 -> "expected an expression for the test of the conditional\n" + | 185 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 186 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 178 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 175 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 49 -> + | 187 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 184 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 58 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 161 -> "expected an identifier for the bound variable of the universal test\n" - | 162 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 163 -> "expected the expression designating the set on which to perform the universal test\n" - | 164 -> "expected the \"we have\" keyword for this universal test\n" - | 160 -> "expected an expression for the universal test\n" - | 169 -> "expected an identifier that will designate the existential witness for the test\n" - | 170 -> "expected the \"in\" keyword to continue this existential test\n" - | 171 -> "expected an expression that designates the set subject to the existential test\n" - | 172 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 173 -> "expected a keyword to complete the \"such that\" construction\n" - | 167 -> "expected an expression for the existential test\n" - | 76 -> + | 170 -> "expected an identifier for the bound variable of the universal test\n" + | 171 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 172 -> "expected the expression designating the set on which to perform the universal test\n" + | 173 -> "expected the \"we have\" keyword for this universal test\n" + | 169 -> "expected an expression for the universal test\n" + | 178 -> "expected an identifier that will designate the existential witness for the test\n" + | 179 -> "expected the \"in\" keyword to continue this existential test\n" + | 180 -> "expected an expression that designates the set subject to the existential test\n" + | 181 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 182 -> "expected a keyword to complete the \"such that\" construction\n" + | 176 -> "expected an expression for the existential test\n" + | 85 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 77 -> "expected structure fields introduced by --\n" - | 78 -> "expected the name of the structure field\n" - | 82 -> "expected a colon\n" - | 83 -> "expected the expression for this struct field\n" - | 79 -> "expected another structure field or the closing bracket\n" - | 80 -> "expected the name of the structure field\n" - | 151 -> "expected an expression for the content of this enum case\n" - | 152 -> + | 86 -> "expected structure fields introduced by --\n" + | 87 -> "expected the name of the structure field\n" + | 91 -> "expected a colon\n" + | 92 -> "expected the expression for this struct field\n" + | 88 -> "expected another structure field or the closing bracket\n" + | 89 -> "expected the name of the structure field\n" + | 160 -> "expected an expression for the content of this enum case\n" + | 161 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 54 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 206 -> "expected a scope use item: a rule, definition or assertion\n" - | 241 -> "expected the name of the variable subject to the rule\n" - | 219 -> + | 63 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 215 -> "expected a scope use item: a rule, definition or assertion\n" + | 250 -> "expected the name of the variable subject to the rule\n" + | 228 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 248 -> "expected a condition or a consequence for this rule\n" - | 243 -> "expected filled or not filled for a rule consequence\n" - | 249 -> "expected the name of the parameter for this dependent variable \n" - | 242 -> "expected the expression of the rule\n" - | 246 -> "expected the filled keyword the this rule \n" - | 220 -> "expected a struct field or a sub-scope context item after the dot\n" - | 207 -> "expected the name of the label\n" - | 237 -> "expected a rule or a definition after the label declaration\n" - | 238 -> "expected the label to which the exception is referring back\n" - | 240 -> "expected a rule or a definition after the exception declaration\n" - | 253 -> "expected the name of the variable you want to define\n" - | 254 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 256 -> "expected an expression for the consequence of this definition under condition\n" - | 255 -> + | 257 -> "expected a condition or a consequence for this rule\n" + | 252 -> "expected filled or not filled for a rule consequence\n" + | 258 -> "expected the name of the parameter for this dependent variable \n" + | 251 -> "expected the expression of the rule\n" + | 255 -> "expected the filled keyword the this rule \n" + | 229 -> "expected a struct field or a sub-scope context item after the dot\n" + | 216 -> "expected the name of the label\n" + | 246 -> "expected a rule or a definition after the label declaration\n" + | 247 -> "expected the label to which the exception is referring back\n" + | 249 -> "expected a rule or a definition after the exception declaration\n" + | 262 -> "expected the name of the variable you want to define\n" + | 263 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 265 -> "expected an expression for the consequence of this definition under condition\n" + | 264 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 257 -> "expected an expression for the definition\n" - | 209 -> "expected an expression that shoud be asserted during execution\n" - | 210 -> "expecting the name of the varying variable\n" - | 213 -> "the variable varies with an expression that was expected here\n" - | 214 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 212 -> "expected an indication about what this variable varies with\n" - | 222 -> "expected an expression for this condition\n" - | 232 -> "expected a consequence for this definition under condition\n" - | 228 -> "expected an expression for this definition under condition\n" - | 224 -> "expected the name of the variable that should be fixed\n" - | 225 -> "expected the legislative text by which the value of the variable is fixed\n" - | 226 -> "expected the legislative text by which the value of the variable is fixed\n" - | 235 -> "expected a new scope use item \n" - | 264 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 265 -> "expected the struct name\n" - | 266 -> "expected a colon\n" - | 267 -> "expected struct data or condition\n" - | 268 -> "expected the name of this struct data \n" - | 269 -> "expected the type of this struct data, introduced by the content keyword\n" - | 270 -> "expected the type of this struct data\n" - | 292 -> "expected the name of this struct condition\n" - | 285 -> "expected a new struct data, or another declaration or scope use\n" - | 286 -> "expected the type of the parameter of this struct data function\n" - | 290 -> "expected a new struct data, or another declaration or scope use\n" - | 282 -> "expected a new struct data, or another declaration or scope use\n" - | 295 -> "expected the name of the scope you are declaring\n" - | 296 -> "expected a colon followed by the list of context items of this scope\n" - | 297 -> "expected a context item introduced by \"context\"\n" - | 298 -> "expected the name of this new context item\n" - | 299 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 300 -> "expected the name of the subscope for this context item\n" - | 307 -> "expected another scope context item or the end of the scope declaration\n" - | 302 -> "expected the type of this context item\n" - | 303 -> "expected the next context item or a dependency declaration for this item\n" - | 305 -> "expected the next context item or a dependency declaration for this item\n" - | 310 -> "expected the name of your enum\n" - | 311 -> "expected a colon\n" - | 312 -> "expected an enum case\n" - | 313 -> "expected the name of an enum case \n" - | 314 -> "expected a payload for your enum case, or another case or declaration \n" - | 315 -> "expected a content type\n" - | 320 -> "expected another enum case, or a new declaration or scope use\n" + | 266 -> "expected an expression for the definition\n" + | 218 -> "expected an expression that shoud be asserted during execution\n" + | 219 -> "expecting the name of the varying variable\n" + | 222 -> "the variable varies with an expression that was expected here\n" + | 223 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 221 -> "expected an indication about what this variable varies with\n" + | 231 -> "expected an expression for this condition\n" + | 241 -> "expected a consequence for this definition under condition\n" + | 237 -> "expected an expression for this definition under condition\n" + | 233 -> "expected the name of the variable that should be fixed\n" + | 234 -> "expected the legislative text by which the value of the variable is fixed\n" + | 235 -> "expected the legislative text by which the value of the variable is fixed\n" + | 244 -> "expected a new scope use item \n" + | 273 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 274 -> "expected the struct name\n" + | 275 -> "expected a colon\n" + | 276 -> "expected struct data or condition\n" + | 277 -> "expected the name of this struct data \n" + | 278 -> "expected the type of this struct data, introduced by the content keyword\n" + | 279 -> "expected the type of this struct data\n" + | 293 -> "expected the name of this struct condition\n" + | 286 -> "expected a new struct data, or another declaration or scope use\n" + | 287 -> "expected the type of the parameter of this struct data function\n" + | 291 -> "expected a new struct data, or another declaration or scope use\n" + | 283 -> "expected a new struct data, or another declaration or scope use\n" + | 296 -> "expected the name of the scope you are declaring\n" + | 297 -> "expected a colon followed by the list of context items of this scope\n" + | 298 -> "expected a context item introduced by \"context\"\n" + | 299 -> "expected the name of this new context item\n" + | 300 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 301 -> "expected the name of the subscope for this context item\n" + | 308 -> "expected another scope context item or the end of the scope declaration\n" + | 303 -> "expected the type of this context item\n" + | 304 -> "expected the next context item or a dependency declaration for this item\n" + | 306 -> "expected the next context item or a dependency declaration for this item\n" + | 311 -> "expected the name of your enum\n" + | 312 -> "expected a colon\n" + | 313 -> "expected an enum case\n" + | 314 -> "expected the name of an enum case \n" + | 315 -> "expected a payload for your enum case, or another case or declaration \n" + | 316 -> "expected a content type\n" + | 321 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" | 19 -> "expected some text or the beginning of a code section\n" | 20 -> "expected a declaration or a scope use\n" | 21 -> "should not happen\n" - | 326 -> "expected a metadata-closing tag\n" | 327 -> "expected a metadata-closing tag\n" + | 328 -> "expected a metadata-closing tag\n" | _ -> raise Not_found diff --git a/src/catala/catala_surface/print.ml b/src/catala/catala_surface/print.ml new file mode 100644 index 00000000..5e7751b4 --- /dev/null +++ b/src/catala/catala_surface/print.ml @@ -0,0 +1,26 @@ +(* This file is part of the Catala compiler, a specification language for tax and social benefits + computation rules. Copyright (C) 2020 Inria, contributor: Denis Merigoux + + + 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 Ast + +let format_primitive_typ (fmt : Format.formatter) (t : primitive_typ) : unit = + match t with + | Integer -> Format.fprintf fmt "integer" + | Decimal -> Format.fprintf fmt "decimal" + | Boolean -> Format.fprintf fmt "boolean" + | Money -> Format.fprintf fmt "money" + | Duration -> Format.fprintf fmt "duration" + | Text -> Format.fprintf fmt "text" + | Date -> Format.fprintf fmt "date" + | Named constructor -> Format.fprintf fmt "%s" constructor diff --git a/tests/test_array/aggregation.catala b/tests/test_array/aggregation.catala new file mode 100644 index 00000000..3ed64125 --- /dev/null +++ b/tests/test_array/aggregation.catala @@ -0,0 +1,18 @@ +@Article@ + +/* +new scope A: + param x content set money + +scope A: + def x := [$0; $4 +$ $5; $8 *$ 0.65] + +new scope B: + param a scope A + param y content money + param z content int + +scope B: + def y := sum money for m in a.x of (m +$ $1) + def z := number for m in a.x of (m >=$ $8.95) +*/ \ No newline at end of file diff --git a/tests/test_array/aggregation.catala.A.out b/tests/test_array/aggregation.catala.A.out new file mode 100644 index 00000000..8dbf5aeb --- /dev/null +++ b/tests/test_array/aggregation.catala.A.out @@ -0,0 +1,2 @@ +[RESULT] Computation successful! Results: +[RESULT] x = [$0.00; $9.00; $5.20] diff --git a/tests/test_array/aggregation.catala.B.out b/tests/test_array/aggregation.catala.B.out new file mode 100644 index 00000000..5e8aef0b --- /dev/null +++ b/tests/test_array/aggregation.catala.B.out @@ -0,0 +1,3 @@ +[RESULT] Computation successful! Results: +[RESULT] y = $17.20 +[RESULT] z = 1 diff --git a/tests/test_array/simple.catala.A.out b/tests/test_array/simple.catala.A.out index 5a826abe..ee019865 100644 --- a/tests/test_array/simple.catala.A.out +++ b/tests/test_array/simple.catala.A.out @@ -1,2 +1,2 @@ [RESULT] Computation successful! Results: -[RESULT] x = [0;9;64] +[RESULT] x = [0; 9; 64] diff --git a/tests/test_dec/simple.catala.A.out b/tests/test_dec/simple.catala.A.out index ccba3f94..025fb8a9 100644 --- a/tests/test_dec/simple.catala.A.out +++ b/tests/test_dec/simple.catala.A.out @@ -1,4 +1,4 @@ [RESULT] Computation successful! Results: -[RESULT] x = 84.0648665 +[RESULT] x = 84.648665 [RESULT] y = 4.368297 -[RESULT] z = 19.24431111254569000230… +[RESULT] z = 19.37795552820698775747… From 7318b51e25f7eb7474b1ba54e19f74f4aa0c33f2 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 30 Dec 2020 01:02:04 +0100 Subject: [PATCH 130/142] Debugging unification... --- src/catala/default_calculus/typing.ml | 92 ++++++++++++++----------- tests/test_array/fold_error.catala | 11 +++ tests/test_money/no_mingle.catala.A.out | 4 +- 3 files changed, 65 insertions(+), 42 deletions(-) create mode 100644 tests/test_array/fold_error.catala diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index f0194527..3422f6c5 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -68,31 +68,45 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked UnionFind.elem (** Raises an error if unification cannot be performed *) let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = - (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) + Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in - match (t1_repr, t2_repr) with - | (TLit tl1, _), (TLit tl2, _) when tl1 = tl2 -> () - | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> - unify t11 t21; - unify t12 t22 - | (TTuple ts1, _), (TTuple ts2, _) -> List.iter2 unify ts1 ts2 - | (TEnum ts1, _), (TEnum ts2, _) -> List.iter2 unify ts1 ts2 - | (TArray t1', _), (TArray t2', _) -> unify t1' t2' - | (TAny _, _), (TAny _, _) -> ignore (UnionFind.union t1 t2) - | (TAny _, _), t_repr | t_repr, (TAny _, _) -> - let t_union = UnionFind.union t1 t2 in - ignore (UnionFind.set t_union t_repr) - | (_, t1_pos), (_, t2_pos) -> - (* TODO: if we get weird error messages, then it means that we should use the persistent - version of the union-find data structure. *) - Errors.raise_multispanned_error - (Format.asprintf "Error during typechecking, types %a and %a are incompatible" format_typ t1 - format_typ t2) - [ - (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); - (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); - ] + let repr = + match (t1_repr, t2_repr) with + | (TLit tl1, _), (TLit tl2, _) when tl1 = tl2 -> None + | (TArrow (t11, t12), _), (TArrow (t21, t22), _) -> + unify t11 t21; + unify t12 t22; + None + | (TTuple ts1, _), (TTuple ts2, _) -> + List.iter2 unify ts1 ts2; + None + | (TEnum ts1, _), (TEnum ts2, _) -> + List.iter2 unify ts1 ts2; + None + | (TArray t1', _), (TArray t2', _) -> + unify t1' t2'; + None + | (TAny _, _), (TAny _, _) -> None + | (TAny _, _), t_repr | t_repr, (TAny _, _) -> Some t_repr + | (_, t1_pos), (_, t2_pos) -> + (* TODO: if we get weird error messages, then it means that we should use the persistent + version of the union-find data structure. *) + Errors.raise_multispanned_error + (Format.asprintf "Error during typechecking, types %a and %a are incompatible" format_typ + t1 format_typ t2) + [ + (Some (Format.asprintf "Type %a coming from expression:" format_typ t1), t1_pos); + (Some (Format.asprintf "Type %a coming from expression:" format_typ t2), t2_pos); + ] + in + let t_union = UnionFind.union t1 t2 in + match repr with + | None -> () + | Some t_repr -> + Cli.debug_print + (Format.asprintf "Setting %a to %a" format_typ t_union format_typ (UnionFind.make t_repr)); + UnionFind.set t_union t_repr (** Operators have a single type, instead of being polymorphic with constraints. This allows us to have a simpler type system, while we argue the syntactic burden of operator annotations helps @@ -236,18 +250,16 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m | EAbs (pos_binder, binder, taus) -> let xs, body = Bindlib.unmbind binder in if Array.length xs = List.length taus then - let xstaus = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - let env = - List.fold_left - (fun env (x, tau) -> - A.VarMap.add x (ast_to_typ (Pos.unmark tau), Pos.get_position tau) env) - env xstaus + let xstaus = + List.map2 + (fun x tau -> (x, (ast_to_typ (Pos.unmark tau), Pos.get_position tau))) + (Array.to_list xs) taus in + let env = List.fold_left (fun env (x, tau) -> A.VarMap.add x tau env) env xstaus in List.fold_right - (fun t_arg (acc : typ Pos.marked UnionFind.elem) -> - UnionFind.make - (TArrow (UnionFind.make (Pos.map_under_mark ast_to_typ t_arg), acc), pos_binder)) - taus + (fun (_, t_arg) (acc : typ Pos.marked UnionFind.elem) -> + UnionFind.make (TArrow (UnionFind.make t_arg, acc), pos_binder)) + xstaus (typecheck_expr_bottom_up env body) else Errors.raise_spanned_error @@ -287,13 +299,13 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m es; UnionFind.make (Pos.same_pos_as (TArray cell_type) e) in - (* Cli.debug_print (Format.asprintf "Found type of %a: %a" Print.format_expr e format_typ out); *) + Cli.debug_print (Format.asprintf "Found type of %a: %a" Print.format_expr e format_typ out); out (** Checks whether the expression can be typed with the provided type *) and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = - (* Cli.debug_print (Format.asprintf "Typechecking %a : %a" Print.format_expr e format_typ tau); *) + Cli.debug_print (Format.asprintf "Typechecking %a : %a" Print.format_expr e format_typ tau); match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt (Pos.unmark v) env with @@ -376,12 +388,12 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) | EAbs (pos_binder, binder, t_args) -> let xs, body = Bindlib.unmbind binder in if Array.length xs = List.length t_args then - let xstaus = List.map2 (fun x t_arg -> (x, t_arg)) (Array.to_list xs) t_args in - let env = - List.fold_left - (fun env (x, t_arg) -> A.VarMap.add x (ast_to_typ (Pos.unmark t_arg), pos_binder) env) - env xstaus + let xstaus = + List.map2 + (fun x t_arg -> (x, Pos.map_under_mark ast_to_typ t_arg)) + (Array.to_list xs) t_args in + let env = List.fold_left (fun env (x, t_arg) -> A.VarMap.add x t_arg env) env xstaus in let t_out = typecheck_expr_bottom_up env body in let t_func = List.fold_right diff --git a/tests/test_array/fold_error.catala b/tests/test_array/fold_error.catala new file mode 100644 index 00000000..f2179c06 --- /dev/null +++ b/tests/test_array/fold_error.catala @@ -0,0 +1,11 @@ +@Article@ + +/* +new scope A: + param list content set int + param list_high_count content int + +scope A: + def list := [0; 5; 6; 7; 1; 64; 12] + def list_high_count := number for m in list of (m >=$ $7) +*/ \ No newline at end of file diff --git a/tests/test_money/no_mingle.catala.A.out b/tests/test_money/no_mingle.catala.A.out index 54266e36..f22b4673 100644 --- a/tests/test_money/no_mingle.catala.A.out +++ b/tests/test_money/no_mingle.catala.A.out @@ -9,5 +9,5 @@ [ERROR] Type money coming from expression: [ERROR] --> test_money/no_mingle.catala [ERROR] | -[ERROR] 4 | new scope A: -[ERROR] | ^ +[ERROR] 6 | param y content money +[ERROR] | ^^^^^ From 2cfb3482740cb996c5993a8b85b2e9bfd83e6b16 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 30 Dec 2020 01:13:28 +0100 Subject: [PATCH 131/142] Debugged unification and typing --- src/catala/default_calculus/typing.ml | 33 +++++++++--------------- tests/test_array/fold_error.catala.A.out | 13 ++++++++++ 2 files changed, 25 insertions(+), 21 deletions(-) create mode 100644 tests/test_array/fold_error.catala.A.out diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index 3422f6c5..e16bb869 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -68,7 +68,7 @@ let rec format_typ (fmt : Format.formatter) (typ : typ Pos.marked UnionFind.elem (** Raises an error if unification cannot be performed *) let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFind.elem) : unit = - Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); + (* Cli.debug_print (Format.asprintf "Unifying %a and %a" format_typ t1 format_typ t2); *) let t1_repr = UnionFind.get (UnionFind.find t1) in let t2_repr = UnionFind.get (UnionFind.find t2) in let repr = @@ -101,12 +101,7 @@ let rec unify (t1 : typ Pos.marked UnionFind.elem) (t2 : typ Pos.marked UnionFin ] in let t_union = UnionFind.union t1 t2 in - match repr with - | None -> () - | Some t_repr -> - Cli.debug_print - (Format.asprintf "Setting %a to %a" format_typ t_union format_typ (UnionFind.make t_repr)); - UnionFind.set t_union t_repr + match repr with None -> () | Some t_repr -> UnionFind.set t_union t_repr (** Operators have a single type, instead of being polymorphic with constraints. This allows us to have a simpler type system, while we argue the syntactic burden of operator annotations helps @@ -179,7 +174,7 @@ let rec typ_to_ast (ty : typ Pos.marked UnionFind.elem) : A.typ Pos.marked = (** {1 Double-directed typing} *) -type env = typ Pos.marked A.VarMap.t +type env = typ Pos.marked UnionFind.elem A.VarMap.t (** Infers the most permissive type from an expression *) let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.marked UnionFind.elem @@ -188,7 +183,7 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt (Pos.unmark v) env with - | Some t -> UnionFind.make t + | Some t -> t | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) @@ -252,13 +247,13 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m if Array.length xs = List.length taus then let xstaus = List.map2 - (fun x tau -> (x, (ast_to_typ (Pos.unmark tau), Pos.get_position tau))) + (fun x tau -> (x, UnionFind.make (ast_to_typ (Pos.unmark tau), Pos.get_position tau))) (Array.to_list xs) taus in let env = List.fold_left (fun env (x, tau) -> A.VarMap.add x tau env) env xstaus in List.fold_right (fun (_, t_arg) (acc : typ Pos.marked UnionFind.elem) -> - UnionFind.make (TArrow (UnionFind.make t_arg, acc), pos_binder)) + UnionFind.make (TArrow (t_arg, acc), pos_binder)) xstaus (typecheck_expr_bottom_up env body) else @@ -299,17 +294,17 @@ let rec typecheck_expr_bottom_up (env : env) (e : A.expr Pos.marked) : typ Pos.m es; UnionFind.make (Pos.same_pos_as (TArray cell_type) e) in - Cli.debug_print (Format.asprintf "Found type of %a: %a" Print.format_expr e format_typ out); + (* Cli.debug_print (Format.asprintf "Found type of %a: %a" Print.format_expr e format_typ out); *) out (** Checks whether the expression can be typed with the provided type *) and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) (tau : typ Pos.marked UnionFind.elem) : unit = - Cli.debug_print (Format.asprintf "Typechecking %a : %a" Print.format_expr e format_typ tau); + (* Cli.debug_print (Format.asprintf "Typechecking %a : %a" Print.format_expr e format_typ tau); *) match Pos.unmark e with | EVar v -> ( match A.VarMap.find_opt (Pos.unmark v) env with - | Some tau' -> ignore (unify tau (UnionFind.make tau')) + | Some tau' -> ignore (unify tau tau') | None -> Errors.raise_spanned_error "Variable not found in the current context" (Pos.get_position e) ) @@ -390,19 +385,15 @@ and typecheck_expr_top_down (env : env) (e : A.expr Pos.marked) if Array.length xs = List.length t_args then let xstaus = List.map2 - (fun x t_arg -> (x, Pos.map_under_mark ast_to_typ t_arg)) + (fun x t_arg -> (x, UnionFind.make (Pos.map_under_mark ast_to_typ t_arg))) (Array.to_list xs) t_args in let env = List.fold_left (fun env (x, t_arg) -> A.VarMap.add x t_arg env) env xstaus in let t_out = typecheck_expr_bottom_up env body in let t_func = List.fold_right - (fun t_arg acc -> - UnionFind.make - (Pos.same_pos_as - (TArrow (UnionFind.make (ast_to_typ (Pos.unmark t_arg), pos_binder), acc)) - e)) - t_args t_out + (fun (_, t_arg) acc -> UnionFind.make (Pos.same_pos_as (TArrow (t_arg, acc)) e)) + xstaus t_out in unify t_func tau else diff --git a/tests/test_array/fold_error.catala.A.out b/tests/test_array/fold_error.catala.A.out new file mode 100644 index 00000000..49bdd846 --- /dev/null +++ b/tests/test_array/fold_error.catala.A.out @@ -0,0 +1,13 @@ +[ERROR] Error during typechecking, types money and integer are incompatible +[ERROR] +[ERROR] Type money coming from expression: +[ERROR] --> test_array/fold_error.catala +[ERROR] | +[ERROR] 10 | def list_high_count := number for m in list of (m >=$ $7) +[ERROR] | ^^^ +[ERROR] +[ERROR] Type integer coming from expression: +[ERROR] --> test_array/fold_error.catala +[ERROR] | +[ERROR] 5 | param list content set int +[ERROR] | ^^^^^^^ From be9e7e2a1e14adef24ea8915ae47f89fa6d9a272 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 30 Dec 2020 11:50:19 +0100 Subject: [PATCH 132/142] Added collection length and mem test --- src/catala/catala_surface/ast.ml | 2 +- src/catala/catala_surface/desugaring.ml | 46 +- src/catala/catala_surface/lexer.ml | 4 - src/catala/catala_surface/lexer_en.ml | 4 - src/catala/catala_surface/lexer_fr.ml | 4 - src/catala/catala_surface/parser.messages | 418 +++++++++--------- src/catala/catala_surface/parser.mly | 3 +- src/catala/catala_surface/parser_errors.ml | 238 +++++----- syntax_highlighting/en/ace/mode-catala_en.js | 2 +- .../en/atom/grammars/catala_en.cson | 2 +- syntax_highlighting/en/catala_en.iro | 2 +- syntax_highlighting/en/pygments/catala_en.py | 2 +- .../en/vscode/syntaxes/catalavs.xml | 2 +- syntax_highlighting/fr/ace/mode-catala_fr.js | 2 +- .../fr/atom/grammars/catala_fr.cson | 2 +- syntax_highlighting/fr/catala_fr.iro | 2 +- syntax_highlighting/fr/pygments/catala_fr.py | 2 +- .../fr/vscode/syntaxes/catalavs.xml | 2 +- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 2 +- .../nv/vscode/syntaxes/catalavs.xml | 2 +- tests/test_array/simple.catala | 4 + 23 files changed, 393 insertions(+), 358 deletions(-) diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index c99771ae..00ac832e 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -87,7 +87,7 @@ type binop = type unop = Not | Minus of op_kind -type builtin_expression = Cardinal | Now +type builtin_expression = Cardinal type aggregate_func = AggregateSum of primitive_typ | AggregateCount diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index 9a252ba8..c4971581 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -410,7 +410,12 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti ( Scopelang.Ast.EAbs ( pos, binder, - [ (Scopelang.Ast.TLit t, Pos.get_position op'); (Scopelang.Ast.TAny, pos) ] ), + [ + (Scopelang.Ast.TLit t, Pos.get_position op'); + (Scopelang.Ast.TAny, pos) + (* we put any here because the type of the elements of the arrays is not + always the type of the accumulator; for instance in AggregateCount. *); + ] ), pos )) (Bindlib.bind_mvar [| acc_var; param |] f_body) in @@ -429,6 +434,45 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti ((Scopelang.Ast.EOp (Dcalc.Ast.Ternop Dcalc.Ast.Fold), pos), [ f; init; collection ]), pos )) f collection init + | MemCollection (member, collection) -> + let param_var = Scopelang.Ast.Var.make ("collection_member", pos) in + let param = Scopelang.Ast.make_var (param_var, pos) in + let collection = rec_helper collection in + let init = Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos) in + let acc_var = Scopelang.Ast.Var.make ("acc", pos) in + let acc = Scopelang.Ast.make_var (acc_var, pos) in + let f_body = + Bindlib.box_apply3 + (fun member acc param -> + ( Scopelang.Ast.EApp + ( (Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.Or), pos), + [ + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Binop Dcalc.Ast.Eq), pos), [ member; param ]), + pos ); + acc; + ] ), + pos )) + (translate_expr scope ctxt member) + acc param + in + let f = + Bindlib.box_apply + (fun binder -> + ( Scopelang.Ast.EAbs + ( pos, + binder, + [ (Scopelang.Ast.TLit Dcalc.Ast.TBool, pos); (Scopelang.Ast.TAny, pos) ] ), + pos )) + (Bindlib.bind_mvar [| acc_var; param_var |] f_body) + in + Bindlib.box_apply3 + (fun f collection init -> + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Ternop Dcalc.Ast.Fold), pos), [ f; init; collection ]), + pos )) + f collection init + | Builtin Cardinal -> Bindlib.box (Scopelang.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.Length), pos) | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented for this expression" pos diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index a656cbbf..d35b6b1b 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -113,7 +113,6 @@ let token_list : (string * token) list = ("exists", EXISTS); ("such", SUCH); ("that", THAT); - ("now", NOW); ("&&", AND); ("||", OR); ("not", NOT); @@ -279,9 +278,6 @@ let rec lex_code (lexbuf : lexbuf) : token = | "that" -> update_acc lexbuf; THAT - | "now" -> - update_acc lexbuf; - NOW | "&&" -> update_acc lexbuf; AND diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 2952626f..78bda516 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -67,7 +67,6 @@ let token_list_en : (string * token) list = ("exists", EXISTS); ("such", SUCH); ("that", THAT); - ("now", NOW); ("and", AND); ("or", OR); ("not", NOT); @@ -236,9 +235,6 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "that" -> L.update_acc lexbuf; THAT - | "now" -> - L.update_acc lexbuf; - NOW | "and" -> L.update_acc lexbuf; AND diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 4107bccd..87cace82 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -65,7 +65,6 @@ let token_list_fr : (string * token) list = ("existe", EXISTS); ("tel", SUCH); ("que", THAT); - ("maintenant", NOW); ("et", AND); ("ou", OR); ("non", NOT); @@ -240,9 +239,6 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "que" -> L.update_acc lexbuf; THAT - | "maintenant" -> - L.update_acc lexbuf; - NOW | "et" -> L.update_acc lexbuf; AND diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index 93d3ee2d..b6ffb9f5 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE LAW_TEXT END_CODE ## -## Ends in an error in state: 328. +## Ends in an error in state: 327. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE option(law_text) . END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -12,7 +12,7 @@ expected a metadata-closing tag source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 327. +## Ends in an error in state: 326. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -72,7 +72,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 321. +## Ends in an error in state: 320. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -85,7 +85,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 316. +## Ends in an error in state: 315. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -97,7 +97,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 315. +## Ends in an error in state: 314. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -109,7 +109,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 314. +## Ends in an error in state: 313. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -121,7 +121,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 313. +## Ends in an error in state: 312. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -133,7 +133,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 312. +## Ends in an error in state: 311. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -145,7 +145,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 311. +## Ends in an error in state: 310. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -157,7 +157,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 306. +## Ends in an error in state: 305. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -169,7 +169,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 304. +## Ends in an error in state: 303. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -181,7 +181,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 303. +## Ends in an error in state: 302. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -193,7 +193,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 308. +## Ends in an error in state: 307. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -206,7 +206,7 @@ expected another scope context item or the end of the scope declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 301. +## Ends in an error in state: 300. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -218,7 +218,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 300. +## Ends in an error in state: 299. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -232,7 +232,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 298. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -246,7 +246,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 297. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -258,7 +258,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 297. +## Ends in an error in state: 296. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -270,7 +270,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 296. +## Ends in an error in state: 295. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 283. +## Ends in an error in state: 282. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -295,7 +295,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 291. +## Ends in an error in state: 290. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -307,7 +307,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 287. +## Ends in an error in state: 286. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -319,7 +319,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 285. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -331,7 +331,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 293. +## Ends in an error in state: 292. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -343,7 +343,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 279. +## Ends in an error in state: 278. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -355,7 +355,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 278. +## Ends in an error in state: 277. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -367,7 +367,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 277. +## Ends in an error in state: 276. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -379,7 +379,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 276. +## Ends in an error in state: 275. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -391,7 +391,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 275. +## Ends in an error in state: 274. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -403,7 +403,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 274. +## Ends in an error in state: 273. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -415,7 +415,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 272. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -429,7 +429,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 244. +## Ends in an error in state: 243. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -441,23 +441,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 63, spurious reduction of production primitive_expression -> CARDINAL -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression -## In state 238, spurious reduction of production assertion_base -> expression -## In state 239, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 243, spurious reduction of production scope_item -> ASSERTION assertion +## In state 62, spurious reduction of production primitive_expression -> CARDINAL +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression +## In state 237, spurious reduction of production assertion_base -> expression +## In state 238, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 242, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 235. +## Ends in an error in state: 234. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -469,7 +469,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 234. +## Ends in an error in state: 233. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -480,15 +480,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 233. +## Ends in an error in state: 232. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -500,7 +500,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 237. +## Ends in an error in state: 236. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -512,9 +512,9 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 241. +## Ends in an error in state: 240. ## -## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## condition @@ -523,21 +523,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 63, spurious reduction of production primitive_expression -> CARDINAL -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression -## In state 232, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 62, spurious reduction of production primitive_expression -> CARDINAL +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression +## In state 231, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 231. +## Ends in an error in state: 230. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -549,7 +549,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 221. +## Ends in an error in state: 220. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -560,15 +560,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 223. +## Ends in an error in state: 222. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -579,15 +579,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 222. +## Ends in an error in state: 221. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -599,7 +599,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 219. +## Ends in an error in state: 218. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -611,7 +611,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 218. +## Ends in an error in state: 217. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -623,7 +623,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 266. +## Ends in an error in state: 265. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -635,7 +635,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 264. +## Ends in an error in state: 263. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -647,7 +647,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 265. +## Ends in an error in state: 264. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -659,7 +659,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 263. +## Ends in an error in state: 262. ## ## definition -> option(label) option(exception_to) DEFINITION qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -670,15 +670,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 262. +## Ends in an error in state: 261. ## ## definition -> option(label) option(exception_to) DEFINITION . qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -690,7 +690,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION IDENT DEFINED_AS ## -## Ends in an error in state: 249. +## Ends in an error in state: 248. ## ## definition -> option(label) option(exception_to) . DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) option(exception_to) . RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -703,7 +703,7 @@ expected a rule or a definition after the exception declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION YEAR ## -## Ends in an error in state: 247. +## Ends in an error in state: 246. ## ## exception_to -> EXCEPTION . ident [ RULE DEFINITION ] ## @@ -715,7 +715,7 @@ expected the label to which the exception is referring back source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL IDENT DEFINED_AS ## -## Ends in an error in state: 246. +## Ends in an error in state: 245. ## ## definition -> option(label) . option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) . option(exception_to) RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -728,7 +728,7 @@ expected a rule or a definition after the label declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL YEAR ## -## Ends in an error in state: 216. +## Ends in an error in state: 215. ## ## label -> LABEL . ident [ RULE EXCEPTION DEFINITION ] ## @@ -740,7 +740,7 @@ expected the name of the label source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 229. +## Ends in an error in state: 228. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -752,7 +752,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 255. +## Ends in an error in state: 254. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -764,7 +764,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 251. +## Ends in an error in state: 250. ## ## rule -> option(label) option(exception_to) RULE rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -776,7 +776,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 258. +## Ends in an error in state: 257. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -788,7 +788,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 252. +## Ends in an error in state: 251. ## ## rule -> option(label) option(exception_to) RULE rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -800,7 +800,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 257. +## Ends in an error in state: 256. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -811,15 +811,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 228, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 220, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 228. +## Ends in an error in state: 227. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -832,7 +832,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 249. ## ## rule -> option(label) option(exception_to) RULE . rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -844,7 +844,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 214. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -856,7 +856,7 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 63. +## Ends in an error in state: 62. ## ## aggregate_func -> CARDINAL . [ FOR ] ## primitive_expression -> CARDINAL . [ WITH THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -869,7 +869,7 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 161. +## Ends in an error in state: 160. ## ## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -883,7 +883,7 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 159. ## ## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -896,7 +896,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL ALT YEAR ## -## Ends in an error in state: 89. +## Ends in an error in state: 88. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] ## @@ -908,7 +908,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL THEN ## -## Ends in an error in state: 88. +## Ends in an error in state: 87. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RBRACKET ] ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] @@ -920,20 +920,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 63, spurious reduction of production primitive_expression -> CARDINAL -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 152, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 62, spurious reduction of production primitive_expression -> CARDINAL +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 151, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another structure field or the closing bracket source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON YEAR ## -## Ends in an error in state: 92. +## Ends in an error in state: 91. ## ## struct_content_field -> ident COLON . logical_expression [ RBRACKET ALT ] ## @@ -945,7 +945,7 @@ expected the expression for this struct field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT YEAR ## -## Ends in an error in state: 91. +## Ends in an error in state: 90. ## ## struct_content_field -> ident . COLON logical_expression [ RBRACKET ALT ] ## @@ -957,7 +957,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT YEAR ## -## Ends in an error in state: 87. +## Ends in an error in state: 86. ## ## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -969,7 +969,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET YEAR ## -## Ends in an error in state: 86. +## Ends in an error in state: 85. ## ## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -981,7 +981,7 @@ expected structure fields introduced by -- source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 85. +## Ends in an error in state: 84. ## ## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -993,7 +993,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 176. +## Ends in an error in state: 175. ## ## expression -> exists_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1005,9 +1005,9 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 182. +## Ends in an error in state: 181. ## -## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression SUCH @@ -1017,9 +1017,9 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 181. +## Ends in an error in state: 180. ## -## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression @@ -1028,16 +1028,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 180. +## Ends in an error in state: 179. ## -## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN @@ -1047,9 +1047,9 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 179. +## Ends in an error in state: 178. ## -## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident @@ -1059,9 +1059,9 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 178. +## Ends in an error in state: 177. ## -## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked @@ -1071,7 +1071,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 168. ## ## expression -> forall_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1083,9 +1083,9 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 173. +## Ends in an error in state: 172. ## -## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN primitive_expression @@ -1094,16 +1094,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 172. +## Ends in an error in state: 171. ## -## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN @@ -1113,9 +1113,9 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 171. +## Ends in an error in state: 170. ## -## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident @@ -1125,9 +1125,9 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 170. +## Ends in an error in state: 169. ## -## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOW NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked @@ -1137,7 +1137,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 58. +## Ends in an error in state: 57. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -1149,7 +1149,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 184. +## Ends in an error in state: 183. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1160,20 +1160,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 187. +## Ends in an error in state: 186. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1185,7 +1185,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 186. +## Ends in an error in state: 185. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1196,20 +1196,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 185. +## Ends in an error in state: 184. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1221,7 +1221,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 56. +## Ends in an error in state: 55. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1233,7 +1233,7 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 76. +## Ends in an error in state: 75. ## ## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1245,7 +1245,7 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 189. +## Ends in an error in state: 188. ## ## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1256,20 +1256,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 54. +## Ends in an error in state: 53. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1281,7 +1281,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 197. +## Ends in an error in state: 196. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1292,14 +1292,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 200. +## Ends in an error in state: 199. ## ## match_arms -> ALT match_arm . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1310,20 +1310,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 151, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 204, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 150, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 203, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 203. +## Ends in an error in state: 202. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1335,7 +1335,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 208. +## Ends in an error in state: 207. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1347,7 +1347,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 202. +## Ends in an error in state: 201. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1359,7 +1359,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 206. +## Ends in an error in state: 205. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1372,7 +1372,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 205. +## Ends in an error in state: 204. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1384,7 +1384,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 199. +## Ends in an error in state: 198. ## ## match_arms -> ALT . match_arm match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1396,7 +1396,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 198. +## Ends in an error in state: 197. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1408,7 +1408,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 52. +## Ends in an error in state: 51. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1420,7 +1420,7 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 64. +## Ends in an error in state: 63. ## ## sum_expression -> sum_unop . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1432,7 +1432,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 150. +## Ends in an error in state: 149. ## ## logical_expression -> logical_unop . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1461,7 +1461,7 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 70. +## Ends in an error in state: 69. ## ## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1473,7 +1473,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 214. +## Ends in an error in state: 213. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1484,22 +1484,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression -## In state 130, spurious reduction of production mult_expression -> base_expression -## In state 117, spurious reduction of production sum_expression -> mult_expression -## In state 93, spurious reduction of production compare_expression -> sum_expression -## In state 153, spurious reduction of production logical_expression -> compare_expression -## In state 168, spurious reduction of production expression -> logical_expression -## In state 212, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 213, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 129, spurious reduction of production mult_expression -> base_expression +## In state 116, spurious reduction of production sum_expression -> mult_expression +## In state 92, spurious reduction of production compare_expression -> sum_expression +## In state 152, spurious reduction of production logical_expression -> compare_expression +## In state 167, spurious reduction of production expression -> logical_expression +## In state 211, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 212, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 68. +## Ends in an error in state: 67. ## ## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1511,7 +1511,7 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 166. +## Ends in an error in state: 165. ## ## base_expression -> primitive_expression IN . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1523,7 +1523,7 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 130. +## Ends in an error in state: 129. ## ## mult_expression -> base_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## mult_expression -> base_expression . mult_op mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1535,15 +1535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression -## In state 72, spurious reduction of production base_expression -> primitive_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 137. +## Ends in an error in state: 136. ## ## mult_expression -> base_expression mult_op . mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1555,7 +1555,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 116. +## Ends in an error in state: 115. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1567,7 +1567,7 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 75. +## Ends in an error in state: 74. ## ## base_expression -> primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1579,7 +1579,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 156. +## Ends in an error in state: 155. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1591,7 +1591,7 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 128. +## Ends in an error in state: 127. ## ## sum_expression -> mult_expression sum_op . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1603,7 +1603,7 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 72. +## Ends in an error in state: 71. ## ## base_expression -> primitive_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## base_expression -> primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1617,14 +1617,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 67, spurious reduction of production primitive_expression -> small_expression +## In state 66, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 73. +## Ends in an error in state: 72. ## ## base_expression -> primitive_expression WITH . constructor [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1636,7 +1636,7 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 67. +## Ends in an error in state: 66. ## ## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -1758,7 +1758,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 337. +## Ends in an error in state: 336. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1770,7 +1770,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 342. +## Ends in an error in state: 341. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1782,7 +1782,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 336. +## Ends in an error in state: 335. ## ## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1794,7 +1794,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 331. +## Ends in an error in state: 330. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## @@ -1806,7 +1806,7 @@ expected an article title, another heading or some text source_file_or_master: LAW_TEXT YEAR ## -## Ends in an error in state: 346. +## Ends in an error in state: 345. ## ## list(law_intermediate_text) -> law_intermediate_text . list(law_intermediate_text) [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index ee6eeac6..218cedda 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -47,7 +47,7 @@ %token LESSER_MONEY GREATER_MONEY LESSER_EQUAL_MONEY GREATER_EQUAL_MONEY %token LESSER_DATE GREATER_DATE LESSER_EQUAL_DATE GREATER_EQUAL_DATE %token LESSER_DURATION GREATER_DURATION LESSER_EQUAL_DURATION GREATER_EQUAL_DURATION -%token EXISTS IN SUCH THAT NOW +%token EXISTS IN SUCH THAT %token DOT AND OR LPAREN RPAREN EQUAL %token CARDINAL ASSERTION FIXED BY YEAR MONTH DAY %token PLUS MINUS MULT DIV @@ -137,7 +137,6 @@ struct_or_enum_inject: primitive_expression: | e = small_expression { e } -| NOW { (Builtin Now, $sloc) } | CARDINAL { (Builtin Cardinal, $sloc) } diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 18e6d119..31f89845 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -13,11 +13,11 @@ let message s = "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" | 8 -> "expected some text, another heading or a law article\n" - | 346 -> "expected a heading, an article title or some text\n" - | 331 -> "expected an article title, another heading or some text\n" - | 336 -> "expected a code block, a metadata block, more law text or a heading\n" - | 342 -> "expected a code block, a metadata block, more law text or a heading\n" - | 337 -> "expected a declaration or a scope use\n" + | 345 -> "expected a heading, an article title or some text\n" + | 330 -> "expected an article title, another heading or some text\n" + | 335 -> "expected a code block, a metadata block, more law text or a heading\n" + | 341 -> "expected a code block, a metadata block, more law text or a heading\n" + | 336 -> "expected a declaration or a scope use\n" | 22 -> "expected the name of the scope you want to use\n" | 24 -> "expected a scope use precondition or a colon\n" | 25 -> "expected an expression which will act as the condition\n" @@ -27,138 +27,138 @@ let message s = | 30 -> "expected a \"/\"\n" | 31 -> "expected the third component of the date literal\n" | 32 -> "expected a delimiter to finish the date literal\n" - | 67 -> "expected an operator to compose the expression on the left with\n" - | 73 -> "expected an enum constructor to test if the expression on the left\n" - | 72 -> "expected an operator to compose the expression on the left with\n" - | 128 -> "expected an expression on the right side of the sum or minus operator\n" - | 156 -> "expected an expression on the right side of the logical operator\n" - | 75 -> "expected an expression for the argument of this function call\n" - | 116 -> "expected an expression on the right side of the comparison operator\n" - | 137 -> "expected an expression on the right side of the multiplication or division operator\n" - | 130 -> "expected an operator to compose the expression on the left\n" - | 166 -> "expected an expression standing for the set you want to test for membership\n" - | 68 -> "expected an identifier standing for a struct field or a subscope name\n" - | 214 -> "expected a colon after the scope use precondition\n" - | 70 -> "expected a constructor, to get the payload of this enum case\n" + | 66 -> "expected an operator to compose the expression on the left with\n" + | 72 -> "expected an enum constructor to test if the expression on the left\n" + | 71 -> "expected an operator to compose the expression on the left with\n" + | 127 -> "expected an expression on the right side of the sum or minus operator\n" + | 155 -> "expected an expression on the right side of the logical operator\n" + | 74 -> "expected an expression for the argument of this function call\n" + | 115 -> "expected an expression on the right side of the comparison operator\n" + | 136 -> "expected an expression on the right side of the multiplication or division operator\n" + | 129 -> "expected an operator to compose the expression on the left\n" + | 165 -> "expected an expression standing for the set you want to test for membership\n" + | 67 -> "expected an identifier standing for a struct field or a subscope name\n" + | 213 -> "expected a colon after the scope use precondition\n" + | 69 -> "expected a constructor, to get the payload of this enum case\n" | 35 -> "expected the \"for\" keyword to spell the aggregation\n" - | 150 -> "expected an expression to take the negation of\n" - | 64 -> "expected an expression to take the opposite of\n" - | 52 -> "expected an expression to match with\n" - | 198 -> "expected a pattern matching case\n" - | 199 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 205 -> + | 149 -> "expected an expression to take the negation of\n" + | 63 -> "expected an expression to take the opposite of\n" + | 51 -> "expected an expression to match with\n" + | 197 -> "expected a pattern matching case\n" + | 198 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 204 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 206 -> "expected an identifier for this enum case binding\n" - | 202 -> "expected a colon and then the expression for this matching case\n" - | 208 -> "expected a colon or a binding for the enum constructor payload\n" - | 203 -> "expected an expression for this pattern matching case\n" - | 200 -> + | 205 -> "expected an identifier for this enum case binding\n" + | 201 -> "expected a colon and then the expression for this matching case\n" + | 207 -> "expected a colon or a binding for the enum constructor payload\n" + | 202 -> "expected an expression for this pattern matching case\n" + | 199 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 197 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 54 -> "expected an expression inside the parenthesis\n" - | 189 -> "unmatched parenthesis that should have been closed by here\n" - | 76 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 56 -> "expected an expression for the test of the conditional\n" - | 185 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 186 -> + | 196 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 53 -> "expected an expression inside the parenthesis\n" + | 188 -> "unmatched parenthesis that should have been closed by here\n" + | 75 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 55 -> "expected an expression for the test of the conditional\n" + | 184 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 185 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 187 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 184 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 58 -> + | 186 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 183 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 57 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 170 -> "expected an identifier for the bound variable of the universal test\n" - | 171 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 172 -> "expected the expression designating the set on which to perform the universal test\n" - | 173 -> "expected the \"we have\" keyword for this universal test\n" - | 169 -> "expected an expression for the universal test\n" - | 178 -> "expected an identifier that will designate the existential witness for the test\n" - | 179 -> "expected the \"in\" keyword to continue this existential test\n" - | 180 -> "expected an expression that designates the set subject to the existential test\n" - | 181 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 182 -> "expected a keyword to complete the \"such that\" construction\n" - | 176 -> "expected an expression for the existential test\n" - | 85 -> + | 169 -> "expected an identifier for the bound variable of the universal test\n" + | 170 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 171 -> "expected the expression designating the set on which to perform the universal test\n" + | 172 -> "expected the \"we have\" keyword for this universal test\n" + | 168 -> "expected an expression for the universal test\n" + | 177 -> "expected an identifier that will designate the existential witness for the test\n" + | 178 -> "expected the \"in\" keyword to continue this existential test\n" + | 179 -> "expected an expression that designates the set subject to the existential test\n" + | 180 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 181 -> "expected a keyword to complete the \"such that\" construction\n" + | 175 -> "expected an expression for the existential test\n" + | 84 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 86 -> "expected structure fields introduced by --\n" - | 87 -> "expected the name of the structure field\n" - | 91 -> "expected a colon\n" - | 92 -> "expected the expression for this struct field\n" - | 88 -> "expected another structure field or the closing bracket\n" - | 89 -> "expected the name of the structure field\n" - | 160 -> "expected an expression for the content of this enum case\n" - | 161 -> + | 85 -> "expected structure fields introduced by --\n" + | 86 -> "expected the name of the structure field\n" + | 90 -> "expected a colon\n" + | 91 -> "expected the expression for this struct field\n" + | 87 -> "expected another structure field or the closing bracket\n" + | 88 -> "expected the name of the structure field\n" + | 159 -> "expected an expression for the content of this enum case\n" + | 160 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 63 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 215 -> "expected a scope use item: a rule, definition or assertion\n" - | 250 -> "expected the name of the variable subject to the rule\n" - | 228 -> + | 62 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 214 -> "expected a scope use item: a rule, definition or assertion\n" + | 249 -> "expected the name of the variable subject to the rule\n" + | 227 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 257 -> "expected a condition or a consequence for this rule\n" - | 252 -> "expected filled or not filled for a rule consequence\n" - | 258 -> "expected the name of the parameter for this dependent variable \n" - | 251 -> "expected the expression of the rule\n" - | 255 -> "expected the filled keyword the this rule \n" - | 229 -> "expected a struct field or a sub-scope context item after the dot\n" - | 216 -> "expected the name of the label\n" - | 246 -> "expected a rule or a definition after the label declaration\n" - | 247 -> "expected the label to which the exception is referring back\n" - | 249 -> "expected a rule or a definition after the exception declaration\n" - | 262 -> "expected the name of the variable you want to define\n" - | 263 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 265 -> "expected an expression for the consequence of this definition under condition\n" - | 264 -> + | 256 -> "expected a condition or a consequence for this rule\n" + | 251 -> "expected filled or not filled for a rule consequence\n" + | 257 -> "expected the name of the parameter for this dependent variable \n" + | 250 -> "expected the expression of the rule\n" + | 254 -> "expected the filled keyword the this rule \n" + | 228 -> "expected a struct field or a sub-scope context item after the dot\n" + | 215 -> "expected the name of the label\n" + | 245 -> "expected a rule or a definition after the label declaration\n" + | 246 -> "expected the label to which the exception is referring back\n" + | 248 -> "expected a rule or a definition after the exception declaration\n" + | 261 -> "expected the name of the variable you want to define\n" + | 262 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 264 -> "expected an expression for the consequence of this definition under condition\n" + | 263 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 266 -> "expected an expression for the definition\n" - | 218 -> "expected an expression that shoud be asserted during execution\n" - | 219 -> "expecting the name of the varying variable\n" - | 222 -> "the variable varies with an expression that was expected here\n" - | 223 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 221 -> "expected an indication about what this variable varies with\n" - | 231 -> "expected an expression for this condition\n" - | 241 -> "expected a consequence for this definition under condition\n" - | 237 -> "expected an expression for this definition under condition\n" - | 233 -> "expected the name of the variable that should be fixed\n" + | 265 -> "expected an expression for the definition\n" + | 217 -> "expected an expression that shoud be asserted during execution\n" + | 218 -> "expecting the name of the varying variable\n" + | 221 -> "the variable varies with an expression that was expected here\n" + | 222 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 220 -> "expected an indication about what this variable varies with\n" + | 230 -> "expected an expression for this condition\n" + | 240 -> "expected a consequence for this definition under condition\n" + | 236 -> "expected an expression for this definition under condition\n" + | 232 -> "expected the name of the variable that should be fixed\n" + | 233 -> "expected the legislative text by which the value of the variable is fixed\n" | 234 -> "expected the legislative text by which the value of the variable is fixed\n" - | 235 -> "expected the legislative text by which the value of the variable is fixed\n" - | 244 -> "expected a new scope use item \n" - | 273 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 274 -> "expected the struct name\n" - | 275 -> "expected a colon\n" - | 276 -> "expected struct data or condition\n" - | 277 -> "expected the name of this struct data \n" - | 278 -> "expected the type of this struct data, introduced by the content keyword\n" - | 279 -> "expected the type of this struct data\n" - | 293 -> "expected the name of this struct condition\n" - | 286 -> "expected a new struct data, or another declaration or scope use\n" - | 287 -> "expected the type of the parameter of this struct data function\n" - | 291 -> "expected a new struct data, or another declaration or scope use\n" - | 283 -> "expected a new struct data, or another declaration or scope use\n" - | 296 -> "expected the name of the scope you are declaring\n" - | 297 -> "expected a colon followed by the list of context items of this scope\n" - | 298 -> "expected a context item introduced by \"context\"\n" - | 299 -> "expected the name of this new context item\n" - | 300 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 301 -> "expected the name of the subscope for this context item\n" - | 308 -> "expected another scope context item or the end of the scope declaration\n" - | 303 -> "expected the type of this context item\n" - | 304 -> "expected the next context item or a dependency declaration for this item\n" - | 306 -> "expected the next context item or a dependency declaration for this item\n" - | 311 -> "expected the name of your enum\n" - | 312 -> "expected a colon\n" - | 313 -> "expected an enum case\n" - | 314 -> "expected the name of an enum case \n" - | 315 -> "expected a payload for your enum case, or another case or declaration \n" - | 316 -> "expected a content type\n" - | 321 -> "expected another enum case, or a new declaration or scope use\n" + | 243 -> "expected a new scope use item \n" + | 272 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 273 -> "expected the struct name\n" + | 274 -> "expected a colon\n" + | 275 -> "expected struct data or condition\n" + | 276 -> "expected the name of this struct data \n" + | 277 -> "expected the type of this struct data, introduced by the content keyword\n" + | 278 -> "expected the type of this struct data\n" + | 292 -> "expected the name of this struct condition\n" + | 285 -> "expected a new struct data, or another declaration or scope use\n" + | 286 -> "expected the type of the parameter of this struct data function\n" + | 290 -> "expected a new struct data, or another declaration or scope use\n" + | 282 -> "expected a new struct data, or another declaration or scope use\n" + | 295 -> "expected the name of the scope you are declaring\n" + | 296 -> "expected a colon followed by the list of context items of this scope\n" + | 297 -> "expected a context item introduced by \"context\"\n" + | 298 -> "expected the name of this new context item\n" + | 299 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 300 -> "expected the name of the subscope for this context item\n" + | 307 -> "expected another scope context item or the end of the scope declaration\n" + | 302 -> "expected the type of this context item\n" + | 303 -> "expected the next context item or a dependency declaration for this item\n" + | 305 -> "expected the next context item or a dependency declaration for this item\n" + | 310 -> "expected the name of your enum\n" + | 311 -> "expected a colon\n" + | 312 -> "expected an enum case\n" + | 313 -> "expected the name of an enum case \n" + | 314 -> "expected a payload for your enum case, or another case or declaration \n" + | 315 -> "expected a content type\n" + | 320 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" | 19 -> "expected some text or the beginning of a code section\n" | 20 -> "expected a declaration or a scope use\n" | 21 -> "should not happen\n" + | 326 -> "expected a metadata-closing tag\n" | 327 -> "expected a metadata-closing tag\n" - | 328 -> "expected a metadata-closing tag\n" | _ -> raise Not_found diff --git a/syntax_highlighting/en/ace/mode-catala_en.js b/syntax_highlighting/en/ace/mode-catala_en.js index fabc647f..d9fa9626 100644 --- a/syntax_highlighting/en/ace/mode-catala_en.js +++ b/syntax_highlighting/en/ace/mode-catala_en.js @@ -78,7 +78,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu }, { "token": "support.type", - "regex": "\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b" + "regex": "\\b(integer|boolean|date|money|text|decimal|number|sum)\\b" }, { "token": ["entity.name.class", "punctuation", "entity.name.function"], diff --git a/syntax_highlighting/en/atom/grammars/catala_en.cson b/syntax_highlighting/en/atom/grammars/catala_en.cson index 03ce04fc..734544f5 100644 --- a/syntax_highlighting/en/atom/grammars/catala_en.cson +++ b/syntax_highlighting/en/atom/grammars/catala_en.cson @@ -124,7 +124,7 @@ 'name' : 'keyword.operator.catala_en' } { - 'match' : '\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b' + 'match' : '\\b(integer|boolean|date|money|text|decimal|number|sum)\\b' 'name' : 'support.type.catala_en' } { diff --git a/syntax_highlighting/en/catala_en.iro b/syntax_highlighting/en/catala_en.iro index 12bd5838..4c4e2ab1 100644 --- a/syntax_highlighting/en/catala_en.iro +++ b/syntax_highlighting/en/catala_en.iro @@ -245,7 +245,7 @@ code : context { } : pattern { - regex \= \b(integer|boolean|date|money|text|decimal|number|sum|now)\b + regex \= \b(integer|boolean|date|money|text|decimal|number|sum)\b styles [] = .primitive; } diff --git a/syntax_highlighting/en/pygments/catala_en.py b/syntax_highlighting/en/pygments/catala_en.py index 24096add..e70604ea 100644 --- a/syntax_highlighting/en/pygments/catala_en.py +++ b/syntax_highlighting/en/pygments/catala_en.py @@ -35,7 +35,7 @@ class CatalaEnLexer(RegexLexer): Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)', bygroups(Operator)), - (u'\\b(integer|boolean|date|money|text|decimal|number|sum|now)\\b', + (u'\\b(integer|boolean|date|money|text|decimal|number|sum)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), diff --git a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml index 70ae06b5..3eebc2b4 100644 --- a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml @@ -197,7 +197,7 @@ match - \b(integer|boolean|date|money|text|decimal|number|sum|now)\b + \b(integer|boolean|date|money|text|decimal|number|sum)\b name support.type.catala_en diff --git a/syntax_highlighting/fr/ace/mode-catala_fr.js b/syntax_highlighting/fr/ace/mode-catala_fr.js index 08df1403..0b19c36b 100644 --- a/syntax_highlighting/fr/ace/mode-catala_fr.js +++ b/syntax_highlighting/fr/ace/mode-catala_fr.js @@ -78,7 +78,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu }, { "token": "support.type", - "regex": "\\b(entier|bool\u00e9en|date|argent|texte|d\u00e9cimal|d\u00e9cret|loi|nombre|somme|date_aujourd_hui)\\b" + "regex": "\\b(entier|bool\u00e9en|date|argent|texte|d\u00e9cimal|d\u00e9cret|loi|nombre|somme)\\b" }, { "token": ["entity.name.class", "punctuation", "entity.name.function"], diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index d1afa088..a74fb5fe 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -124,7 +124,7 @@ 'name' : 'keyword.operator.catala_fr' } { - 'match' : '\\b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\\b' + 'match' : '\\b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme)\\b' 'name' : 'support.type.catala_fr' } { diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index fab64f5e..500473d9 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -245,7 +245,7 @@ code : context { } : pattern { - regex \= \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b + regex \= \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme)\b styles [] = .primitive; } diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index 10d29754..e629980d 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -35,7 +35,7 @@ class CatalaFrLexer(RegexLexer): Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour)', bygroups(Operator)), - (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme|date_aujourd_hui)\\b', + (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index 69d8b3ad..47039654 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -197,7 +197,7 @@ match - \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme|date_aujourd_hui)\b + \b(entier|booléen|date|argent|texte|décimal|décret|loi|nombre|somme)\b name support.type.catala_fr diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index d2da1dc6..f732b837 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -124,7 +124,7 @@ 'name' : 'keyword.operator.catala_nv' } { - 'match' : '\\b(int|bool|date|money|text|decimal|number|sum|now)\\b' + 'match' : '\\b(int|bool|date|money|text|decimal|number|sum)\\b' 'name' : 'support.type.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index f4da4f9c..0dbdc016 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -245,7 +245,7 @@ code : context { } : pattern { - regex \= \b(int|bool|date|money|text|decimal|number|sum|now)\b + regex \= \b(int|bool|date|money|text|decimal|number|sum)\b styles [] = .primitive; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index 80d00de3..316f31a7 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -35,7 +35,7 @@ class CatalaNvLexer(RegexLexer): bygroups(Operator)), (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)', bygroups(Operator)), - (u'\\b(int|bool|date|money|text|decimal|number|sum|now)\\b', + (u'\\b(int|bool|date|money|text|decimal|number|sum)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), (u'\\b([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\'\\.]*)\\b', bygroups(Name.Variable, Operator, Text)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index b89a62d4..ec86f5e9 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -197,7 +197,7 @@ match - \b(int|bool|date|money|text|decimal|number|sum|now)\b + \b(int|bool|date|money|text|decimal|number|sum)\b name support.type.catala_nv diff --git a/tests/test_array/simple.catala b/tests/test_array/simple.catala index 9f600ef6..48212111 100644 --- a/tests/test_array/simple.catala +++ b/tests/test_array/simple.catala @@ -9,10 +9,14 @@ scope A: new scope B: param a scope A + param v content int + param w content bool param y content bool param z content bool scope B: + def v := number of a.x + def w := 64 in a.x def y := exists m in a.x such that m = 9 def z := for all m in a.x we have m > 0 */ \ No newline at end of file From 89fe5878b041924c8e9d71d4e1095c39af8204cb Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Wed, 30 Dec 2020 12:02:09 +0100 Subject: [PATCH 133/142] Various small fixings --- src/catala/default_calculus/print.ml | 16 ++++----- src/catala/scope_language/scope_to_dcalc.ml | 37 +++++++++++---------- tests/test_array/simple.catala.B.out | 2 ++ 3 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 69bf375e..33ef9461 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -173,13 +173,13 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = match i with | None -> Format.fprintf fmt "%a.%d" format_expr e1 n | Some i -> Format.fprintf fmt "%a.\"%a\"" format_expr e1 Uid.MarkedString.format_info i ) - | EInj (e, _n, i, _ts) -> Format.fprintf fmt "%a %a" Uid.MarkedString.format_info i format_expr e + | EInj (e, _n, i, _ts) -> Format.fprintf fmt "%a@ %a" Uid.MarkedString.format_info i format_expr e | EMatch (e, es) -> - Format.fprintf fmt "@[match %a with %a@]" format_expr e + Format.fprintf fmt "@[match@ %a@ with@ %a@]" format_expr e (Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt " |@ ") + ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ |@ ") (fun fmt (e, c) -> - Format.fprintf fmt "%a %a" Uid.MarkedString.format_info c format_expr e)) + Format.fprintf fmt "%a@ %a" Uid.MarkedString.format_info c format_expr e)) es | ELit l -> Format.fprintf fmt "%a" format_lit (Pos.same_pos_as l e) | EApp ((EAbs (_, binder, taus), _), args) -> @@ -188,7 +188,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let xs_tau_arg = List.map2 (fun (x, tau) arg -> (x, tau, arg)) xs_tau args in Format.fprintf fmt "@[%a%a@]" (Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") (fun fmt (x, tau, arg) -> Format.fprintf fmt "@[@[let@ %a@ :@ %a@ =@ %a@]@ in@\n@]" format_var x format_typ tau format_expr arg)) @@ -196,9 +196,9 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | EAbs (_, binder, taus) -> let xs, body = Bindlib.unmbind binder in let xs_tau = List.map2 (fun x tau -> (x, tau)) (Array.to_list xs) taus in - Format.fprintf fmt "@[λ@ %a@ →@ %a@]" + Format.fprintf fmt "@[λ@ %a →@ %a@]" (Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt " ") + ~pp_sep:(fun fmt () -> Format.fprintf fmt "@ ") (fun fmt (x, tau) -> Format.fprintf fmt "@[(%a:@ %a)@]" format_var x format_typ tau)) xs_tau format_expr body @@ -221,7 +221,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = if List.length exceptions = 0 then Format.fprintf fmt "@[⟨%a@ ⊢@ %a⟩@]" format_expr just format_expr cons else - Format.fprintf fmt "@[⟨%a@ |@ @[%a ⊢ %a@]@ ⟩@]" + Format.fprintf fmt "@[⟨%a@ |@ %a@ ⊢@ %a@ ⟩@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") format_expr) exceptions format_expr just format_expr cons | EAssert e' -> Format.fprintf fmt "@[assert@ (%a)@]" format_expr e' diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 0f12cec1..41a771b3 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -411,6 +411,24 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) (fun e u -> (Dcalc.Ast.EApp (e, u), Pos.no_pos)) subscope_func (Bindlib.box_list subscope_args) in + let call_expr = + Bindlib.box_apply + (fun call_expr -> + ( Dcalc.Ast.EApp + ( ( Dcalc.Ast.EOp + (Dcalc.Ast.Unop + (Dcalc.Ast.Log + ( Dcalc.Ast.EndCall, + [ + (sigma_name, pos_sigma); + Ast.SubScopeName.get_info subindex; + Ast.ScopeName.get_info subname; + ] ))), + Pos.get_position call_expr ), + [ call_expr ] ), + Pos.get_position call_expr )) + call_expr + in let result_tuple_var = Dcalc.Ast.Var.make ("result", Pos.no_pos) in let next_e, new_ctx = translate_rules new_ctx rest (sigma_name, pos_sigma) in let results_bindings, _ = @@ -425,24 +443,7 @@ let rec translate_rule (ctx : ctx) (rule : Ast.rule) (rest : Ast.rule list) all_subscope_vars_dcalc (next_e, List.length all_subscope_vars_dcalc - 1) in - let results_bindings = - Bindlib.box_apply - (fun results_bindings -> - ( Dcalc.Ast.EApp - ( ( Dcalc.Ast.EOp - (Dcalc.Ast.Unop - (Dcalc.Ast.Log - ( Dcalc.Ast.EndCall, - [ - (sigma_name, pos_sigma); - Ast.SubScopeName.get_info subindex; - Ast.ScopeName.get_info subname; - ] ))), - Pos.get_position results_bindings ), - [ results_bindings ] ), - Pos.get_position results_bindings )) - results_bindings - in + let result_tuple_typ = ( Dcalc.Ast.TTuple (List.map (fun (_, tau, _) -> (tau, pos_sigma)) all_subscope_vars_dcalc), pos_sigma ) diff --git a/tests/test_array/simple.catala.B.out b/tests/test_array/simple.catala.B.out index 18ca5c8d..3e39b8d8 100644 --- a/tests/test_array/simple.catala.B.out +++ b/tests/test_array/simple.catala.B.out @@ -1,3 +1,5 @@ [RESULT] Computation successful! Results: +[RESULT] v = 3 +[RESULT] w = true [RESULT] y = true [RESULT] z = false From c6b6e82b8b9930548a679802bd35a433bbd096b7 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 31 Dec 2020 00:28:26 +0100 Subject: [PATCH 134/142] Various fixes, now passing first French tests --- .../allocations_familiales.catala_fr | 3 +- .../decrets_divers.catala_fr | 166 ++++---- .../allocations_familiales/metadata.catala_fr | 355 +++++++++-------- .../securite_sociale_D.catala_fr | 346 ++++++++-------- .../securite_sociale_L.catala_fr | 374 +++++++++--------- .../securite_sociale_R.catala_fr | 122 +++--- .../tests/tests_ouverture_droits.catala_fr | 34 ++ src/catala/catala_surface/desugaring.ml | 13 +- src/catala/catala_surface/name_resolution.ml | 25 +- src/catala/catala_surface/parser.mly | 18 +- src/catala/default_calculus/interpreter.ml | 5 +- src/catala/default_calculus/print.ml | 8 +- src/catala/desugared/ast.ml | 14 +- src/catala/desugared/dependency.ml | 2 +- src/catala/desugared/desugared_to_scope.ml | 39 +- syntax_highlighting/en/ace/mode-catala_en.js | 2 +- .../en/atom/grammars/catala_en.cson | 2 +- syntax_highlighting/en/catala_en.iro | 4 +- syntax_highlighting/en/pygments/catala_en.py | 3 +- .../en/vscode/syntaxes/catalavs.xml | 2 +- syntax_highlighting/fr/ace/mode-catala_fr.js | 2 +- .../fr/atom/grammars/catala_fr.cson | 2 +- syntax_highlighting/fr/catala_fr.iro | 4 +- syntax_highlighting/fr/pygments/catala_fr.py | 3 +- .../fr/vscode/syntaxes/catalavs.xml | 2 +- .../nv/atom/grammars/catala_nv.cson | 2 +- syntax_highlighting/nv/catala_nv.iro | 2 +- syntax_highlighting/nv/pygments/catala_nv.py | 3 +- .../nv/vscode/syntaxes/catalavs.xml | 2 +- 29 files changed, 834 insertions(+), 725 deletions(-) create mode 100644 examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr diff --git a/examples/allocations_familiales/allocations_familiales.catala_fr b/examples/allocations_familiales/allocations_familiales.catala_fr index af87c81a..c1cd4d36 100644 --- a/examples/allocations_familiales/allocations_familiales.catala_fr +++ b/examples/allocations_familiales/allocations_familiales.catala_fr @@ -2,10 +2,11 @@ @@Inclusion: metadata.catala_fr@@ +@@Inclusion: decrets_divers.catala_fr@@ + @@Inclusion: securite_sociale_L.catala_fr@@ @@Inclusion: securite_sociale_R.catala_fr@@ @@Inclusion: securite_sociale_D.catala_fr@@ -@@Inclusion: decrets_divers.catala_fr@@ diff --git a/examples/allocations_familiales/decrets_divers.catala_fr b/examples/allocations_familiales/decrets_divers.catala_fr index 74e1b942..6e89db38 100644 --- a/examples/allocations_familiales/decrets_divers.catala_fr +++ b/examples/allocations_familiales/decrets_divers.catala_fr @@ -10,12 +10,12 @@ Au titre de l’année 2020, l’article 81 de la loi du 24 décembr Le montant précité de la base mensuelle de calcul des allocations familiales (BMAF), en pourcentage duquel sont fxés les montants des prestations familiales, est ainsi porté de 413,16 € à 414,4 € au 1er avril 2020. /* -champ d'application CalculAllocationsFamiliales : - définition prestations_familiales.base_mensuelle - sous condition - date_calcul >= |01/04/2020| et - date_calcul < |01/04/2021| - conséquence égal à 414,4 € +# champ d'application CalculAllocationsFamiliales : +# définition prestations_familiales.base_mensuelle +# sous condition +# date_calcul >= |01/04/2020| et +# date_calcul < |01/04/2021| +# conséquence égal à 414,4 € */ Des règles spécifques s’appliquent par ailleurs aux prestations familiales suivantes en métropole tout comme dans les collectivités de Guadeloupe, Guyane, Martinique, La Réunion, Saint-Barthélemy et à Saint-Martin : l’article 37 de la LFSS pour 2018 a prévu une mesure d’harmonisation du barème de l’allocation de base (AB), de la prime à la naissance et de la prime à l’adoption sur celui du complément familial. Cette réforme est applicable aux enfants nés ou adoptés à compter du 1er avril 2018 et en conséquence à l’ensemble des enfants à compter du 1er avril 2021. @@ -35,98 +35,106 @@ Je vous demande de bien vouloir transmettre à la connaissance des or /* # Cependant, le cas de Mayotte n'est pas traité dans la loi et ce sont donc # les règles de cette annexe qui s'apppliquent. -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.base sous condition - ménage.résidence = Mayotte et - allocations_familiales.droits_ouverts - conséquence égal à - si nombre de ménage.enfants = 1 alors - allocations_familiales.montant_premier_enfant - sinon ( - allocations_familiales.montant_deuxieme_enfant + - allocations_familiales.montant_troisième_enfant_et_plus - ) +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.base sous condition +# ménage.résidence = Mayotte et +# allocations_familiales.droits_ouverts +# conséquence égal à +# si nombre de ménage.enfants = 1 alors +# allocations_familiales.montant_premier_enfant +# sinon ( +# allocations_familiales.montant_deuxieme_enfant + +# allocations_familiales.montant_troisième_enfant_et_plus +# ) - définition allocations_familiales.montant_deuxieme_enfant sous condition - ménage.résidence = Mayotte et - date_calcul > |30/04/2020| et - date_calcul <= |31/12/2020| - conséquence égal à - prestations_familiales.base_mensuelle * 30,68 % +# définition allocations_familiales.montant_deuxieme_enfant sous condition +# ménage.résidence = Mayotte et +# date_calcul > |30/04/2020| et +# date_calcul <= |31/12/2020| +# conséquence égal à +# prestations_familiales.base_mensuelle * 30,68 % - définition allocations_familiales.montant_troisième_enfant_et_plus sous condition - ménage.résidence = Mayotte et - date_calcul > |30/04/2020| et - date_calcul <= |31/12/2020| - conséquence égal à - prestations_familiales.base_mensuelle * 14,3 % + - (si nombre de ménage.enfants >= 4 alors - prestations_familiales.base_mensuelle * 4,63 % * - (nombre de ménage.enfants - 3) - sinon 0 €) +# définition allocations_familiales.montant_troisième_enfant_et_plus sous condition +# ménage.résidence = Mayotte et +# date_calcul > |30/04/2020| et +# date_calcul <= |31/12/2020| +# conséquence égal à +# prestations_familiales.base_mensuelle * 14,3 % + +# (si nombre de ménage.enfants >= 4 alors +# prestations_familiales.base_mensuelle * 4,63 % * +# (nombre de ménage.enfants - 3) +# sinon 0 €) - définition allocations_familiales.montant_deuxieme_enfant sous condition - ménage.résidence = Mayotte et - date_calcul > |01/01/2021| et - date_calcul <= |31/03/2021| - conséquence égal à - prestations_familiales.base_mensuelle * 32 % +# définition allocations_familiales.montant_deuxieme_enfant sous condition +# ménage.résidence = Mayotte et +# date_calcul > |01/01/2021| et +# date_calcul <= |31/03/2021| +# conséquence égal à +# prestations_familiales.base_mensuelle * 32 % - définition allocations_familiales.montant_troisième_enfant_et_plus sous condition - ménage.résidence = Mayotte et - date_calcul > |01/01/2021| et - date_calcul <= |31/03/2021| - conséquence égal à - prestations_familiales.base_mensuelle * 16 % + - (si nombre de ménage.enfants >= 4 alors - prestations_familiales.base_mensuelle * 4,63 % * - (nombre de ménage.enfants - 3) - sinon 0 €) +# définition allocations_familiales.montant_troisième_enfant_et_plus sous condition +# ménage.résidence = Mayotte et +# date_calcul > |01/01/2021| et +# date_calcul <= |31/03/2021| +# conséquence égal à +# prestations_familiales.base_mensuelle * 16 % + +# (si nombre de ménage.enfants >= 4 alors +# prestations_familiales.base_mensuelle * 4,63 % * +# (nombre de ménage.enfants - 3) +# sinon 0 €) - définition allocations_familiales.montant_premier_enfant sous condition - ménage.résident = Mayotte et - allocations_familiales.date_ouverture_droits < |01/01/2012| - conséquence égal à 57,28 € +# définition allocations_familiales.montant_premier_enfant sous condition +# ménage.résident = Mayotte et +# allocations_familiales.date_ouverture_droits < |01/01/2012| +# conséquence égal à 57,28 € - définition allocations_familiales.montant_premier_enfant sous condition - ménage.résident = Mayotte et - allocations_familiales.date_ouverture_droits >= |01/01/2012| et - date_calcul > |30/04/2020| et - date_calcul <= |31/12/2020| - conséquence égal à - prestations_familiales.base_mensuelle * 7,17 % +# définition allocations_familiales.montant_premier_enfant sous condition +# ménage.résident = Mayotte et +# allocations_familiales.date_ouverture_droits >= |01/01/2012| et +# date_calcul > |30/04/2020| et +# date_calcul <= |31/12/2020| +# conséquence égal à +# prestations_familiales.base_mensuelle * 7,17 % - définition allocations_familiales.montant_premier_enfant sous condition - ménage.résident = Mayotte et - allocations_familiales.date_ouverture_droits >= |01/01/2012| et - date_calcul > |01/01/2021| et - date_calcul <= |31/03/2021| - conséquence égal à - prestations_familiales.base_mensuelle * 5,88 % +# définition allocations_familiales.montant_premier_enfant sous condition +# ménage.résident = Mayotte et +# allocations_familiales.date_ouverture_droits >= |01/01/2012| et +# date_calcul > |01/01/2021| et +# date_calcul <= |31/03/2021| +# conséquence égal à +# prestations_familiales.base_mensuelle * 5,88 % */ @@Décret n° 2019-1387 du 18 décembre 2019 portant relèvement du salaire minimum de croissance@@ +@@Début métadonnées@@ +/* +déclaration champ d'application Smic : + contexte résidence contenu Collectivité + contexte brut_horaire contenu argent +*/ +@@Fin métadonnées@@ + @Article 1|LEGIARTI000039640195|01/01/2020@ A compter du 1er janvier 2020, pour les catégories de travailleurs mentionnés à l' article L. 2211-1 du code du travail , le montant du salaire minimum de croissance est relevé dans les conditions ci-après : 1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion, à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon, son montant est porté à 10,15 € l'heure ; /* -champ d'application CalculAllocationsFamiliales : - définition smic.brut_horaire sous condition - (ménage.résidence = Métropole) ou - (ménage.résidence = Guyane) ou - (ménage.résidence = Martinique) ou - (ménage.résidence = LaRéunion) ou - (ménage.résidence = SaintBarthélemy) ou - (ménage.résidence = SaintMartin) ou - (ménage.résidence = SaintPierreEtMiquelon) +champ d'application Smic : + définition brut_horaire sous condition + (résidence = Métropole) ou + (résidence = Guyane) ou + (résidence = Martinique) ou + (résidence = LaRéunion) ou + (résidence = SaintBarthélemy) ou + (résidence = SaintMartin) ou + (résidence = SaintPierreEtMiquelon) conséquence égal à 10,15 € */ 2° A Mayotte, son montant est fixé à 7,66 € l'heure. /* -champ d'application CalculAllocationsFamiliales : - définition smic.brut_horaire sous condition - (ménage.résidence = Mayotte) +champ d'application Smic : + définition brut_horaire sous condition + (résidence = Mayotte) conséquence égal à 7,66 € */ diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index e9d2a45b..fe3bc4ab 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -1,25 +1,24 @@ @@Début métadonnées@@ /* -déclaration structure Personne : - donnée prénom contenu texte - donnée nom contenu texte - donnée date_de_naissance contenu date +# déclaration structure Personne : +# donnée prénom contenu texte +# donnée nom contenu texte +# donnée date_de_naissance contenu date -déclaration structure ParentsGardeAlternée : - donnée parent1 contenu Personne - donnée parent2 contenu Personne +# déclaration structure ParentsGardeAlternée : +# donnée parent1 contenu Personne +# donnée parent2 contenu Personne -déclaration énumération PriseEnCharge : - -- Complète contenu Personne - -- GardeAlternée contenu ParentsGardeAlternée +# déclaration énumération PriseEnCharge : +# -- Complète contenu Personne +# -- GardeAlternée contenu ParentsGardeAlternée -# Une structure regroupe des données ensemble déclaration structure Enfant : donnée fin_obligation_scolaire contenu date - donnée âge contenu entier donnée rémuneration_mensuelle contenu argent - donnée prise_en_charge contenu PriseEnCharge - condition confié_service_social + donnée âge contenu entier + # donnée prise_en_charge contenu PriseEnCharge + # condition confié_service_social déclaration énumération Collectivité : -- Guadeloupe @@ -32,198 +31,198 @@ déclaration énumération Collectivité : -- SaintPierreEtMiquelon -- Mayotte -déclaration structure Ménage : - donnée enfants contenu collection Enfant - donnée parent_en_charge contenu Personne dépend de Enfant - donnée enfant_plus_âgé contenu Enfant - donnée parents contenu collection Personne - donnée parent1 contenu Personne - donnée parent2 contenu Personne - donnée résidence contenu Collectivité - # Le mot optionnel permet de prévoir le cas où le - # ménage n'a pas d'enfants +# déclaration structure Ménage : +# donnée enfants contenu collection Enfant +# donnée parent_en_charge contenu Personne dépend de Enfant +# donnée enfant_plus_âgé contenu Enfant +# donnée parents contenu collection Personne +# donnée parent1 contenu Personne +# donnée parent2 contenu Personne +# donnée résidence contenu Collectivité +# # Le mot optionnel permet de prévoir le cas où le +# # ménage n'a pas d'enfants -déclaration champ d'application MénageBienFormé : - contexte ménage contenu Ménage +# déclaration champ d'application MénageBienFormé : +# contexte ménage contenu Ménage -champ d'application MénageBienFormé : - assertion nombre de parents > 0 et nombre de parents <= 2 +# champ d'application MénageBienFormé : +# assertion nombre de parents > 0 et nombre de parents <= 2 - # Les champs parent1 et parent2 sont cohérents - assertion ménage.parent1 dans ménage.parents - assertion ( - selon ménage.parent2 sous forme - -- Présent de parent2 : - parent2 dans ménage.parents et parent2 != ménage.parent1 - -- Absent : vrai - ) +# # Les champs parent1 et parent2 sont cohérents +# assertion ménage.parent1 dans ménage.parents +# assertion ( +# selon ménage.parent2 sous forme +# -- Présent de parent2 : +# parent2 dans ménage.parents et parent2 != ménage.parent1 +# -- Absent : vrai +# ) - # Dans la traduction informatique, le ménage est en charge de chacun - # des enfants - assertion (pour tout enfant dans enfants on a - selon enfant.prise_en_charge sous forme - -- Complète de parent : parent dans ménage.parents - -- GardeAlternée de parents_garde_alternée : - parents_garde_alternée.parent1 dans ménage.parents ou - parents_garde_alternée.parent2 dans ménage.parents - ) +# # Dans la traduction informatique, le ménage est en charge de chacun +# # des enfants +# assertion (pour tout enfant dans enfants on a +# selon enfant.prise_en_charge sous forme +# -- Complète de parent : parent dans ménage.parents +# -- GardeAlternée de parents_garde_alternée : +# parents_garde_alternée.parent1 dans ménage.parents ou +# parents_garde_alternée.parent2 dans ménage.parents +# ) - # parent_en_charge permet de savoir quel parent du ménage - # est en charge de quel enfant - définition parent_en_charge de enfant égal à ( - selon enfant.prise_en_charge sous forme - -- Complète de parent : parent - -- GardeAlternée de parents_garde_alternée : ( - si parents_garde_alternée.parent1 dans ménage.parents - alors parents_garde_alternée.parent1 - sinon parents_garde_alternée.parent2 - )) +# # parent_en_charge permet de savoir quel parent du ménage +# # est en charge de quel enfant +# définition parent_en_charge de enfant égal à ( +# selon enfant.prise_en_charge sous forme +# -- Complète de parent : parent +# -- GardeAlternée de parents_garde_alternée : ( +# si parents_garde_alternée.parent1 dans ménage.parents +# alors parents_garde_alternée.parent1 +# sinon parents_garde_alternée.parent2 +# )) - # Lorsqu'un enfant est confié au service social, il ne peut être - # en garde alternée - assertion pour tout enfant dans enfants on a - si enfant.confié_service_social - alors enfant.prise_en_charge = Complète contenu service_social - sinon vrai +# # Lorsqu'un enfant est confié au service social, il ne peut être +# # en garde alternée +# assertion pour tout enfant dans enfants on a +# si enfant.confié_service_social +# alors enfant.prise_en_charge = Complète contenu service_social +# sinon vrai -déclaration énumération Prestation: - -- PrestationAccueilJeuneEnfant - -- AllocationFamiliale - -- ComplémentFamilial - -- AllocationLogement - -- AllocationÉducationEnfantHandicapé - -- AllocationSoutienFamilial - -- AllocationRentréeScolaire - -- AllocationJournalièrePresenceParentale +# déclaration énumération Prestation: +# -- PrestationAccueilJeuneEnfant +# -- AllocationFamiliale +# -- ComplémentFamilial +# -- AllocationLogement +# -- AllocationÉducationEnfantHandicapé +# -- AllocationSoutienFamilial +# -- AllocationRentréeScolaire +# -- AllocationJournalièrePresenceParentale -déclaration structure PrestationsFamiliales : - condition conditions_hors_âge dépend de Enfant - condition droits_ouverts dépend de Enfant - donnée base_mensuelle contenu argent - donnée base_mensuelle_dom contenu argent +# déclaration structure PrestationsFamiliales : +# condition conditions_hors_âge dépend de Enfant +# condition droits_ouverts dépend de Enfant +# donnée base_mensuelle contenu argent +# donnée base_mensuelle_dom contenu argent -déclaration énumération ChargeAllocation : - -- Complète - -- Partagée +# déclaration énumération ChargeAllocation : +# -- Complète +# -- Partagée -déclaration structure AllocationsFamiliales : - condition droits_ouverts - donnée date_ouverture_droits contenu date - condition conditions_hors_âge dépend de Enfant - donnée base contenu argent - donnée avec_garde_alternée contenu argent - donnée montant_versé contenu argent - donnée récipiendaire_par_enfant contenu Personne dépend de Enfant - donnée charge_par_enfant contenu ChargeAllocation dépend de Enfant - donnée rapport_enfants_total_moyen contenu décimal - donnée nombre_total_enfants contenu entier - donnée nombre_moyen_enfants contenu décimal - donnée montant_premier_enfant contenu argent - donnée montant_deuxieme_enfant contenu argent - donnée montant_troisième_enfant_et_plus contenu argent +# déclaration structure AllocationsFamiliales : +# condition droits_ouverts +# donnée date_ouverture_droits contenu date +# condition conditions_hors_âge dépend de Enfant +# donnée base contenu argent +# donnée avec_garde_alternée contenu argent +# donnée montant_versé contenu argent +# donnée récipiendaire_par_enfant contenu Personne dépend de Enfant +# donnée charge_par_enfant contenu ChargeAllocation dépend de Enfant +# donnée rapport_enfants_total_moyen contenu décimal +# donnée nombre_total_enfants contenu entier +# donnée nombre_moyen_enfants contenu décimal +# donnée montant_premier_enfant contenu argent +# donnée montant_deuxieme_enfant contenu argent +# donnée montant_troisième_enfant_et_plus contenu argent -déclaration structure AllocationForfaitaire : - condition droits_ouverts dépend de Enfant - donnée montant_versé contenu argent +# déclaration structure AllocationForfaitaire : +# condition droits_ouverts dépend de Enfant +# donnée montant_versé contenu argent -déclaration énumération ChoixParentAllocataire : - -- UnParent contenu Personne - -- DeuxParents +# déclaration énumération ChoixParentAllocataire : +# -- UnParent contenu Personne +# -- DeuxParents -déclaration structure AllocationsGardeAlternée : - donnée choix_allocataire contenu ChoixParentAllocataire - dépend de Enfant - condition unique_allocataire dépend de Enfant - condition allocataire_double dépend de Enfant - condition demande_conjointe_partage_charge dépend de Enfant - condition desaccord_charge dépend de Enfant +# déclaration structure AllocationsGardeAlternée : +# donnée choix_allocataire contenu ChoixParentAllocataire +# dépend de Enfant +# condition unique_allocataire dépend de Enfant +# condition allocataire_double dépend de Enfant +# condition demande_conjointe_partage_charge dépend de Enfant +# condition desaccord_charge dépend de Enfant -déclaration structure MajorationsAllocationsFamiliales : - condition droits_ouverts dépend de Enfant - donnée base_par_enfant contenu argent dépend de Enfant - donnée avec_garde_alternée contenu argent dépend de Enfant - donnée montant_versé contenu argent +# déclaration structure MajorationsAllocationsFamiliales : +# condition droits_ouverts dépend de Enfant +# donnée base_par_enfant contenu argent dépend de Enfant +# donnée avec_garde_alternée contenu argent dépend de Enfant +# donnée montant_versé contenu argent -déclaration structure ComplémentDégressif : - condition droits_ouverts dépend de argent - donnée dépassement contenu argent dépend de argent - donnée pour_allocation_forfaitaire contenu argent - donnée pour_allocations_familiales_et_majorations contenu argent - donnée montant_versé contenu argent +# déclaration structure ComplémentDégressif : +# condition droits_ouverts dépend de argent +# donnée dépassement contenu argent dépend de argent +# donnée pour_allocation_forfaitaire contenu argent +# donnée pour_allocations_familiales_et_majorations contenu argent +# donnée montant_versé contenu argent -déclaration structure TitreI: - condition droits_ouverts_allocations_familiales dépend de Personne +# déclaration structure TitreI: +# condition droits_ouverts_allocations_familiales dépend de Personne -déclaration structure L511_1: - donnée prestation_courante contenu Prestation +# déclaration structure L511_1: +# donnée prestation_courante contenu Prestation -déclaration structure L512_3 : - donnée âge_limite_alinéa_2 contenu entier - donnée âge_limite_alinéa_2_alternatif contenu entier - condition âge_limite_alinéa_2_alternatif_utilisé - donnée plafond_rémunération_mensuelle_alinéa_2 contenu argent +# déclaration structure L512_3 : +# donnée âge_limite_alinéa_2 contenu entier +# donnée âge_limite_alinéa_2_alternatif contenu entier +# condition âge_limite_alinéa_2_alternatif_utilisé +# donnée plafond_rémunération_mensuelle_alinéa_2 contenu argent -déclaration structure L521_1 : - donnée nombre_minimum_enfants contenu argent - donnée ressources_ménage contenu argent +# déclaration structure L521_1 : +# donnée nombre_minimum_enfants contenu argent +# donnée ressources_ménage contenu argent -déclaration structure L521_3 : - donnée âge_limite_alinéa_1 contenu entier dépend de Enfant - donnée minimum_alinéa_2 contenu argent +# déclaration structure L521_3 : +# donnée âge_limite_alinéa_1 contenu entier dépend de Enfant +# donnée minimum_alinéa_2 contenu argent -déclaration structure L751_1 : - condition régime_outre_mer +# déclaration structure L751_1 : +# condition régime_outre_mer -déclaration structure D521_3 : - donnée plafond_I contenu argent - donnée plafond_II contenu argent +# déclaration structure D521_3 : +# donnée plafond_I contenu argent +# donnée plafond_II contenu argent -déclaration structure SMIC : - donnée brut_horaire contenu argent dépend de Collectivité +# déclaration structure SMIC : +# donnée brut_horaire contenu argent dépend de Collectivité -déclaration champ d'application CalculPrestationsFamiliales : - # Les règles déclarées dans PrestationsFamiliales pourront utiliser - # ménage et l512_3 et leur données associées - contexte date_calcul contenu date - contexte ménage contenu Ménage - contexte prestations_familiales contenu PrestationsFamiliales - contexte l511_1 contenu L511_1 - contexte l512_3 contenu L512_3 - contexte ménage_bien_formé champ d'application MénageBienFormé +# déclaration champ d'application CalculPrestationsFamiliales : +# # Les règles déclarées dans PrestationsFamiliales pourront utiliser +# # ménage et l512_3 et leur données associées +# contexte date_calcul contenu date +# contexte ménage contenu Ménage +# contexte prestations_familiales contenu PrestationsFamiliales +# contexte l511_1 contenu L511_1 +# contexte l512_3 contenu L512_3 +# contexte ménage_bien_formé champ d'application MénageBienFormé -champ d'application CalculPrestationsFamiliales: - définition ménage_bien_formé.ménage égal à ménage +# champ d'application CalculPrestationsFamiliales: +# définition ménage_bien_formé.ménage égal à ménage -déclaration champ d'application CalculAllocationsFamilialesAvril2008 : - contexte l521_3 contenu L521_3 +# déclaration champ d'application CalculAllocationsFamilialesAvril2008 : +# contexte l521_3 contenu L521_3 -déclaration champ d'application CalculAllocationsFamiliales : - contexte date_calcul contenu date - contexte ménage contenu Ménage - contexte allocations_familiales contenu AllocationsFamiliales - contexte allocation_forfaitaire contenu AllocationForfaitaire - contexte allocations_garde_alternée contenu AllocationsGardeAlternée - contexte majorations_allocations_familiales - contenu MajorationsAllocationsFamiliales - contexte smic contenu SMIC +# déclaration champ d'application CalculAllocationsFamiliales : +# contexte date_calcul contenu date +# contexte ménage contenu Ménage +# contexte allocations_familiales contenu AllocationsFamiliales +# contexte allocation_forfaitaire contenu AllocationForfaitaire +# contexte allocations_garde_alternée contenu AllocationsGardeAlternée +# contexte majorations_allocations_familiales +# contenu MajorationsAllocationsFamiliales +# contexte smic contenu SMIC - contexte titre_I contenu TitreI - contexte l521_1 contenu L521_1 - contexte l521_3 contenu L521_3 - contexte l751_1 contenu L751_1 - contexte d521_1 contenu D521_1 - contexte d521_3 contenu D521_3 - contexte calcul_prestations_familiales - champ d'application CalculPrestationsFamiliales - contexte calcul_avril_2008 - champ d'application CalculAllocationsFamilialesAvril2008 +# contexte titre_I contenu TitreI +# contexte l521_1 contenu L521_1 +# contexte l521_3 contenu L521_3 +# contexte l751_1 contenu L751_1 +# contexte d521_1 contenu D521_1 +# contexte d521_3 contenu D521_3 +# contexte calcul_prestations_familiales +# champ d'application CalculPrestationsFamiliales +# contexte calcul_avril_2008 +# champ d'application CalculAllocationsFamilialesAvril2008 -champ d'application CalculAllocationsFamiliales: - définition calcul_prestations_familiales.ménage égal à ménage - définition calcul_prestations_familiales.date_calcul égal à date_calcul - # AllocationsFamiliales est un cas particulier de PrestationsFamiliales, - # le dernier est donc inclus dans l'autre. Il est nécessaire de préciser - # que les deux contextes parlent du même ménage pour caractériser - # l'inclusion. +# champ d'application CalculAllocationsFamiliales: +# définition calcul_prestations_familiales.ménage égal à ménage +# définition calcul_prestations_familiales.date_calcul égal à date_calcul +# # AllocationsFamiliales est un cas particulier de PrestationsFamiliales, +# # le dernier est donc inclus dans l'autre. Il est nécessaire de préciser +# # que les deux contextes parlent du même ménage pour caractériser +# # l'inclusion. */ @@Fin métadonnées@@ diff --git a/examples/allocations_familiales/securite_sociale_D.catala_fr b/examples/allocations_familiales/securite_sociale_D.catala_fr index fb260fe0..d8c8dd18 100644 --- a/examples/allocations_familiales/securite_sociale_D.catala_fr +++ b/examples/allocations_familiales/securite_sociale_D.catala_fr @@ -13,12 +13,12 @@ familiales et de la majoration pour âge prévue à l'article L. 521-3 est défini selon le barème suivant : /* # Composantes des allocations familiales -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.base sous condition - allocations_familiales.droits_ouverts - conséquence égal à - allocations_familiales.montant_deuxieme_enfant + - allocations_familiales.montant_troisième_enfant_et_plus +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.base sous condition +# allocations_familiales.droits_ouverts +# conséquence égal à +# allocations_familiales.montant_deuxieme_enfant + +# allocations_familiales.montant_troisième_enfant_et_plus */ 1° Lorsque le ménage ou la personne a disposé d'un montant de ressources inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux @@ -26,37 +26,37 @@ servant au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 32 % pour le deuxième enfant à charge ; /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_deuxieme_enfant sous condition - l521_1.ressources_ménage <= d521_3.plafond_I - conséquence égal à - si nombre de ménage.enfants >= 2 - alors prestations_familiales.base_mensuelle * 32 % - sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_deuxieme_enfant sous condition +# l521_1.ressources_ménage <= d521_3.plafond_I +# conséquence égal à +# si nombre de ménage.enfants >= 2 +# alors prestations_familiales.base_mensuelle * 32 % +# sinon 0 € */ b) 41 % pour le troisième enfant à charge et chacun des suivants. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_troisième_enfant_et_plus - sous condition - l521_1.ressources_ménage <= d521_3.plafond_I - conséquence égal à - si nombre de ménage.enfants >= 3 - alors prestations_familiales.base_mensuelle * 41 % * ( - (nombre de ménage.enfants) - 2 - ) sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_troisième_enfant_et_plus +# sous condition +# l521_1.ressources_ménage <= d521_3.plafond_I +# conséquence égal à +# si nombre de ménage.enfants >= 3 +# alors prestations_familiales.base_mensuelle * 41 % * ( +# (nombre de ménage.enfants) - 2 +# ) sinon 0 € */ La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des prestations familiales ; /* -champ d'application CalculAllocationsFamiliales : - définition - majorations_allocations_familiales.base_par_enfant de enfant - sous condition - l521_1.ressources_ménage <= d521_3.plafond_I - conséquence égal à - prestations_familiales.base_mensuelle * 16 % +# champ d'application CalculAllocationsFamiliales : +# définition +# majorations_allocations_familiales.base_par_enfant de enfant +# sous condition +# l521_1.ressources_ménage <= d521_3.plafond_I +# conséquence égal à +# prestations_familiales.base_mensuelle * 16 % */ 2° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal @@ -65,39 +65,39 @@ allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 16 % pour le deuxième enfant à charge ; /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_deuxieme_enfant sous condition - (l521_1.ressources_ménage > d521_3.plafond_I) et - (l521_1.ressources_ménage <= d521_3.plafond_II) - conséquence égal à - si nombre de ménage.enfants >= 2 - alors prestations_familiales.base_mensuelles * 32 % - sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_deuxieme_enfant sous condition +# (l521_1.ressources_ménage > d521_3.plafond_I) et +# (l521_1.ressources_ménage <= d521_3.plafond_II) +# conséquence égal à +# si nombre de ménage.enfants >= 2 +# alors prestations_familiales.base_mensuelles * 32 % +# sinon 0 € */ b) 20,5 % pour le troisième enfant à charge et chacun des suivants. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_troisième_enfant_et_plus - sous condition - (l521_1.ressources_ménage > d521_3.plafond_I) et - (l521_1.ressources_ménage <= d521_3.plafond_II) - conséquence égal à - si nombre de ménage.enfants >= 3 - alors prestations_familiales.base_mensuelle * 20,5 % * ( - (nombre de ménage.enfants) - 2 - ) sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_troisième_enfant_et_plus +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_I) et +# (l521_1.ressources_ménage <= d521_3.plafond_II) +# conséquence égal à +# si nombre de ménage.enfants >= 3 +# alors prestations_familiales.base_mensuelle * 20,5 % * ( +# (nombre de ménage.enfants) - 2 +# ) sinon 0 € */ La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des prestations familiales ; /* -champ d'application CalculAllocationsFamiliales : - définition - majorations_allocations_familiales.base_par_enfant de enfant - sous condition - (l521_1.ressources_ménage > d521_3.plafond_I) et - (l521_1.ressources_ménage <= d521_3.plafond_II) - conséquence égal à - prestations_familiales.base_mensuelle * 8 % +# champ d'application CalculAllocationsFamiliales : +# définition +# majorations_allocations_familiales.base_par_enfant de enfant +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_I) et +# (l521_1.ressources_ménage <= d521_3.plafond_II) +# conséquence égal à +# prestations_familiales.base_mensuelle * 8 % */ 3° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -106,36 +106,36 @@ au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 8 % pour le deuxième enfant à charge ; /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_deuxieme_enfant sous condition - (l521_1.ressources_ménage > d521_3.plafond_II) - conséquence égal à - si nombre de ménage.enfants >= 2 - alors prestations_familiales.base_mensuelle * 8 % - sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_deuxieme_enfant sous condition +# (l521_1.ressources_ménage > d521_3.plafond_II) +# conséquence égal à +# si nombre de ménage.enfants >= 2 +# alors prestations_familiales.base_mensuelle * 8 % +# sinon 0 € */ b) 10,25 % pour le troisième enfant à charge et chacun des suivants. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.montant_troisième_enfant_et_plus - sous condition - (l521_1.ressources_ménage > d521_3.plafond_II) - conséquence égal à - si nombre de ménage.enfants >= 3 - alors prestations_familiales.base_mensuelle * 10,25 % * ( - (nombre de ménage.enfants) - 2 - ) sinon 0 € +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.montant_troisième_enfant_et_plus +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_II) +# conséquence égal à +# si nombre de ménage.enfants >= 3 +# alors prestations_familiales.base_mensuelle * 10,25 % * ( +# (nombre de ménage.enfants) - 2 +# ) sinon 0 € */ La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des prestations familiales. /* -champ d'application CalculAllocationsFamiliales : - définition - majorations_allocations_familiales.base_par_enfant de enfant - sous condition - (l521_1.ressources_ménage > d521_3.plafond_II) - conséquence égal à - prestations_familiales.base_mensuelle * 4 % +# champ d'application CalculAllocationsFamiliales : +# définition +# majorations_allocations_familiales.base_par_enfant de enfant +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_II) +# conséquence égal à +# prestations_familiales.base_mensuelle * 4 % */ II.-En application du sixième alinéa de l'article L. 521-1, le montant @@ -150,42 +150,42 @@ Ce complément dégressif est égal, pour chaque mois, au douzième de la différence entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. /* -champ d'application CalculAllocationsFamiliales : - définition complément_dégressif.dépassement de allocation - sous condition - (l521_1.ressources_ménage > d521_3.plafond_I) et - (l521_1.ressources_ménage <= d521_3.plafond_I + 12 * allocation) - conséquence égal à - d521_3.plafond_I + 12 * allocation - l521_1.ressources_ménage +# champ d'application CalculAllocationsFamiliales : +# définition complément_dégressif.dépassement de allocation +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_I) et +# (l521_1.ressources_ménage <= d521_3.plafond_I + 12 * allocation) +# conséquence égal à +# d521_3.plafond_I + 12 * allocation - l521_1.ressources_ménage - définition complément_dégressif.dépassement de allocation - sous condition - (l521_1.ressources_ménage > d521_3.plafond_II) et - (l521_1.ressources_ménage <= d521_3.plafond_II + 12 * allocation) - conséquence égal à - d521_3.plafond_II + 12 * allocation - l521_1.ressources_ménage +# définition complément_dégressif.dépassement de allocation +# sous condition +# (l521_1.ressources_ménage > d521_3.plafond_II) et +# (l521_1.ressources_ménage <= d521_3.plafond_II + 12 * allocation) +# conséquence égal à +# d521_3.plafond_II + 12 * allocation - l521_1.ressources_ménage - # Dans les autres cas, le dépassement est nul - définition complément_dégressif.dépassement de allocations égal à 0 € +# # Dans les autres cas, le dépassement est nul +# définition complément_dégressif.dépassement de allocations égal à 0 € - règle complément_dégressif.droits_ouverts de allocation - sous condition complément_dégressif.dépassement de allocation > 0 € - conséquence rempli +# règle complément_dégressif.droits_ouverts de allocation +# sous condition complément_dégressif.dépassement de allocation > 0 € +# conséquence rempli - définition - complément_dégressif.pour_allocations_familiales_et_majorations - sous condition complément_dégressif.droits_ouverts de complément_dégressif.base - conséquence égal à - (complément_dégressif.dépassement de complément_dégressif.base) / 12 +# définition +# complément_dégressif.pour_allocations_familiales_et_majorations +# sous condition complément_dégressif.droits_ouverts de complément_dégressif.base +# conséquence égal à +# (complément_dégressif.dépassement de complément_dégressif.base) / 12 - définition complément_dégressif.base - égal à - (si allocations_familiales.droits_ouverts alors - allocations_familiales.montant_versé - sinon 0 €) + - (si majorations_allocations_familiales.droits_ouverts alors - majorations_allocations_familiales.montant_versé - sinon 0 €) +# définition complément_dégressif.base +# égal à +# (si allocations_familiales.droits_ouverts alors +# allocations_familiales.montant_versé +# sinon 0 €) + +# (si majorations_allocations_familiales.droits_ouverts alors +# majorations_allocations_familiales.montant_versé +# sinon 0 €) */ @Article D521-2|LEGIARTI000030680324@ @@ -197,13 +197,13 @@ inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle de calcul des allocations familiales par enfant ; /* -champ d'application CalculAllocationsFamiliales : - définition allocation_forfaitaire.montant_versé sous condition - l521_1.ressources_ménage <= d521_3.plafond_I - conséquence égal à - prestations_familiales.base_mensuelle * 20,234 % * - nombre pour enfant dans ménage.enfants de - allocation_forfaitaire.droits_ouverts de enfant +# champ d'application CalculAllocationsFamiliales : +# définition allocation_forfaitaire.montant_versé sous condition +# l521_1.ressources_ménage <= d521_3.plafond_I +# conséquence égal à +# prestations_familiales.base_mensuelle * 20,234 % * +# nombre pour enfant dans ménage.enfants de +# allocation_forfaitaire.droits_ouverts de enfant */ 2° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -212,14 +212,14 @@ supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations familiales par enfant ; /* -champ d'application CalculAllocationsFamiliales : - définition allocation_forfaitaire.montant_versé sous condition - (l521_1.ressources_ménage > d521_3.plafond_I) et - (l521_1.ressources_ménage <= d521_3.plafond_II) - conséquence égal à - prestations_familiales.base_mensuelle * 10,117 % * - nombre pour enfant dans ménage.enfants de - allocation_forfaitaire.droits_ouvert de enfant +# champ d'application CalculAllocationsFamiliales : +# définition allocation_forfaitaire.montant_versé sous condition +# (l521_1.ressources_ménage > d521_3.plafond_I) et +# (l521_1.ressources_ménage <= d521_3.plafond_II) +# conséquence égal à +# prestations_familiales.base_mensuelle * 10,117 % * +# nombre pour enfant dans ménage.enfants de +# allocation_forfaitaire.droits_ouvert de enfant */ 3° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -227,13 +227,13 @@ supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul des allocations familiales par enfant. /* -champ d'application CalculAllocationsFamiliales : - définition allocation_forfaitaire.montant_versé sous condition - l521_1.ressources_ménage > d521_3.plafond_II - conséquence égal à - prestations_familiales.base_mensuelle * 5,059 % * - nombre pour enfant dans ménage.enfants de - allocation_forfaitaire.droits_ouvert de enfant +# champ d'application CalculAllocationsFamiliales : +# définition allocation_forfaitaire.montant_versé sous condition +# l521_1.ressources_ménage > d521_3.plafond_II +# conséquence égal à +# prestations_familiales.base_mensuelle * 5,059 % * +# nombre pour enfant dans ménage.enfants de +# allocation_forfaitaire.droits_ouvert de enfant */ II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel @@ -245,22 +245,22 @@ Ce complément dégressif est égal, pour chaque mois, au douzième de la diffé entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. /* -champ d'application CalculAllocationsFamiliales : - définition - complément_dégressif.pour_allocation_forfaitaire - sous condition - allocation_forfaitaire.droits_ouverts et - complément_dégressif.droits_ouverts de allocation_forfaitaire.droits_ouverts - conséquence égal à - (complément_dégressif.dépassement - de allocation_forfaitaire.montant_versé) / 12 +# champ d'application CalculAllocationsFamiliales : +# définition +# complément_dégressif.pour_allocation_forfaitaire +# sous condition +# allocation_forfaitaire.droits_ouverts et +# complément_dégressif.droits_ouverts de allocation_forfaitaire.droits_ouverts +# conséquence égal à +# (complément_dégressif.dépassement +# de allocation_forfaitaire.montant_versé) / 12 */ III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de l'article L. 521-1 est fixé à trois. /* -champ d'application CalculAllocationsFamiliales : - définition l521_1.nombre_minimum_enfants égal à 3 +# champ d'application CalculAllocationsFamiliales : +# définition l521_1.nombre_minimum_enfants égal à 3 */ @Article D521-3|LEGIARTI000030678079@ @@ -268,17 +268,17 @@ champ d'application CalculAllocationsFamiliales : I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à 55 950 euros. Il est majoré de 5 595 euros par enfant à charge. /* -champ d'application CalculAllocationsFamiliales : - définition d521_3.plafond_I égal à 55 950 € + - 5 595 € * nombre de ménage.enfants +# champ d'application CalculAllocationsFamiliales : +# définition d521_3.plafond_I égal à 55 950 € + +# 5 595 € * nombre de ménage.enfants */ II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à 78 300 euros. Il est majoré de 5 595 euros par enfant à charge. /* -champ d'application CalculAllocationsFamiliales : - définition d521_3.plafond_II égal à 78 300 € + - 5 595 € * nombre de ménage.enfants +# champ d'application CalculAllocationsFamiliales : +# définition d521_3.plafond_II égal à 78 300 € + +# 5 595 € * nombre de ménage.enfants */ III.-Les montants des plafonds et de leur majoration respective fixés au présent @@ -308,20 +308,20 @@ fixé à 5,88 p. 100 de la base mensuelle prévue à l'article L. 755-3. /* # Composantes des allocations familiales -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.base sous condition - l751_1.régime_outre_mer et - allocations_familiales.droits_ouverts - conséquence égal à - si nombre de ménage.enfants = 1 alors - allocations_familiales.montant_premier_enfant - sinon ( - allocations_familiales.montant_deuxieme_enfant + - allocations_familiales.montant_troisième_enfant_et_plus - ) +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.base sous condition +# l751_1.régime_outre_mer et +# allocations_familiales.droits_ouverts +# conséquence égal à +# si nombre de ménage.enfants = 1 alors +# allocations_familiales.montant_premier_enfant +# sinon ( +# allocations_familiales.montant_deuxieme_enfant + +# allocations_familiales.montant_troisième_enfant_et_plus +# ) - définition allocations_familiales.montant_premier_enfant égal à - prestations_familiales.base_mensuelle_dom * 5,88 % +# définition allocations_familiales.montant_premier_enfant égal à +# prestations_familiales.base_mensuelle_dom * 5,88 % # Question : le complément dégressif s'applique-t-il ici ? Car le complément # est basé sur les plafonds du taux de base qui ne s'appliquent pas ici, @@ -331,16 +331,16 @@ La majoration des allocations familiales pour un seul enfant à charge est fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à partir de onze ans et à 5,67 p. 100 à partir de seize ans. /* -champ d'application CalculAllocationsFamiliales : - définition l521_3.âge_limite_alinéa_1 de enfant - sous condition l751_1.régime_outre_mer - conséquence égal à 11 an -définition - majorations_allocations_familiales.base_par_enfant de enfant -sous condition - l751_1.régime_outre_mer et - (majorations_allocations_familiales.droits_ouverts de enfant) -conséquence égal à - prestations_familiales.base_mensuelle_dom * - (si enfant.âge >= 16 an alors 5,67 % sinon 3,69 %) +# champ d'application CalculAllocationsFamiliales : +# définition l521_3.âge_limite_alinéa_1 de enfant +# sous condition l751_1.régime_outre_mer +# conséquence égal à 11 an +# définition +# majorations_allocations_familiales.base_par_enfant de enfant +# sous condition +# l751_1.régime_outre_mer et +# (majorations_allocations_familiales.droits_ouverts de enfant) +# conséquence égal à +# prestations_familiales.base_mensuelle_dom * +# (si enfant.âge >= 16 an alors 5,67 % sinon 3,69 %) */ diff --git a/examples/allocations_familiales/securite_sociale_L.catala_fr b/examples/allocations_familiales/securite_sociale_L.catala_fr index eb3194c4..e6e41461 100644 --- a/examples/allocations_familiales/securite_sociale_L.catala_fr +++ b/examples/allocations_familiales/securite_sociale_L.catala_fr @@ -30,50 +30,68 @@ Les prestations familiales comprennent : 9°) l'allocation journalière de présence parentale. /* -# Voir métadonnnée L511_1.prestation_courante +déclaration énumération ÉlémentPrestationsFamiliales: + -- PrestationAccueilJeuneEnfant + -- AllocationsFamiliales + -- ComplémentFamilial + -- AllocationLogement + -- AllocationÉducationEnfantHandicapé + -- AllocationSoutienFamilial + -- AllocationRentréeScolaire + -- AllocationJournalièrePresenceParentale */ @@Chapitre 2 : Champ d'application@@++++ +@@Début métadonnées@@ +/* +déclaration énumération ÂgeAlternatif: + -- Absent + -- Présent contenu entier + +déclaration champ d'application OuvertureDroitPrestationsFamiliales: + contexte droits_ouverts condition dépend de Enfant + contexte conditions_hors_âge condition dépend de Enfant + contexte plafond_l512_3_2 contenu argent + contexte âge_l512_3_2 contenu entier + contexte âge_l512_3_2_alternatif contenu ÂgeAlternatif + contexte date_courante contenu date + contexte prestation_courante contenu ÉlémentPrestationsFamiliales + contexte résidence contenu Collectivité + contexte smic champ d'application Smic + +champ d'application OuvertureDroitPrestationsFamiliales: + définition smic.résidence égal à résidence +*/ +@@Fin métadonnées@@ + @Article L512-3|LEGIARTI000038834523@ Sous réserve des règles particulières à chaque prestation, ouvre droit aux prestations familiales : -/* -champ d'application CalculPrestationsFamiliales : - # On suppose dans le programme que tous les enfants déclarés dans - # ménage.enfants ouvrent droit aux allocations familiales - assertion pour tout enfant dans ménage.enfants on a - prestations_familiales.droits_ouverts de enfant -*/ 1°) tout enfant jusqu'à la fin de l'obligation scolaire ; /* -champ d'application CalculPrestationsFamiliales : - règle prestations_familiales.droits_ouverts de enfant sous condition - (enfant dans ménage.enfants) et - (date_calcul <= enfant.fin_obligation_scolaire) +champ d'application OuvertureDroitPrestationsFamiliales : + règle droits_ouverts de enfant sous condition + (date_courante <=@ enfant.fin_obligation_scolaire) conséquence rempli */ 2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite, tout enfant dont la rémunération éventuelle n'excède pas un plafond. /* -champ d'application CalculPrestationsFamiliales : +champ d'application OuvertureDroitPrestationsFamiliales : # On définit les conditions hors âge d'abord car elles - # sont référencées dans l'article L521-1 - règle prestations_familiales.conditions_hors_âge de enfant sous condition - (enfant dans ménage.enfants) et ( - (date_calcul <= enfant.fin_obligation_scolaire) ou - (enfant.rémuneration_mensuelle < - l512_3.plafond_rémunération_mensuelle_alinéa_2) - ) + # sont référencées plus tard dans l'article L521-1 + règle conditions_hors_âge de enfant sous condition + (date_courante <=@ enfant.fin_obligation_scolaire) ou + (enfant.rémuneration_mensuelle <=€ plafond_l512_3_2) conséquence rempli - règle prestations_familiales.droits_ouverts de enfant sous condition - (enfant dans ménage.enfants) et - (date_calcul > enfant.fin_obligation_scolaire) et - (l512_3.conditions_hors_âge de enfant) et - (enfant.âge < l512_3.âge_limite_alinéa_2) + règle droits_ouverts de enfant sous condition + (date_courante >@ enfant.fin_obligation_scolaire) et + (conditions_hors_âge de enfant) et + (enfant.âge <= âge_l512_3_2) conséquence rempli */ @@ -81,13 +99,17 @@ Toutefois, pour l'attribution du complément familial et de l'allocation de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite peut être différent de celui mentionné au 2° du présent article. /* -champ d'application CalculPrestationsFamiliales : - définition l512_3.âge_limite_alinéa_2 sous condition - l512_3.âge_limite_alinéa_2_alternatif_utilisé et - (l511_1.prestation_courante = ComplémentFamilial ou - l511_1.prestation_courante = AllocationLogement) +champ d'application OuvertureDroitPrestationsFamiliales : + définition âge_l512_3_2 sous condition + (selon âge_l512_3_2_alternatif sous forme + -- Présent de âge : vrai + -- Absent: faux) et + (prestation_courante = ComplémentFamilial ou + prestation_courante = AllocationLogement) conséquence égal à - l512_3.âge_limite_alinéa_2_alternatif + selon âge_l512_3_2_alternatif sous forme + -- Présent de âge : âge + -- Absent: 0 */ @@Titre 2 : Prestations générales d'entretien@@+++ @@ -97,19 +119,19 @@ champ d'application CalculPrestationsFamiliales : @Article L521-1|LEGIARTI000029963006@ Les allocations familiales sont dues à partir du deuxième enfant à charge. /* -champ d'application CalculAllocationsFamiliales : - règle allocations_familiales.droits_ouverts sous condition - nombre de ménage.enfants >= 2 - conséquence rempli +# champ d'application CalculAllocationsFamiliales : +# règle allocations_familiales.droits_ouverts sous condition +# nombre de ménage.enfants >= 2 +# conséquence rempli - # Les droits doivent être ouverts pour appliquer le champ - # CalculAllocationsFamiliales. Si cette condition n'est pas remplie, - # alors il est inutile de calculer le reste - assertion allocations_familiales.droits_ouverts - # Le champ d'application CalculAllocationsFamiliales inclus - # PrestationsFamiliales, mais à condition que la prestation courante - # soit cohérente - définition l511_1.prestation_courante égal à AllocationFamiliale +# # Les droits doivent être ouverts pour appliquer le champ +# # CalculAllocationsFamiliales. Si cette condition n'est pas remplie, +# # alors il est inutile de calculer le reste +# assertion allocations_familiales.droits_ouverts +# # Le champ d'application CalculAllocationsFamiliales inclus +# # PrestationsFamiliales, mais à condition que la prestation courante +# # soit cohérente +# définition l511_1.prestation_courante égal à AllocationFamiliale */ Une allocation forfaitaire par enfant d'un montant fixé par décret est versée @@ -120,24 +142,24 @@ limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée à la condition que le ou les enfants répondent aux conditions autres que celles de l'âge pour l'ouverture du droit aux allocations familiales. /* -champ d'application CalculAllocationsFamiliales : - assertion fixé allocation_forfaitaire.montant_versé par décret +# champ d'application CalculAllocationsFamiliales : +# assertion fixé allocation_forfaitaire.montant_versé par décret - # Ici, l'ouverture du droit aux allocations familiales est conditionné - # au fait d'avoir deux enfants à charges qui répondent aux conditions - # d'ouverture du droit à une prestation familiale. Pour cette raison, - # nous nous référons ici aux conditions_hors_âge de prestations_familiales - # et non pas de allocations_familiales - règle allocations_familiales.conditions_hors_âge de enfant sous condition - prestations_familiales.conditions_hors_âge de enfant - conséquence rempli +# # Ici, l'ouverture du droit aux allocations familiales est conditionné +# # au fait d'avoir deux enfants à charges qui répondent aux conditions +# # d'ouverture du droit à une prestation familiale. Pour cette raison, +# # nous nous référons ici aux conditions_hors_âge de prestations_familiales +# # et non pas de allocations_familiales +# règle allocations_familiales.conditions_hors_âge de enfant sous condition +# prestations_familiales.conditions_hors_âge de enfant +# conséquence rempli - règle allocation_forfaitaire.droits_ouverts de enfant sous condition - (nombre de ménage.enfants >= l512_1.nombre_minimum_enfants) et - (enfant dans ménage.enfants) et - (enfant.âge = l512_3.âge_limite_alinéa_2) et - (allocations_familiales.conditions_hors_âge de enfant) - conséquence rempli +# règle allocation_forfaitaire.droits_ouverts de enfant sous condition +# (nombre de ménage.enfants >= l512_1.nombre_minimum_enfants) et +# (enfant dans ménage.enfants) et +# (enfant.âge = l512_3.âge_limite_alinéa_2) et +# (allocations_familiales.conditions_hors_âge de enfant) +# conséquence rempli */ Le montant des allocations mentionnées aux deux premiers alinéas du présent @@ -145,21 +167,21 @@ article, ainsi que celui des majorations mentionnées à l'article L. 521-3 varient en fonction des ressources du ménage ou de la personne qui a la charge des enfants, selon un barème défini par décret. /* -champ d'application CalculAllocationsFamiliales : - assertion fixé allocations_familiales.montant_versé par décret - assertion varie allocations_familiales.montant_versé avec - l521_1.ressources_ménage - assertion fixé majorations_allocations_familiales.montant_versé par décret - assertion varie majorations_allocations_familiales.montant_versé avec - l521_1.ressources_ménage +# champ d'application CalculAllocationsFamiliales : +# assertion fixé allocations_familiales.montant_versé par décret +# assertion varie allocations_familiales.montant_versé avec +# l521_1.ressources_ménage +# assertion fixé majorations_allocations_familiales.montant_versé par décret +# assertion varie majorations_allocations_familiales.montant_versé avec +# l521_1.ressources_ménage */ Le montant des allocations familiales varie en fonction du nombre d'enfants à charge. /* -champ d'application CalculAllocationsFamiliales : - assertion varie allocations_familiales.montant_versé avec - nombre de ménage.enfants +# champ d'application CalculAllocationsFamiliales : +# assertion varie allocations_familiales.montant_versé avec +# nombre de ménage.enfants */ Les niveaux des plafonds de ressources, qui varient en fonction du nombre @@ -181,24 +203,24 @@ sont définies par décret. # est assez important et nous avons choisi de ne pas l'inclure dans ce # document. -champ d'application CalculAllocationsFamiliales : - assertion fixé complément_dégressif.montant_versé par décret +# champ d'application CalculAllocationsFamiliales : +# assertion fixé complément_dégressif.montant_versé par décret */ @Article L521-2|LEGIARTI000006743210@ Les allocations sont versées à la personne qui assume, dans quelques conditions que ce soit, la charge effective et permanente de l'enfant. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.charge_par_enfant de enfant - sous condition - (enfant dans ménage.enfants) et - (enfant.prise_en_charge sous forme Complète) - conséquence égal à Complète +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.charge_par_enfant de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (enfant.prise_en_charge sous forme Complète) +# conséquence égal à Complète - définition allocations_familiales.récipiendaire_par_enfant de enfant - sous condition enfant dans ménage.enfants - conséquence égal à ménage.parent_en_charge +# définition allocations_familiales.récipiendaire_par_enfant de enfant +# sous condition enfant dans ménage.enfants +# conséquence égal à ménage.parent_en_charge */ En cas de résidence alternée de l'enfant au domicile de chacun des parents telle @@ -210,44 +232,44 @@ désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fi les conditions d'application du présent alinéa. /* -champ d'application CalculAllocationsFamiliales : -# Premier cas : garde alternée, parents désignent un unique allocataire - règle allocations_garde_alternée.unique_allocataire de enfant sous condition - (enfant dans ménage.enfants) et - (enfant.prise_en_charge sous forme GardeAlternée) et - ((allocations_garde_alternée.choix_allocataire de enfant) - sous forme Présent) et - ((allocations_garde_alternée.choix_allocataire de enfant) -> Présent - sous forme UnParent) et - (((allocations_garde_alternée.choix_allocataire de enfant) -> Présent -> UnParent) - dans ménage.parents) - conséquence rempli +# champ d'application CalculAllocationsFamiliales : +# # Premier cas : garde alternée, parents désignent un unique allocataire +# règle allocations_garde_alternée.unique_allocataire de enfant sous condition +# (enfant dans ménage.enfants) et +# (enfant.prise_en_charge sous forme GardeAlternée) et +# ((allocations_garde_alternée.choix_allocataire de enfant) +# sous forme Présent) et +# ((allocations_garde_alternée.choix_allocataire de enfant) -> Présent +# sous forme UnParent) et +# (((allocations_garde_alternée.choix_allocataire de enfant) -> Présent -> UnParent) +# dans ménage.parents) +# conséquence rempli - définition allocations_familiales.charge_par_enfant de enfant - sous condition allocations_garde_alternée.unique_allocataire de enfant - conséquence égal à Complète +# définition allocations_familiales.charge_par_enfant de enfant +# sous condition allocations_garde_alternée.unique_allocataire de enfant +# conséquence égal à Complète -# Deuxième cas : garde alternée, parents partagent la charge pour -# l'allocation - règle allocations_garde_alternée.allocataire_double de enfant sous condition - (enfant dans ménage.enfants) et - (enfant.prise_en_charge sous forme GardeAlternée) et - (enfant.choix_allocataire_garde_alternée sous forme Présent) et - (enfant.choix_allocataire_garde_alternée -> Présent sous forme DeuxParents) - conséquence rempli +# # Deuxième cas : garde alternée, parents partagent la charge pour +# # l'allocation +# règle allocations_garde_alternée.allocataire_double de enfant sous condition +# (enfant dans ménage.enfants) et +# (enfant.prise_en_charge sous forme GardeAlternée) et +# (enfant.choix_allocataire_garde_alternée sous forme Présent) et +# (enfant.choix_allocataire_garde_alternée -> Présent sous forme DeuxParents) +# conséquence rempli - définition allocations_familiales.charge_par_enfant de enfant - sous condition - (enfant dans ménage.enfants) et - (allocations_garde_alternée.allocataire_double de enfant) - conséquence égal à Partagée +# définition allocations_familiales.charge_par_enfant de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (allocations_garde_alternée.allocataire_double de enfant) +# conséquence égal à Partagée - définition allocations_familiales.charge_par_enfant de enfant sous condition - (enfant dans ménage.enfants) et - (enfant.prise_en_charge sous forme GardeAlternée) et - (allocations_garde_alternée.demande_conjointe_partage_charge de enfant ou - allocations_garde_alternée.desaccord_charge de enfant) - conséquence égal à Partagée +# définition allocations_familiales.charge_par_enfant de enfant sous condition +# (enfant dans ménage.enfants) et +# (enfant.prise_en_charge sous forme GardeAlternée) et +# (allocations_garde_alternée.demande_conjointe_partage_charge de enfant ou +# allocations_garde_alternée.desaccord_charge de enfant) +# conséquence égal à Partagée # Quelles variables fixées par R521_2 ? @@ -258,13 +280,13 @@ remplit pas les conditions prévues au titre I du présent livre pour l'ouvertur du droit aux allocations familiales, ce droit s'ouvre du chef du père ou, à défaut, du chef de la mère. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.récipiendaire_par_enfant de enfant - sous condition - (enfant dans ménage.enfants) et - (titre_I.droits_ouverts_allocations_familiales de - (ménage.parent_en_charge de enfant)) - conséquence égal à ménage.parent1 +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.récipiendaire_par_enfant de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (titre_I.droits_ouverts_allocations_familiales de +# (ménage.parent_en_charge de enfant)) +# conséquence égal à ménage.parent1 # ménage.parent1 est le père ou à défaut la mère # (ménage.parent2 est optionnel) */ @@ -283,18 +305,18 @@ charge morale ou matérielle de l'enfant ou en vue de faciliter le retour de l'enfant dans son foyer. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.charge_par_enfant de enfant - sous condition - (enfant dans ménage.enfants) et - (enfant.confié_service_social) - conséquence égal à Complète +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.charge_par_enfant de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (enfant.confié_service_social) +# conséquence égal à Complète - définition allocations_familiales.récipiendaire_par_enfant de enfant - sous condition - (enfant dans ménage.enfants) et - (enfant.confié_service_social) - conséquence égal à service_social +# définition allocations_familiales.récipiendaire_par_enfant de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (enfant.confié_service_social) +# conséquence égal à service_social */ Un décret en Conseil d'Etat fixe les conditions d'application du présent @@ -317,26 +339,26 @@ d) enfants confiés à un service public, à une institution privée, à un part l'exception du plus âgé, ouvre droit à partir d'un âge minimum à une majoration des allocations familiales. /* -champ d'application CalculAllocationsFamiliales : - règle majorations_allocations_familiales.droits_ouverts de enfant - sous condition - (enfant dans ménage.enfants) et - (enfant != ménage.enfant_plus_âgé) et - (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) - conséquence rempli +# champ d'application CalculAllocationsFamiliales : +# règle majorations_allocations_familiales.droits_ouverts de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (enfant != ménage.enfant_plus_âgé) et +# (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) +# conséquence rempli */ Toutefois, les personnes ayant un nombre déterminé d'enfants à charge bénéficient de ladite majoration pour chaque enfant à charge à partir de l'âge mentionné au premier alinéa. /* -champ d'application CalculAllocationsFamiliales : - règle majorations_allocations_familiales.droits_ouverts de enfant - sous condition - (enfant dans ménage.enfants) et - (nombre de ménage.enfants >= l521_3.minimum_alinéa_2) et - (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) - conséquence rempli +# champ d'application CalculAllocationsFamiliales : +# règle majorations_allocations_familiales.droits_ouverts de enfant +# sous condition +# (enfant dans ménage.enfants) et +# (nombre de ménage.enfants >= l521_3.minimum_alinéa_2) et +# (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) +# conséquence rempli */ @@Titre 5 : Dispositions communes@@+++ @@ -349,8 +371,8 @@ mensuelles de calcul revalorisées au 1er avril de chaque année par application du coefficient mentionné à l'article L. 161-25 . /* # Idem que L521-1, on ne formalise pas ici l'évolution de la BMPA -champ d'application PrestationsFamiliales : - assertion fixé prestations_familiales.base_mensuelle par décret +# champ d'application PrestationsFamiliales : +# assertion fixé prestations_familiales.base_mensuelle par décret */ @@Livre 7 : Régimes divers - Dispositions diverses@@++ @@ -366,15 +388,15 @@ en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à l'ensemble des bénéficiaires de la législation générale de sécurité sociale, y compris les membres des professions agricoles. /* -champ d'application CalculPrestationsFamiliales : - règle l751_1.régime_outre_mer sous condition - (ménage.résidence = Guadeloupe) ou - (ménage.résidence = Guyane) ou - (ménage.résidence = Martinique) ou - (ménage.résidence = LaRéunion) ou - (ménage.résidence = SaintBarthélemy) ou - (ménage.résidence = SaintMartin) - conséquence rempli +# champ d'application CalculPrestationsFamiliales : +# règle l751_1.régime_outre_mer sous condition +# (ménage.résidence = Guadeloupe) ou +# (ménage.résidence = Guyane) ou +# (ménage.résidence = Martinique) ou +# (ménage.résidence = LaRéunion) ou +# (ménage.résidence = SaintBarthélemy) ou +# (ménage.résidence = SaintMartin) +# conséquence rempli */ @@Chapitre 5 : Prestations familiales et prestations assimilées@@++++ @@ -388,9 +410,9 @@ La base de calcul des prestations familiales est la même que celle qui est fixée en application de l'article L. 551-1 . /* -champ d'application CalculPrestationsFamiliales : - définition prestations_familiales.base_mensuelle_dom égal à - prestations_familiales.base_mensuelle +# champ d'application CalculPrestationsFamiliales : +# définition prestations_familiales.base_mensuelle_dom égal à +# prestations_familiales.base_mensuelle */ @Article L755-11|LEGIARTI000031323803@ @@ -408,11 +430,11 @@ longtemps que le présent chapitre V est applicable. Les allocations familiales sont dues, pour tout enfant, à la personne qui a effectivement la charge de celui-ci. /* -champ d'application CalculAllocationsFamiliales : - règle allocations_familiales.droits_ouverts sous condition - (l751_1.régime_outre_mer) et - (nombre de ménage.enfants >= 1) - conséquence rempli +# champ d'application CalculAllocationsFamiliales : +# règle allocations_familiales.droits_ouverts sous condition +# (l751_1.régime_outre_mer) et +# (nombre de ménage.enfants >= 1) +# conséquence rempli */ Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas applicables lorsque le ménage ou la personne a un seul enfant à charge. @@ -420,16 +442,16 @@ applicables lorsque le ménage ou la personne a un seul enfant à charge. # Ceci concerne l'ouverture du droit à l'allocation forfaitaire # et au complément dégressif. -champ d'application CalculAllocationsFamiliales : - règle allocation_forfaitaire.droits_ouverts de enfant sous condition - (l751_1.régime_outre_mer) et - (nombre de ménage.enfants = 1) - conséquence non rempli +# champ d'application CalculAllocationsFamiliales : +# règle allocation_forfaitaire.droits_ouverts de enfant sous condition +# (l751_1.régime_outre_mer) et +# (nombre de ménage.enfants = 1) +# conséquence non rempli - règle - complément_dégressif.droits_ouvert de allocation - sous condition - (l751_1.régime_outre_mer) et - (nombre de ménage.enfants = 1) - conséquence non rempli +# règle +# complément_dégressif.droits_ouvert de allocation +# sous condition +# (l751_1.régime_outre_mer) et +# (nombre de ménage.enfants = 1) +# conséquence non rempli */ diff --git a/examples/allocations_familiales/securite_sociale_R.catala_fr b/examples/allocations_familiales/securite_sociale_R.catala_fr index e515f1d7..23022496 100644 --- a/examples/allocations_familiales/securite_sociale_R.catala_fr +++ b/examples/allocations_familiales/securite_sociale_R.catala_fr @@ -11,8 +11,8 @@ Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième alinéa du présent article. /* -champ d'application CalculAllocationsFamiliales : - définition l512_3.âge_limite_alinéa_2 égal à 20 an +champ d'application OuvertureDroitPrestationsFamiliales : + définition âge_l512_3_2 égal à 20 */ Le plafond de rémunération mentionné au 2° de l'article L. 512-3 est égal, pour @@ -20,9 +20,9 @@ un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169. /* -champ d'application CalculAllocationsFamiliales : - définition l512_3.plafond_rémunération_mensuelle_alinéa_2 égal à - 55 % * smic.brut_horaire de ménage.résidence * 169 +champ d'application OuvertureDroitPrestationsFamiliales : + définition plafond_l512_3_2 égal à + (smic.brut_horaire *€ 55 %) *€ 169,0 */ Pour ceux des enfants qui bénéficient d'avantages en nature, l'évaluation de ces @@ -42,15 +42,15 @@ L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les enfants ouvrent droit à la majoration des allocations familiales est fixé à 14 ans. /* -champ d'application CalculAllocationsFamiliales : - définition l521_3.âge_limite_alinéa_1 de enfant égal à 14 an +# champ d'application CalculAllocationsFamiliales : +# définition l521_3.âge_limite_alinéa_1 de enfant égal à 14 an */ Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article L. 521-3 ouvrant droit à ladite majoration pour chaque enfant est fixé à trois. /* -champ d'application CalculAllocationsFamiliales : - définition l521_3.minimum_alinéa_2 égal à 3 +# champ d'application CalculAllocationsFamiliales : +# définition l521_3.minimum_alinéa_2 égal à 3 */ NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les @@ -61,15 +61,15 @@ le onzième anniversaire est postérieur au 30 avril 2008. # version du corpus législatif dont un morceau s'applique encore. Nous avons # choisi de montrer ce vieux champ d'application ici plutôt qu'à côté du texte # du décret de 2008 pour des raisons de place seulement. -champ d'application CalculAllocationFamilialesAvril2008: -# Âge limite avant décret n° 2008-409 du 28 avril 2008 - définition l521_3.minimum_alinéa_2 de enfant égal à 16 an +# champ d'application CalculAllocationFamilialesAvril2008: +# # Âge limite avant décret n° 2008-409 du 28 avril 2008 +# définition l521_3.minimum_alinéa_2 de enfant égal à 16 an -champ d'application CalculAllocationsFamiliales : - définition l521_3.minimum_alinéa_2 de enfant - sous condition (enfant.date_naissance + 11 an <= |30/04/2008|) - conséquence égal à - calcul_avril_2008.l521_3.minimum_alinéa_2 de enfant +# champ d'application CalculAllocationsFamiliales : +# définition l521_3.minimum_alinéa_2 de enfant +# sous condition (enfant.date_naissance + 11 an <= |30/04/2008|) +# conséquence égal à +# calcul_avril_2008.l521_3.minimum_alinéa_2 de enfant */ @Article R521-2|LEGIARTI000006750608@ Dans les situations visées au deuxième alinéa de l'article L. 521-2 , @@ -85,18 +85,18 @@ une demande conjointe de partage. # Le fait que l'allocataire dans le cas d'un commun accord soit celui des # deux parents désigné par l'accord est déjà modélisé dans L512-2. -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.charge_par_enfant de enfant sous condition - (enfant dans ménage.enfants) et - (enfant.prise_en_charge sous forme GardeAlternée) et - ( - (allocations_garde_alternée.demande_conjointe_partage_charge) ou - ( - (non allocations_garde_alternée.demande_conjointe_partage_charge) et - (enfant.choix_allocataire_garde_alternée sous forme Absent) - ) - ) - conséquence égal à Partagée +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.charge_par_enfant de enfant sous condition +# (enfant dans ménage.enfants) et +# (enfant.prise_en_charge sous forme GardeAlternée) et +# ( +# (allocations_garde_alternée.demande_conjointe_partage_charge) ou +# ( +# (non allocations_garde_alternée.demande_conjointe_partage_charge) et +# (enfant.choix_allocataire_garde_alternée sous forme Absent) +# ) +# ) +# conséquence égal à Partagée */ Lorsque les parents ont désigné un allocataire unique ou fait une demande @@ -116,14 +116,14 @@ multiplié par un coefficient résultant du rapport entre le nombre moyen d'enfants et le nombre total d'enfants. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.avec_garde_alternée égal à - allocations_familiales.base * - allocations_familiales.rapport_enfants_total_moyen +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.avec_garde_alternée égal à +# allocations_familiales.base * +# allocations_familiales.rapport_enfants_total_moyen - définition allocations_familiales.rapport_enfants_total_moyen égal à - allocations_familiales.nombre_moyen_enfants / - allocations_familiales.nombre_total_enfants +# définition allocations_familiales.rapport_enfants_total_moyen égal à +# allocations_familiales.nombre_moyen_enfants / +# allocations_familiales.nombre_total_enfants */ Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme @@ -133,21 +133,21 @@ du nombre d'enfants à charge dans les conditions suivantes : 2° Les autres enfants à charge comptent pour 1. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.nombre_moyen_enfants égal à - somme entier pour enfant dans ménage.enfants de ( - selon enfant.prise_en_charge sous forme - -- Complète : 1 - -- GardeAlternée de parents : 0,5 - ) +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.nombre_moyen_enfants égal à +# somme entier pour enfant dans ménage.enfants de ( +# selon enfant.prise_en_charge sous forme +# -- Complète : 1 +# -- GardeAlternée de parents : 0,5 +# ) */ Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du ou des enfants en résidence alternée et, le cas échéant, du ou des autres enfants à charge. /* -champ d'application CalculAllocationsFamiliales : - définition allocations_familiales.nombre_total_enfants égal à - nombre de ménage.enfants +# champ d'application CalculAllocationsFamiliales : +# définition allocations_familiales.nombre_total_enfants égal à +# nombre de ménage.enfants */ @Article R521-4|LEGIARTI000006750613@ @@ -164,16 +164,16 @@ Lorsque le ou les enfants ouvrant droit à ladite majoration sont en résidence alternée, le montant servi au titre de cette majoration est réduit de moitié. /* -champ d'application CalculAllocationsFamiliales : - définition - majorations_allocations_familiales.avec_garde_alternée de enfant - sous condition enfant dans ménage.enfants - conséquence égal à ( - selon enfant.prise_en_charge sous forme - -- Complète : majorations_allocations_familiales.base_par_enfant - -- GardeAlternée de parents: - majorations_allocations_familiales.base_par_enfant / 2 - ) +# champ d'application CalculAllocationsFamiliales : +# définition +# majorations_allocations_familiales.avec_garde_alternée de enfant +# sous condition enfant dans ménage.enfants +# conséquence égal à ( +# selon enfant.prise_en_charge sous forme +# -- Complète : majorations_allocations_familiales.base_par_enfant +# -- GardeAlternée de parents: +# majorations_allocations_familiales.base_par_enfant / 2 +# ) */ @@Livre 7 : Régimes divers - Dispositions diverses@@++ @@ -188,9 +188,9 @@ L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en vigueur dans chacun des départements mentionnés à l'article L. 751-1 , multiplié par 169. /* -champ d'application CalculAllocationsFamiliales : - définition l512_3.plafond_rémunération_mensuelle_alinéa_2 - sous condition l751_1.régime_outre_mer - conséquence égal à - 55 % * smic.brut_horaire de ménage.résidence * 169 +# champ d'application CalculAllocationsFamiliales : +# définition l512_3.plafond_rémunération_mensuelle_alinéa_2 +# sous condition l751_1.régime_outre_mer +# conséquence égal à +# 55 % * smic.brut_horaire de ménage.résidence * 169 */ diff --git a/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr new file mode 100644 index 00000000..56b946fe --- /dev/null +++ b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr @@ -0,0 +1,34 @@ +@@Inclusion: ../allocations_familiales.catala_fr@@ + +@Tests@ + +/* +déclaration champ d'application Test1: + contexte f champ d'application OuvertureDroitPrestationsFamiliales + +champ d'application Test1: + définition f.âge_l512_3_2_alternatif égal à Absent + définition f.date_courante égal à |01/01/2020| + définition f.prestation_courante égal à AllocationsFamiliales + définition f.résidence égal à Métropole + assertion (f.droits_ouverts de Enfant { + -- fin_obligation_scolaire : |01/08/2021| + -- âge: 13 + -- rémuneration_mensuelle: 0€ + }) + assertion (non (f.droits_ouverts de Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- âge: 17 + -- rémuneration_mensuelle: 1000€ + })) + assertion (f.droits_ouverts de Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- âge: 17 + -- rémuneration_mensuelle: 400€ + }) + assertion (non (f.droits_ouverts de Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- âge: 21 + -- rémuneration_mensuelle: 0€ + })) +*/ \ No newline at end of file diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index c4971581..b7821a43 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -557,10 +557,13 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) (Some (Pos.same_pos_as param_var param), ctxt) in let scope_updated = - let x_def, x_type = + let x_def, x_type, is_cond = match Desugared.Ast.ScopeDefMap.find_opt def_key scope.scope_defs with | Some def -> def - | None -> (Desugared.Ast.RuleMap.empty, Name_resolution.get_def_typ ctxt def_key) + | None -> + ( Desugared.Ast.RuleMap.empty, + Name_resolution.get_def_typ ctxt def_key, + Name_resolution.is_def_cond ctxt def_key ) in let rule_name = match def.Ast.definition_label with @@ -590,7 +593,7 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) in { scope with - scope_defs = Desugared.Ast.ScopeDefMap.add def_key (x_def, x_type) scope.scope_defs; + scope_defs = Desugared.Ast.ScopeDefMap.add def_key (x_def, x_type, is_cond) scope.scope_defs; } in { @@ -693,9 +696,9 @@ let desugar_program (ctxt : Name_resolution.context) (prgm : Ast.program) : Desu Desugared.Ast.scope_defs = Desugared.Ast.IdentMap.fold (fun _ v acc -> + let x, y = Scopelang.Ast.ScopeVarMap.find v ctxt.Name_resolution.var_typs in Desugared.Ast.ScopeDefMap.add (Desugared.Ast.ScopeDef.Var v) - ( Desugared.Ast.RuleMap.empty, - Scopelang.Ast.ScopeVarMap.find v ctxt.Name_resolution.var_typs ) + (Desugared.Ast.RuleMap.empty, x, y) acc) s_context.Name_resolution.var_idmap Desugared.Ast.ScopeDefMap.empty; Desugared.Ast.scope_assertions = []; diff --git a/src/catala/catala_surface/name_resolution.ml b/src/catala/catala_surface/name_resolution.ml index c47dcbc6..4edb802c 100644 --- a/src/catala/catala_surface/name_resolution.ml +++ b/src/catala/catala_surface/name_resolution.ml @@ -57,7 +57,7 @@ type context = { scopes : scope_context Scopelang.Ast.ScopeMap.t; (** For each scope, its context *) structs : struct_context Scopelang.Ast.StructMap.t; (** For each struct, its context *) enums : enum_context Scopelang.Ast.EnumMap.t; (** For each enum, its context *) - var_typs : typ Pos.marked Scopelang.Ast.ScopeVarMap.t; + var_typs : (typ Pos.marked * bool) (* is it a condition? *) Scopelang.Ast.ScopeVarMap.t; (** The types of each scope variable declared *) } (** Main context used throughout {!module: Surface.Desugaring} *) @@ -77,7 +77,10 @@ let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) = (** Gets the type associated to an uid *) let get_var_typ (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : typ Pos.marked = - Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs + fst (Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs) + +let is_var_cond (ctxt : context) (uid : Scopelang.Ast.ScopeVar.t) : bool = + snd (Scopelang.Ast.ScopeVarMap.find uid ctxt.var_typs) (** Get the variable uid inside the scope given in argument *) let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) @@ -115,7 +118,15 @@ let get_def_typ (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : typ Pos.mark (* we don't need to look at the subscope prefix because [x] is already the uid referring back to the original subscope *) | Desugared.Ast.ScopeDef.Var x -> - Scopelang.Ast.ScopeVarMap.find x ctxt.var_typs + get_var_typ ctxt x + +let is_def_cond (ctxt : context) (def : Desugared.Ast.ScopeDef.t) : bool = + match def with + | Desugared.Ast.ScopeDef.SubScopeVar (_, x) + (* we don't need to look at the subscope prefix because [x] is already the uid referring back to + the original subscope *) + | Desugared.Ast.ScopeDef.Var x -> + is_var_cond ctxt x (** {1 Declarations pass} *) @@ -150,6 +161,11 @@ let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) in { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes } +let is_type_cond ((typ, _) : Ast.typ Pos.marked) = + match typ with + | Ast.Base Ast.Condition | Ast.Func { arg_typ = _; return_typ = Ast.Condition, _ } -> true + | _ -> false + (** Process a basic type (all types except function types) *) let rec process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) : Scopelang.Ast.typ Pos.marked = @@ -192,6 +208,7 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) (decl : Ast.scope_decl_context_data) : context = (* First check the type of the context data *) 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 = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in match Desugared.Ast.IdentMap.find_opt name scope_ctxt.var_idmap with @@ -209,7 +226,7 @@ let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context) { ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes; - var_typs = Scopelang.Ast.ScopeVarMap.add uid data_typ ctxt.var_typs; + var_typs = Scopelang.Ast.ScopeVarMap.add uid (data_typ, is_cond) ctxt.var_typs; } (** Process an item declaration *) diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 218cedda..42296c41 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -466,9 +466,9 @@ struct_scope: struct_decl_field_name = name; struct_decl_field_typ = match func_typ with | None -> (Base typ, typ_pos) - | Some (return_typ, return_pos) -> (Func { - arg_typ = (typ, typ_pos); - return_typ = (Data return_typ, return_pos); + | Some (arg_typ, arg_pos) -> (Func { + arg_typ = (Data arg_typ, arg_pos); + return_typ = (typ, typ_pos); }, $sloc) ; }, $sloc) } @@ -480,9 +480,9 @@ scope_decl_item: let (typ, typ_pos) = t in match func_typ with | None -> (Base (Data typ), typ_pos) - | Some (return_typ, return_pos) -> (Func { - arg_typ = (Data typ, typ_pos); - return_typ = (Data return_typ, return_pos); + | Some (arg_typ, arg_pos) -> (Func { + arg_typ = (Data arg_typ, arg_pos); + return_typ = (Data typ, typ_pos); }, $sloc); }), $sloc) } | CONTEXT i = ident SCOPE c = constructor { @@ -496,9 +496,9 @@ scope_decl_item: scope_decl_context_item_typ = match func_typ with | None -> (Base (Condition), $loc(_condition)) - | Some (return_typ, return_pos) -> (Func { - arg_typ = (Condition, $loc(_condition)); - return_typ = (Data return_typ, return_pos); + | Some (arg_typ, arg_pos) -> (Func { + arg_typ = (Data arg_typ, arg_pos); + return_typ = (Condition, $loc(_condition)); }, $sloc); }), $sloc) } diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index 5e5b5ef7..b42b908f 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -135,6 +135,7 @@ let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked A.ELit (LBool (ODate.Unix.compare i1 i2 > 0)) | A.Binop (A.Gte KDate), [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 >= 0)) + | A.Binop A.Eq, [ ELit LUnit; ELit LUnit ] -> A.ELit (LBool true) | A.Binop A.Eq, [ ELit (LDuration i1); ELit (LDuration i2) ] -> A.ELit (LBool (i1 = i2)) | A.Binop A.Eq, [ ELit (LDate i1); ELit (LDate i2) ] -> A.ELit (LBool (ODate.Unix.compare i1 i2 = 0)) @@ -170,7 +171,7 @@ let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked A.ELit (LBool ( try - List.for_all2 type_eq ts1 ts2 && i1 == i2 + List.for_all2 type_eq ts1 ts2 && i1 = i2 && match Pos.unmark (evaluate_operator op [ e1; e2 ]) with | A.ELit (LBool b) -> b @@ -340,7 +341,7 @@ and evaluate_expr (e : A.expr Pos.marked) : A.expr Pos.marked = | ELit (LBool true) -> Pos.same_pos_as (Ast.ELit LUnit) e' | ELit (LBool false) -> ( match Pos.unmark e' with - | EApp ((Ast.EOp (Binop op), pos_op), [ e1; e2 ]) -> + | EApp ((Ast.EOp (Binop op), pos_op), [ ((ELit _, _) as e1); ((ELit _, _) as e2) ]) -> Errors.raise_spanned_error (Format.asprintf "Assertion failed: %a %a %a" Print.format_expr e1 Print.format_binop (op, pos_op) Print.format_expr e2) diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index 33ef9461..d76180a3 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -143,7 +143,7 @@ let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ | EApp _ -> true | _ -> false let format_var (fmt : Format.formatter) (v : Var.t) : unit = - Format.fprintf fmt "%s" (Bindlib.name_of v) + Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v) let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = @@ -153,9 +153,9 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = match Pos.unmark e with | EVar v -> Format.fprintf fmt "%a" format_var (Pos.unmark v) | ETuple es -> - Format.fprintf fmt "(%a)" + Format.fprintf fmt "@[(%a)@]" (Format.pp_print_list - ~pp_sep:(fun fmt () -> Format.fprintf fmt ",") + ~pp_sep:(fun fmt () -> Format.fprintf fmt ",@ ") (fun fmt (e, struct_field) -> match struct_field with | Some struct_field -> @@ -164,7 +164,7 @@ let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = | None -> Format.fprintf fmt "@[%a@]" format_expr e)) es | EArray es -> - Format.fprintf fmt "[%a]" + Format.fprintf fmt "@[[%a]@]" (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ";@ ") (fun fmt e -> Format.fprintf fmt "@[%a@]" format_expr e)) diff --git a/src/catala/desugared/ast.ml b/src/catala/desugared/ast.ml index 074d94e6..75ba0b0a 100644 --- a/src/catala/desugared/ast.ml +++ b/src/catala/desugared/ast.ml @@ -83,6 +83,17 @@ let empty_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked opti exception_to_rule = None; } +let always_false_rule (pos : Pos.t) (have_parameter : Scopelang.Ast.typ Pos.marked option) : rule = + { + just = Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool true), pos); + cons = Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LBool false), pos); + parameter = + ( match have_parameter with + | Some typ -> Some (Scopelang.Ast.Var.make ("dummy", pos), typ) + | None -> None ); + exception_to_rule = None; + } + type assertion = Scopelang.Ast.expr Pos.marked Bindlib.box type variation_typ = Increasing | Decreasing @@ -97,7 +108,8 @@ type scope = { scope_vars : Scopelang.Ast.ScopeVarSet.t; scope_sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t; scope_uid : Scopelang.Ast.ScopeName.t; - scope_defs : (rule RuleMap.t * Scopelang.Ast.typ Pos.marked) ScopeDefMap.t; + scope_defs : + (rule RuleMap.t * Scopelang.Ast.typ Pos.marked * bool) (* is it a condition? *) ScopeDefMap.t; scope_assertions : assertion list; scope_meta_assertions : meta_assertion list; } diff --git a/src/catala/desugared/dependency.ml b/src/catala/desugared/dependency.ml index b1295594..64e50967 100644 --- a/src/catala/desugared/dependency.ml +++ b/src/catala/desugared/dependency.ml @@ -127,7 +127,7 @@ let build_scope_dependencies (scope : Ast.scope) : ScopeDependencies.t = in let g = Ast.ScopeDefMap.fold - (fun def_key (def, _) g -> + (fun def_key (def, _, _) g -> let fv = Ast.free_variables def in Ast.ScopeDefMap.fold (fun fv_def fv_def_pos g -> diff --git a/src/catala/desugared/desugared_to_scope.ml b/src/catala/desugared/desugared_to_scope.ml index 8adf2da5..cc06964b 100644 --- a/src/catala/desugared/desugared_to_scope.ml +++ b/src/catala/desugared/desugared_to_scope.ml @@ -94,8 +94,9 @@ let rec def_map_to_tree (def_info : Ast.ScopeDef.t) (** From the {!type: rule_tree}, builds an {!constructor: Dcalc.Ast.EDefault} expression in the scope language. The [~toplevel] parameter is used to know when to place the toplevel binding in the case of functions. *) -let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t option) - (tree : rule_tree) : Scopelang.Ast.expr Pos.marked Bindlib.box = +let rec rule_tree_to_expr ~(toplevel : bool) (def_pos : Pos.t) + (is_func : Scopelang.Ast.Var.t option) (tree : rule_tree) : + Scopelang.Ast.expr Pos.marked Bindlib.box = let exceptions, rule = match tree with Leaf r -> ([], r) | Node (exceptions, r) -> (exceptions, r) in @@ -116,7 +117,7 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti let just = substitute_parameter rule.Ast.just in let cons = substitute_parameter rule.Ast.cons in let exceptions = - Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false is_func) exceptions) + Bindlib.box_list (List.map (rule_tree_to_expr ~toplevel:false def_pos is_func) exceptions) in let default = Bindlib.box_apply3 @@ -128,7 +129,17 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti | None, None -> default | Some new_param, Some (_, typ) -> if toplevel then - Scopelang.Ast.make_abs (Array.of_list [ new_param ]) default Pos.no_pos [ typ ] Pos.no_pos + (* When we're creating a function from multiple defaults, we must check that the result + returned by the function is not empty *) + let default = + Bindlib.box_apply + (fun (default : Scopelang.Ast.expr * Pos.t) -> + ( Scopelang.Ast.EApp + ((Scopelang.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.ErrorOnEmpty), def_pos), [ default ]), + def_pos )) + default + in + Scopelang.Ast.make_abs (Array.of_list [ new_param ]) default def_pos [ typ ] def_pos else default | _ -> (* should not happen *) assert false @@ -137,7 +148,7 @@ let rec rule_tree_to_expr ~(toplevel : bool) (is_func : Scopelang.Ast.Var.t opti (** Translates a definition inside a scope, the resulting expression should be an {!constructor: Dcalc.Ast.EDefault} *) let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) - (typ : Scopelang.Ast.typ Pos.marked) : Scopelang.Ast.expr Pos.marked = + (typ : Scopelang.Ast.typ Pos.marked) (is_cond : bool) : Scopelang.Ast.expr Pos.marked = (* Here, we have to transform this list of rules into a default tree. *) let is_func _ (r : Ast.rule) : bool = Option.is_some r.Ast.parameter in let all_rules_func = Ast.RuleMap.for_all is_func def in @@ -167,14 +178,18 @@ let translate_def (def_info : Ast.ScopeDef.t) (def : Ast.rule Ast.RuleMap.t) (Ast.RuleMap.bindings (Ast.RuleMap.filter (fun n r -> not (is_func n r)) def)) ) in let top_list = def_map_to_tree def_info is_def_func def in + let top_value = + (if is_cond then Ast.always_false_rule else Ast.empty_rule) Pos.no_pos is_def_func + in Bindlib.unbox (rule_tree_to_expr ~toplevel:true + (Ast.ScopeDef.get_position def_info) (Option.map (fun _ -> Scopelang.Ast.Var.make ("ρ", Pos.no_pos)) is_def_func) ( match top_list with | [] -> (* In this case, there are no rules to define the expression *) - Leaf (Ast.empty_rule Pos.no_pos is_def_func) - | _ -> Node (top_list, Ast.empty_rule Pos.no_pos is_def_func) )) + Leaf top_value + | _ -> Node (top_list, top_value) )) (** Translates a scope *) let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = @@ -187,10 +202,10 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = (fun vertex -> match vertex with | Dependency.Vertex.Var (var : Scopelang.Ast.ScopeVar.t) -> - let var_def, var_typ = + let var_def, var_typ, is_cond = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in - let expr_def = translate_def (Ast.ScopeDef.Var var) var_def var_typ in + let expr_def = translate_def (Ast.ScopeDef.Var var) var_def var_typ is_cond in [ Scopelang.Ast.Definition ( ( Scopelang.Ast.ScopeVar @@ -207,11 +222,11 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = in let sub_scope_vars_redefs = Ast.ScopeDefMap.mapi - (fun def_key (def, def_typ) -> + (fun def_key (def, def_typ, is_cond) -> match def_key with | Ast.ScopeDef.Var _ -> assert false (* should not happen *) | Ast.ScopeDef.SubScopeVar (_, sub_scope_var) -> - let expr_def = translate_def def_key def def_typ in + let expr_def = translate_def def_key def def_typ is_cond in let subscop_real_name = Scopelang.Ast.SubScopeMap.find sub_scope_index scope.scope_sub_scopes in @@ -248,7 +263,7 @@ let translate_scope (scope : Ast.scope) : Scopelang.Ast.scope_decl = let scope_sig = Scopelang.Ast.ScopeVarSet.fold (fun var acc -> - let _, typ = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in + let _, typ, _ = Ast.ScopeDefMap.find (Ast.ScopeDef.Var var) scope.scope_defs in Scopelang.Ast.ScopeVarMap.add var typ acc) scope.scope_vars Scopelang.Ast.ScopeVarMap.empty in diff --git a/syntax_highlighting/en/ace/mode-catala_en.js b/syntax_highlighting/en/ace/mode-catala_en.js index d9fa9626..e7c1da96 100644 --- a/syntax_highlighting/en/ace/mode-catala_en.js +++ b/syntax_highlighting/en/ace/mode-catala_en.js @@ -74,7 +74,7 @@ ace.define("ace/mode/catala_en_highlighting_rules", ["require", "exports", "modu }, { "token": "keyword.operator", - "regex": "(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)" + "regex": "(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\$|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\$|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\$|\\*|/\\.|/\\@|/\\^|/\\$|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\$|>=\\$|<=\\$|<\\$|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|not|or|and|\\$|%|year|month|day)" }, { "token": "support.type", diff --git a/syntax_highlighting/en/atom/grammars/catala_en.cson b/syntax_highlighting/en/atom/grammars/catala_en.cson index 734544f5..d641c9b7 100644 --- a/syntax_highlighting/en/atom/grammars/catala_en.cson +++ b/syntax_highlighting/en/atom/grammars/catala_en.cson @@ -120,7 +120,7 @@ 'name' : 'punctuation.catala_en' } { - 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)' + 'match' : '(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\$|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\$|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\$|\\*|/\\.|/\\@|/\\^|/\\$|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\$|>=\\$|<=\\$|<\\$|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|not|or|and|\\$|%|year|month|day)' 'name' : 'keyword.operator.catala_en' } { diff --git a/syntax_highlighting/en/catala_en.iro b/syntax_highlighting/en/catala_en.iro index 4c4e2ab1..b2b6241c 100644 --- a/syntax_highlighting/en/catala_en.iro +++ b/syntax_highlighting/en/catala_en.iro @@ -239,8 +239,8 @@ code : context { styles [] = .punctuation; } - : pattern { - regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) + : pattern { + regex \= (\-\>|\+\.|\+\@|\+\^|\+\$|\+|\-\.|\-\@|\-\^|\-\$|\-|\*\.|\*\@|\*\^|\*\$|\*|/\.|/\@|/\^|/\$|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\$|>=\$|<=\$|<\$|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|not|or|and|\$|%|year|month|day) styles [] = .operator; } diff --git a/syntax_highlighting/en/pygments/catala_en.py b/syntax_highlighting/en/pygments/catala_en.py index e70604ea..db4934f1 100644 --- a/syntax_highlighting/en/pygments/catala_en.py +++ b/syntax_highlighting/en/pygments/catala_en.py @@ -33,8 +33,7 @@ class CatalaEnLexer(RegexLexer): (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})', bygroups( Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\$|%|year|month|day)', - bygroups(Operator)), + (u'(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\$|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\$|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\$|\\*|/\\.|/\\@|/\\^|/\\$|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\$|>=\\$|<=\\$|<\\$|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|not|or|and|\\$|%|year|month|day)', bygroups(Operator)), (u'\\b(integer|boolean|date|money|text|decimal|number|sum)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), diff --git a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml index 3eebc2b4..b9ae2d9e 100644 --- a/syntax_highlighting/en/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/en/vscode/syntaxes/catalavs.xml @@ -191,7 +191,7 @@ match - (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) + (\-\>|\+\.|\+\@|\+\^|\+\$|\+|\-\.|\-\@|\-\^|\-\$|\-|\*\.|\*\@|\*\^|\*\$|\*|/\.|/\@|/\^|/\$|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\$|>=\$|<=\$|<\$|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|not|or|and|\$|%|year|month|day) name keyword.operator.catala_en diff --git a/syntax_highlighting/fr/ace/mode-catala_fr.js b/syntax_highlighting/fr/ace/mode-catala_fr.js index 0b19c36b..da2a9c38 100644 --- a/syntax_highlighting/fr/ace/mode-catala_fr.js +++ b/syntax_highlighting/fr/ace/mode-catala_fr.js @@ -74,7 +74,7 @@ ace.define("ace/mode/catala_fr_highlighting_rules", ["require", "exports", "modu }, { "token": "keyword.operator", - "regex": "(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\\u20ac|%|an|mois|jour)" + "regex": "(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\u20ac|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\u20ac|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\u20ac|\\*|/\\.|/\\@|/\\^|/\\u20ac|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\u20ac|>=\\u20ac|<=\\u20ac|<\\u20ac|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|non|ou|et|\\u20ac|%|an|mois|jour)" }, { "token": "support.type", diff --git a/syntax_highlighting/fr/atom/grammars/catala_fr.cson b/syntax_highlighting/fr/atom/grammars/catala_fr.cson index a74fb5fe..e35c0dd1 100644 --- a/syntax_highlighting/fr/atom/grammars/catala_fr.cson +++ b/syntax_highlighting/fr/atom/grammars/catala_fr.cson @@ -120,7 +120,7 @@ 'name' : 'punctuation.catala_fr' } { - 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\\x{20ac}|%|an|mois|jour)' + 'match' : '(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\x{20ac}|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\x{20ac}|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\x{20ac}|\\*|/\\.|/\\@|/\\^|/\\x{20ac}|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\x{20ac}|>=\\x{20ac}|<=\\x{20ac}|<\\x{20ac}|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|non|ou|et|\\x{20ac}|%|an|mois|jour)' 'name' : 'keyword.operator.catala_fr' } { diff --git a/syntax_highlighting/fr/catala_fr.iro b/syntax_highlighting/fr/catala_fr.iro index 500473d9..6f0e0cc9 100644 --- a/syntax_highlighting/fr/catala_fr.iro +++ b/syntax_highlighting/fr/catala_fr.iro @@ -239,8 +239,8 @@ code : context { styles [] = .punctuation; } - : pattern { - regex \= (\-\>|\+|\-|\*|/|\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour) + : pattern { + regex \= (\-\>|\+\.|\+\@|\+\^|\+\u20ac|\+|\-\.|\-\@|\-\^|\-\u20ac|\-|\*\.|\*\@|\*\^|\*\u20ac|\*|/\.|/\@|/\^|/\u20ac|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\u20ac|>=\u20ac|<=\u20ac|<\u20ac|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|non|ou|et|\u20ac|%|an|mois|jour) styles [] = .operator; } diff --git a/syntax_highlighting/fr/pygments/catala_fr.py b/syntax_highlighting/fr/pygments/catala_fr.py index e629980d..f242c9b3 100644 --- a/syntax_highlighting/fr/pygments/catala_fr.py +++ b/syntax_highlighting/fr/pygments/catala_fr.py @@ -33,8 +33,7 @@ class CatalaFrLexer(RegexLexer): (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:|\\(|\\)|\\[|\\]|\\{|\\})', bygroups( Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|non|ou|et|=|>|<|\u20ac|%|an|mois|jour)', - bygroups(Operator)), + (u'(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\u20ac|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\u20ac|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\u20ac|\\*|/\\.|/\\@|/\\^|/\u20ac|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\u20ac|>=\u20ac|<=\u20ac|<\u20ac|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|non|ou|et|\u20ac|%|an|mois|jour)', bygroups(Operator)), (u'\\b(entier|bool\xe9en|date|argent|texte|d\xe9cimal|d\xe9cret|loi|nombre|somme)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xf4\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xd4\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), diff --git a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml index 47039654..369da1d6 100644 --- a/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/fr/vscode/syntaxes/catalavs.xml @@ -191,7 +191,7 @@ match - (\-\>|\+|\-|\*|/|\!|non|ou|et|=|>|<|\x{20ac}|%|an|mois|jour) + (\-\>|\+\.|\+\@|\+\^|\+\x{20ac}|\+|\-\.|\-\@|\-\^|\-\x{20ac}|\-|\*\.|\*\@|\*\^|\*\x{20ac}|\*|/\.|/\@|/\^|/\x{20ac}|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\x{20ac}|>=\x{20ac}|<=\x{20ac}|<\x{20ac}|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|non|ou|et|\x{20ac}|%|an|mois|jour) name keyword.operator.catala_fr diff --git a/syntax_highlighting/nv/atom/grammars/catala_nv.cson b/syntax_highlighting/nv/atom/grammars/catala_nv.cson index f732b837..23fc9629 100644 --- a/syntax_highlighting/nv/atom/grammars/catala_nv.cson +++ b/syntax_highlighting/nv/atom/grammars/catala_nv.cson @@ -120,7 +120,7 @@ 'name' : 'punctuation.catala_nv' } { - 'match' : '(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)' + 'match' : '(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\$|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\$|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\$|\\*|/\\.|/\\@|/\\^|/\\$|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\$|>=\\$|<=\\$|<\\$|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|not|or|and|\\$|%|year|month|day)' 'name' : 'keyword.operator.catala_nv' } { diff --git a/syntax_highlighting/nv/catala_nv.iro b/syntax_highlighting/nv/catala_nv.iro index 0dbdc016..6b1e9cbd 100644 --- a/syntax_highlighting/nv/catala_nv.iro +++ b/syntax_highlighting/nv/catala_nv.iro @@ -240,7 +240,7 @@ code : context { } : pattern { - regex \= (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) + regex \= (\-\>|\+\.|\+\@|\+\^|\+\$|\+|\-\.|\-\@|\-\^|\-\$|\-|\*\.|\*\@|\*\^|\*\$|\*|/\.|/\@|/\^|/\$|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\$|>=\$|<=\$|<\$|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|not|or|and|\$|%|year|month|day) styles [] = .operator; } diff --git a/syntax_highlighting/nv/pygments/catala_nv.py b/syntax_highlighting/nv/pygments/catala_nv.py index 316f31a7..f37977dd 100644 --- a/syntax_highlighting/nv/pygments/catala_nv.py +++ b/syntax_highlighting/nv/pygments/catala_nv.py @@ -33,8 +33,7 @@ class CatalaNvLexer(RegexLexer): (u'\\b([0-9]+(,[0.9]*|))\\b', bygroups(Number.Integer)), (u'(\\-\\-|\\;|\\.|\\,|\\:=|\\:|\\(|\\)|\\[\\||\\|\\]|\\[|\\]|\\{|\\})', bygroups(Operator)), - (u'(\\-\\>|\\+|\\-|\\*|/|\\!|not|or|and|=|>|<|\\$|%|year|month|day)', - bygroups(Operator)), + (u'(\\-\\>|\\+\\.|\\+\\@|\\+\\^|\\+\\$|\\+|\\-\\.|\\-\\@|\\-\\^|\\-\\$|\\-|\\*\\.|\\*\\@|\\*\\^|\\*\\$|\\*|/\\.|/\\@|/\\^|/\\$|/|\\!|>\\.|>=\\.|<=\\.|<\\.|>\\@|>=\\@|<=\\@|<\\@|>\\$|>=\\$|<=\\$|<\\$|>\\^|>=\\^|<=\\^|<\\^|>|>=|<=|<|=|not|or|and|\\$|%|year|month|day)', bygroups(Operator)), (u'\\b(int|bool|date|money|text|decimal|number|sum)\\b', bygroups(Keyword.Type)), (u'\\b([A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)(\\.)([a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7][a-z\xe9\xe8\xe0\xe2\xf9\xee\xea\u0153\xe7A-Z\xc9\xc8\xc0\xc2\xd9\xce\xca\u0152\xc70-9_\\\']*)\\b', bygroups(Name.Class, Operator, Name.Variable)), diff --git a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml index ec86f5e9..418bc829 100644 --- a/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml +++ b/syntax_highlighting/nv/vscode/syntaxes/catalavs.xml @@ -191,7 +191,7 @@ match - (\-\>|\+|\-|\*|/|\!|not|or|and|=|>|<|\$|%|year|month|day) + (\-\>|\+\.|\+\@|\+\^|\+\$|\+|\-\.|\-\@|\-\^|\-\$|\-|\*\.|\*\@|\*\^|\*\$|\*|/\.|/\@|/\^|/\$|/|\!|>\.|>=\.|<=\.|<\.|>\@|>=\@|<=\@|<\@|>\$|>=\$|<=\$|<\$|>\^|>=\^|<=\^|<\^|>|>=|<=|<|=|not|or|and|\$|%|year|month|day) name keyword.operator.catala_nv From 8f2811b66fac6457ff63b64068a6d39e3d4eedcf Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Thu, 31 Dec 2020 00:32:17 +0100 Subject: [PATCH 135/142] Changed output formatting --- tests/test_struct/nested3.catala.A.out | 2 +- tests/test_struct/nested3.catala.B.out | 2 +- tests/test_struct/simple.catala.A.out | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_struct/nested3.catala.A.out b/tests/test_struct/nested3.catala.A.out index 19684eab..58e046f6 100644 --- a/tests/test_struct/nested3.catala.A.out +++ b/tests/test_struct/nested3.catala.A.out @@ -1,2 +1,2 @@ [RESULT] Computation successful! Results: -[RESULT] t = ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) +[RESULT] t = ("a": ("x": 0, "y": false), "b": ("x": 1, "y": true)) diff --git a/tests/test_struct/nested3.catala.B.out b/tests/test_struct/nested3.catala.B.out index 6bd1ec5b..6d96ed94 100644 --- a/tests/test_struct/nested3.catala.B.out +++ b/tests/test_struct/nested3.catala.B.out @@ -1,3 +1,3 @@ [RESULT] Computation successful! Results: [RESULT] out = 1 -[RESULT] t = ("a": ("x": 0,"y": false),"b": ("x": 1,"y": true)) +[RESULT] t = ("a": ("x": 0, "y": false), "b": ("x": 1, "y": true)) diff --git a/tests/test_struct/simple.catala.A.out b/tests/test_struct/simple.catala.A.out index 9f5a68ed..909c6034 100644 --- a/tests/test_struct/simple.catala.A.out +++ b/tests/test_struct/simple.catala.A.out @@ -1,3 +1,3 @@ [RESULT] Computation successful! Results: -[RESULT] s = ("x": 1,"y": 2) +[RESULT] s = ("x": 1, "y": 2) [RESULT] z = 3 From 0482acbd01da5e8e4445253785e166ebb23006eb Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 3 Jan 2021 18:52:41 +0100 Subject: [PATCH 136/142] Fixed incorrect date --- doc/images/CatalaScreenShot.png | Bin 171148 -> 117623 bytes examples/us_tax_code/section_1015.catala_en | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/images/CatalaScreenShot.png b/doc/images/CatalaScreenShot.png index 294e97ccda4b316c0f10b8ea0faddf662abed740..cb52a2de960f52d581663756878c50797301d00e 100644 GIT binary patch literal 117623 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�lT9sqYN`AF59Vs=gk^O^a(}Td**&)8 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 z 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�lT9sqYN`AF59Vs=gk^O^a(}Td**&)8 z6yONcND@;x4-%_c8hUP%dBUI_^OJq4R1GWC0e!5h1ba*ZH$aX3dTTWy_5C9I3wx6B zf3X|)wWNzrU2gV|jZ!C1cx{<3Ui$3@>i?&pO7z_OeXn&W|2;?Rn>W2x9N5h>a@1*f z|0#WQE5_%^8-(KRQ%7L^IK7%`uv^tlKd^J#(Ii#xS7}Ti_sy+_ystJa{*wmTZXvS~{JWh$B%EcpXO#V!X^8tOoAt z@{Z5aE!I-ArnFEIfpP&1I~PTQcZtQP*zMMj3Hc)$NWoZs4Vig9r*94M7e48I4=J8G zZ7Jk$c`iB_CtNxjSz50vnVgBB>;}W zca9?SkH3ntdh(yOXsUD%Z&;P;JJ~yGj6Aq(lR2CL5EOrTAYYrEEUxPyR*8T$fYhh_ zrLbg6lkb||iogdgPLSX#vvTouHY&2#jV-LrD)TTOrX))v_u z97KQ>W&75kcwnmaoBQaXfc7**B^y!1dgat>O%KtK1hB+kY-$-5Q>^^jD3yBh!oB)! z*=rDrT8!(@mKBtk-X5gljw9MGXV?N0&&ULv?Q&-Oklas3R5LF$dc#EXq%&e*QXsv2 z>yiUHj3DPYs2j&J&eb zW@~xx98zvt9ZB!t-qc)fq|w^l_{}&7zMYyocS)4Ps4Bw zjXqGTHb$MTHpVtV%inBf_csPG;f=aRBZ~DGJ84F83IT*AF|Q$vs*IG{kj-q_6Mn9t zSvj&cRxWf~-Jll&m|29C$CJjf+(%}QkNEnt85g!eczn%|ULQ4(oxX;1S~hHNOW2or zUs+#w+HN0Se2c#hN4mUf2LqFGq}G$tY1L>2PczN4Lo8d&)~i}cu&)YuUY;?!V{G$05MOgzHAl>N*0e?<`i5wJH*V4-iMux zs?tCxG7_&}I@PZ)WyX$w6dL@&YXui~4QxB@lXHqZ-}4TsKjg($9AsDjjA3<=tNxow z+1xj9yXz78oW`KtAVV-s*JPCx4tvL=>?JP%({j_C_F&R2BKnyoPSz|C}N$llu<>XND02G z5oCJuTlZw~G)rSvE3Z)(K0C9*pnRXbs*X+m#d{FA;O3nppodjXfF^RF7x6Gdd59ok7>7CsWF}}P8Jmk>9hC=g( zM4d}(Bl3+H=tpFX9@DiO>-3F&hxZ&7D~+cNrf9<*BF_Ol&Qc$*d0nD)9i1cJ>;EH*Ne0^zRE(VJJS1iP}g^_^N)`e;J>q6KIs za8#i`J4r+-A&|rJ#MWzcrl<_ELp5Ye{7s>VPJn$dhOeRvJdC>VY(HrpxBc%oaFES6u;&l#G(y z@8|qoOIBE6tfm>B;UFnU2eaT$E>SKp=5;f==@l-0$1>9=55sbjTYM9}i0NHf+2+?b ze^E}ffjrCzgkw{;-_`$z(-Ak*X%XoH&FZ&tbz+RBcUnfh>&IJuJ6n)B-<156n^1!d^ngtkF!2pI?#|-J1HAK+<{mVeOyd{If)fX~uB1|8fX? zEg3$mY}89uZ1j=$qU^-rbo`TSd{HNmP@A>p5{4cPz?Ve zKkAy7Rl;IL58neKz@h$NauN!oF^1c$=i;w%FWA)YlR~C1I7S>^is5XQjchO=R5^5% z>T$KKp5&;X?#h`i$9bgWOR6E6Rp%GA4e!^Jg^;&_p=AUOv(PRWpQ9D*Ao3K^X~}9; z25}o>%p!O*>gF7g4^&7d2yHfMO?PORB5e9lKNdn>uqfMgs54|YRp71`mKHUBRV&Yu zQJwtlk_sQ@KL1Z0^dbHAbAMI_Nc=%H>Iy2!6aFen+G5QACFHH92cJ3`jsud2&c{yD z($pC(*#)Yeg&91xA3lbH_E+Cz#4Xa%OfJ1-D=*k=x}5@^yd^=K_CrdUV;*tpj3#=eB@dk(0l z2t}xPf-M1=DVh>6vEA7xf?-@xUob!`kcc4ogQBaE$ve%eXW8ffozBji-FyZ8hD?qt z&GV;y-ev$0_c%3Pq79p?MnIbh#!f+J$@G?`cFl8~7hcQX-1k%=W{AcGQRACKqW)`f zi-TS>Lu|boHFh`9jLYRe4BYx!9ngay{DXnk1^;fpMnU)htS)Dnfc_+ml?Es9`C)r7 zO~JV@TyIN_Xw0wYP2XsEQ%4*%QnM73>oJ-1;dVZBy}W;+GG6Z~995MSGMQY?mSV{S za&#5JZ{9^m>tR$ke5esB5 zwMv7c3bg%C6`4}#bR~GULU~~f@^6X*ld?qQ`=1!+He7G%kx^m$cOkc`oDsuDOt{dJ zmZ)TXg6xf=#Hj!p^pZuh{R1-R+Wq$m#BkAKSRryyKL#kQe%_?R4MqoIwS?@P-mWBA z-0wg^Mx9gHYHuva2;-nk2&f(ITp`q=c|Ha-mIDgd?R z&^-t712?{BQf!^XTD~NSWS=jlU4E+Ql6!fK@qz!mUG`*iz6Y5s-T^X7W3bz|$s$Pp z3o0131tvi08v`->OBZqjxLQCciG^N6nD!aHlu24+dco#aEfxZznL|>( z{xSPaXo)RgWCrQPCTqrUt#Q*w4qof%G7XsVjuTAS7z%$#6}Rgk8W5ESZqLq)#XZ6i zDsn&`Ilir!K8kS@^Q;LH2M>6p!@>se_{ZbkngBqBcq_97I`V5h% zsccTI09=<@_bm$eTu~XVa;4b5L5*kQZB+j4HES6O9jdKlSoz;YQ8k`&b;2lfg5^(~`1ZtDeI=0f_ekyWj2Rw-6dIYQ_Zg01OWq|Ytd zOL>=3k7IK#?wVKr2@gUcCrJH`VJjT2lew+Tny`3gP2eMamxF@2-}r6_TsV_ic>Qsn zUkq}emcTb&^IGdQE^-ESN+Cj6!3B-sZDKW2hT+N~eoB4WV)mjvwL4~3g}Py)Xh=cK zzhVk&gU7_Uh1w#_d)bH&>1@~^Jy|)^+nW>c0D1QCq;? zH$?P`%!i$?J1pufDRgSj`RS@(M;@qJPo^O~4vsVa{hag_&>kmQVtZh}grxg&+*QE3 zfd>9c#Y*GHUf8OZ_#I^cvHl**pq^KH!`Up)>ZfJF^%6N3j;z({Zy_YSNOH+&HrDvX z^`nA${6lf>zi)h{*S|o(THSG>qJ@|}!L=@Rlzy!XXnA09X3BX!X1NPna$ovUFVOa~ z6MxSq$cKFWVb3v1R*bbUp~*N9QEI$fNhu(@+;m;xup$j&UwL+WgPK|sZy9bEMqZp6 ze!~SOsLS*9t$rSv?hW3rUEZa{s`$zf_+B}&7*M=A+NY==5^G`_$JZifSB&$#O} zuB!nTd-Z}DzV3=AAOWaRc=D5_6DR7)UMh7>RJFDHCZ}9_giKr!J(y5SiQnl8He4h{ znOGn&7nzUr;WVRPl4(H?@A?jMa4xGbkK!W5|GOvh$sx1=Y~pIIa!=2Dr^x``Z@h8?n{mHM)u zj#-44%%AzSeyb1)=vY7ZLPKH#B|p+dO>*e_aUSQotqB$2;QucRpc^yFmx^jl)5i+6 z79_dBbMFmEqEAv*9mS-53Tqzo zdZ@tX>1Rh=2-0JVUF`?wk)zqD-n?{MGA+oL`c7vJG|SCFNcwWV?x6| zf!fKRywPu4=Qaq;avTeH#eEExqV3WaP8^3mfgtPVWIyaffNT^5#n9JN4b}S}tV%pA z`9KC9?BY?suqy|DXxLYl)c5qI0?)A?MzbNK==-2&pmXWcZdfHVc)RdWn`5MiZ3Az# z)qz)1&K8Nen=Lw76Wco}m^bhM(H}!{wA*nBqVvez30yV)u9f~?TF$JyCForUVp<6H zbGIz9AF7|NX3ykHWF4nYAAtb8oNvJGqR5;QWfX9u;0e=UB9}S}XkSl;MpE0b% zgJr%}4$6f?*~u0l!PzdB<#>YQEv#d=>*Q;O%o*?P7|W9*Y>4)K!As$ZZ6I-#9thag!7YJmzpB-AT|Q$ErgqKo5# zRR(b(fn{&^hl$J3S^Cm{imuIdajMMw=UOd?sKx(EjWr5%nw>t0fz4zY_o~@<3~3oou{&Wttg9J7 z6j|*n$*|RoyyFK6U12aw@n!qOkSC9}$g|nH(j<8Es_nxTeG1|Khp=;uuIzal^~9NI zV%v5m*2K1L+nyvdv2EL!Sd-+$wr$%v$vwaStNUKoI_rGdYwhmcsP3+Qs>&`Yo59Ks zz+;WZNbOx^VY@%OApRHX<_iz};Ak=bZWND--z`5fG8Fan>n%cE1{x`Q?}7m3@*;AkDR>M^>&859kADYCB}Ujj^Wa269nY zrz46K<2V*{!tIKvYBI-fOfk4sW5s|DvjeNGSj(eMe<-3Qfqha@Du(?>aC8ctt zM4{4~w}UYrSYXQF!S7xLV6FBAbq#A}G1Wm;yLe?}M|JtMFdJ&u*DAYe2_xQm0k~b1 z2x`cM>R=kv>N5=-?!ho5*2o3|OIAa25KyTc;}JRim1^9_Ou-tzLdYk$s=^e@lA{)I zv@ty*2jg!q=>W<<7USX3Gw8Q@a3990=Xddrc_(}brAMD^USu1Sv?>#VcJfa|+46s#YL{}pv$Bp5!fZ```DDq^0JREbOYU0ZI& z;|x_fo|*QGno`D=_)%i-=vRK1MN7s8Na@x_8y-9!$WAgAte*${C>KQ|DRg`ojL}Q3 z$syZ2XWxtnGntddVuhpkltUo3Hdr44{q$iUGdeBMNP%O>5X@O{6sH(KZMbAaWyrba3-J0YH&qC%JmPN)g$k_ zv&Pz?B-Tpy3kS~|A4h0$sMrb1X#o}t_va`I#&hN{)nQZK{QcDb5 z8vSY&Of@th4!owEIGh~BwFdB!MqUzzo-}3|vJCYwzO0JM=3!^CT)Vi)j>hr z&e*1_@%(F{@Yg(B`5u;6;r^Zs|&=A1)zSl? zLe_WbGzXNy=W%zF6*DuJDzECtO4DworlJhb)*&|oo=E;^8JGYN)kGm#{3&PsH=Inz ziqCuEI5^X_WYDxM1)`cO4&J+x(w(=FCj49N4Tm;sziMHQfs(wMn&Q>BzM=7I^n1FX z)Lvb6(iEbZ_;o5hw-Q71`3|zQ<)^ogo`O|FUHlCaSQ<_+vsN#ezmpOsn{UMBGLfW~?i3RT3f0_XlJ94rIbGuuS~B3GSrBew zmsNJ~_x^mNsEhNb*FF*|mxu6~(VSf?O3(Ln&z}*pyD2&6DOm8UZfo&1VPsC1_@o2h zt(i1bo~!Xt>49m|vr+YJ564d@E@j@+^zHO@u1L0B`02pr>$JZrlfU?DjHg&-3!{Y4<42kI}gf> zJ+0C081;ZjgJJq`#4$56t$=lr)fs_i@RsBTMl&Kgx*Vg$hVZcJhj}%e5oeD;|8ckP zgqtE2wn!s0PMsJl-p?=b{Pfdpb*2-xs%Uz7bHlEBy~6%)ryk@?i+M3JhAGS97cJs& zPlTotPD=!74V?Bvb3CEH^XD`%j0#K0bMM`tbJoz8>_R)u8(PkVo2-#;@IHi;Z8k3S z(|h+HB2T*e{-SiKPUy`$+3oWQg#B`8C-}QLx!_XNy*!*yJQo%oL&l0kpDKrapI&6) zz6SPm&8UwuwKLEPb)Nn;WlY>za8t_rp00>X8LZ2Q!Dy(xR*50Pthxt}J&hTEMQ+un z%R@+0CSp31EbRc^jCTsLuSTc%d^u%kSu9b~o2GTFhdo_px!#+qW33d>ijteKezI-% z({a(>TFX<9Ely+&Ou|okC!W;WnB6m-ZaVosBhO^n3eC8uREygnkivt?>J^k5MLt)` zdlPbTQkI;;!>`nZa>BI8zR3NCFYS@EA2Zcq%H*P z;Xzf86^$n5<&1eEJ$zIAh1!b5s?R-@D?y z22*$Do3S7rq|chF?L>xE`;I9j3eI7_D`F0m`l6}?vf>umtmr1%-xE)rkUKY;7bPE4vL%lsP-5A zsyWNLbffJpD6a^Q3zdvg6|71em(=}rFl3yAA^@qRj?IfLtJhA>ydHULw3Q&l>KVSyb8q5>O!)$0$ePx-T2R5=^)%3_MZ;Zj_=vdpvm2 zz`^@*pGuegn31duq8S4H^V5K=pIzAQ@2}bU+==4*AkQN4(F(44M7?jEJ*n4e^;u+0 z{6FLl*WR7ivIRY^?DtqqxO02<2fMKrTXIvWh>4lk<54;e%@(24Jvq&IJFa$LrDEem zA8lbvtv=T_kOnc4u{WPzVlKMH6@-L@wh4s?y_fzjpl~Q`r94+vHgQ6}6p<=MjKD)Aw(i{8rb#J+fjU{Gh{7T98i4&ay(<^yOrFw6<)ar#Neucr+j_m7>5P{0 z$j3phZMWq|vh-*4%EJ&A?qd?Z^1|(5d;Jx!%SnfE3SvhXWL$4>aEJlzXvQaS{p6>` z6`Fq35w3y-)>GFv%^tRZ>1IYoUkBdGYA5mv6D=Ih1~<-@#U|u{_3@a(U`NLFILG*h zsaiwe#^j)0(THpOx-NBRB+M6hSXcxMOxG0%K8QZyDlQWHGGdc4BUdjB?9g7!7jST( zm}ViUBmPqyiAbtuK<)LP()tbMpPK!bJmLHh`KLGjL$(D(ERVm!{<|Q!6j_>=!6I*5 z_`<@j^THzXgZ;Y%?nHM4Ew{lx8_vzix_7Omqae3(wjSYmn-pTj`?*4NSi};xXSRmc zKkOyjMx;EjfjMB7RPRehz}@7TSJ9#NFfSHWlfNBfMhGbE?GG_ET7^8tZQkVw6AqTx z(XF5}bgglpjQqT?NZaFy`Asv%?aUQjFxBGt`d8Y$RQ3nU{8Lw|-LCsH-@s+Rm1*r) zlXE*J_aFJ`6N`2Zj<=xK#@KHUH;a)gpvw=nEuGZ*hcATVuRMUm1EIM^f=?<%_dMO! zpydOy!o*=KE)HV=?4MP-9B~=W$icptnM(p3!(={;mdfhRuh%x6w9lIX*5s$$?@u*Y zn#V3JF2+PpolVjkW|9MBH@9xW2%4e$jEs_l!#HPiTf2_JJ7h!sJii7`2nThn?$UhQ z!lD?oN2?e;UumwH(?iQ-FNtdkXMT;=qvKI`t`2b+bHfF2r}(huVV42_kcbsOT2z%M zog2AOZdqd5OCE~lS_`aoeCzsJbQ=l_ke&FVoc#P;_!#W02Q}Eu*j{S4yBMZt<|!@e zIa(|kDAUraUXauORvA=(n7zLNAzo!n16K@VrZ%xrgCFzg5-{fgMD5tw;l&-uTYEHo zq5Zd{3w;u$O2s!g?3l8Aoq!-6^a+W;Dd+ryML1mA zn6zbEI@f*gTp&ZpfD3*`u1lm8>Y zxoxWE6yC{k2UmGV%lt@s*iT?{Vubll`^~C9xf`$H3l|CwL6k*spvI!rOjEL$J5wr> z#9P}`TkXS`Iq}2NnWACIdJOa=Frx64!`Ai(d&aWaon(5skZo5J8m2JZtp?9bD}dy}giU>E zrfiVixJ@htSGuW+yTDjs-8Kb(Ww=DTBli_klPjqmvmcxJ@z@mYIN7LFiq%+yo^m8b zs+R%RyFc2eJ0E5On{J||=UhO7)(H%^{v8dz;%`@|=6(>HqDRw*y~V+%@IF8@J?n4Y zSHLg!#QG2N5Pil&R;;dQu`#|AbC( z@hV&Uk&-I1h3<YNhs6RQf8iSUd)In6D)9BFUkb^b21|&MhE#Wy>sRXvy$CBqZvF3qm6L>sDIgrp1Iu^=*K zRE=>GmR%CQ0ma0Z?@rl1hUe85Fln8;hyrORGauaM{g}qupEcYK>8%V{K3?LSlpxnw zZh0|78ypL}F~hEIkUc9uBF0SW2Xh4rV_3EM=f&PmOpsG(ez}_80rO4xVICh+HrhH4Tm@1{ZyX(eM5K*Z zt(AQvJP$N*2ns8{L{WOJ(Iy=0P9mMAo^hdS0OGMvqf?g$IR{?O8N0>2WEB%THG{Qj zM5M_$2B2Bp&78{`j#M}Er+IFEt(cbBTw8yZ)OyT?A9Fa|q>v}J`H(nuLpL>4Upi~{ zT$2BWIPQ#l{vF?NT%N*CF>U%?McsCLIuQTQMrk;Ak%2t*{G4PCZ#c4Gth%5l%7zgG zZ$sr8uLb^GElGrxuQB)i4mm>k+6;^wnG_q?0E1s%moACT5g~#a!<^F4WcNVvr8K)V zN>iJ~bkm_6>McTe4P|$|fM}R_xTb?8Q)J(GaA%I*25a&Z(_>1Tr|}{AASe3GXuSXN zsv3kA#dmcmC^S;qi^ol#pO)ZwNQ@LEbFLHJduT8hvnb~aIHAUNj-pthtR?kJwfyzF zh#%~85M_Ib`ejU7F_Q=`hlD znMfG%`6m&)^=!)msY@o`aTKk35dUU!cwYZIF4J|DR}HOw>)nbTLAs(OdX*x z(NOH|IqUu)Iy}VU#(%G<=O=PsYJ|{?!Z>!Bic{N@Qmuo3xhlQ`g+jHA%@wcg8BQkR z(R&vn{yHTP)iMRiE`aF@6O$0H7tKzcg`<=+kIyaPMI})vt=aoF0;bvXOh@EbAfX`; zlsgDu{**#FY8-33H;Fx84m5crdw@5-4Wo@Anj({V!U!;-SCG#grT_i4`jXYI*k?{x z%t#+)NS*@)yZCQLN36#8qd!Ug1~N3|SC7tXc7icGVL(~^S7-@NKt0zW7R@#XMa2SR z=}p%9Fqj_$C&8pJnHrY#^g&k1d!U5UoBnR0hTwh|S?LVnXHXRr1G{TYi%&15=$_`w zWe=L*EqkSkfZ;?9egiE9A0a~Nrg!L;JyTw1BEeQ!`R+QF82;E~sc3=dh0V_V2e@=Q z3`qg==F}^J!+7iue(1PoRvZ1bj@qJ=VXQ0%xh11Fr(ZCHl(c!_cPlTJ3g}MV>c0X2 zXybm$eV}v)H+rS4cZz~jp$@-@tKWkNh(41|sJaXG+u^0%AY&IX9jh7w+)u(Nxeu4l z7m(;U3PPpAe6dTJ6r2i5=0x6PcLWo_%U64HH;U~}cnS;(r8e*3J_#Ys0zTNT%yae% zA`^-XsGW#rB()x;TuWjqDbOtLcGg&)mvD!Nhe_VX1+lqlf{I#&K+dXJ4n&$nwAI0x zTL$@6!$Rur0#p^ImO&e3v)RNQLy|)Z*K?vM82bvcb&&mmz<2*hOuGq9^C=)_p9D6S zXHBh}R!c8`RCPc`sJAFosQc${h?Rk?@7nP&p(tdZ&6$+kB?e$@{$ru#JDv-;&!z!L zLzDUiJ77>OGn=Z}TuUDUyhR2g7;}8cl6{S_H^)gsFDFkHo=4dbMOSn~X42>`r4RRk zG1G?aeZ`9wakROH`o{`fpBDTt87$j^0#cZgedD3^{x=!|!1j&+Y`H!M6WA)Ak=}st?F$a6&U#yDc#DcO z_FXuOZdR8wa}_pu0g`bfx8g(5Dc`k;*rjq>Mv^B{fuZ~8X9-$IM!|_dwymdmuF&&Y zF#MT+wB(ShQ<*XD8xU8Q4VQ-6zEAKLCCeH&O#6dgAerh#atWXitVjKMCndkYquKqP z&CG%+&aD$6h=^)BYv}Cr(&v+{1Fy~97#Z3?5TslP{YcJ{FN3`1Er;* z)_X$x1&5@?lMR4Y;K?!@?ZCQa?xmwpy(yIcV)o&)!bY!jIh~1V7^2^(hD# zjr}20t6<(fSU-Cf9Rhk~+RSEUvYxTYdFWTmT}l@9T8As{EWUv6ETHm$-n^mOblf@? zf76;X)TSizX9?^Hf;bbK{Mn#2t~0n}n^>+_+WjnD)P#V%K6%Ggop%;^Yz~Dd9AVw z=ov!vHjo+hs(M9r_umCs59;{TwrKT>(Iu104DQ4aU{>L)ms%^Oa%%G^UD)88n;zP6 zhAV!J%PGX8r;8Z53wkf&{~BN4R1QE zet-AE2Y6K==P9Z{wzw4az0JjZv-+nGsb#8+ydDla(ea^3|u z?{Nr?%nGmR!ae*0AEyJFgv{MKfy{pb<)Um3L#b7E#57uPH)!^;0Z|c#ZPS{(dTlto z>y=^#fLe>L)EvM&=Amab6}P_pRb0t$Q8KDGn|f5aK@u z+7j6DSPJ=Qu9*a*h2D?xM%+ z%_(M3IBnvG3}=TBp>XMV%C_@*b~HLt!)$<#!^8}m9~@|LQa7z`a9v~xdlV3rToH1S zxHDHgJ3<->}ib7?ZWb?q?A*!#gs0*J?m~Ll;b4f;`G4N9_ymcd(!E! zcCfm1<|O^j30n>nxAu#7^QD1B93Kp1_VAV;L?l8*SIato)rDU(BIJA6^12*@MTjPU z5M0>ZdeQs`3oub)x4^Ib{oFhBV5K_SP~&bIa|ji6ojN6gzl*VGDjUGQpGs>BV5O*=ocl7(K#~TF zvL|Pew8$W9N-wT>U+0FktF-GOXO65cz6PyC`8L=Qb*!Da8b0tX`zBf(&x%+zt$tBT zC8OkhZX69``>V6n?X6)s{0l z5kp932+S!SUA9ieV$tntgkQKSk)wW>*puZSWE2)<)%V@>X&CBIyMNM*Yd|)IkVzDRuM4@+lozMBv)-4Rs&+v&BeYLd@e*sp+%b z&IQX74dGwSJBbKA`_#O@Va?MY6Rq9A_{2tpWKtsJQ9svEWlq0nj?BB^@BMDZminc< zQikckW+!uWl8qpv+|Ke3(}qBuLG(nlCNhbe!wNd&`gKAqq!w4eD_`eQ?tELs&&{B2 z>jpOh{=5UI7oh$$zd9pS1&e#_Iy9S`dK#Db;%4IR0a<^#w>9Hdxt;!5Im?<5&43EH zZgE%YsMq+9kEgreUGImye5*BXzgSrL0CvKf8rC(75XznVenoH9f#;8U<@8yTmz|kM zLZ>g6dDqE1Q80JS4o3P+pPS?-WXzq2NNcfgTsfJQB<{Ohou-Ujk;3$ZUl9!V5`1R- zL%>AL(A-iPej@z-Hocj7^((alk6pLOz13ljA|XE=N6fcK5UvegxgIS{g0$FT-iEI; zbe;uXG972=aF~leH5&bR>RPHKXAWo!yOBWnA7cgrcVwc5*ep3AjhM<6YJylJ|FOmB zxiCNXEUDOYL_DY|2bVWRIsD+;4wPgnFtEU^OV_cD%(C@P`v^98+PH#G{*(txoe|Mw zp#)YLS2ih|BX44SN73rY!dpY9@ znpmO4B~E}^x6(&jf!FVA?cOMM4joEcZdtI3f?~Vl;bp$2p3+%gP?TFuvh5!^?|JON zXQ5nB&eV_YR}~voAIz4cJuU~%pw0;H>8C^hP=tO>la+G8ex;348>(kk6_vBs4~0dPF(tS6j7Bg1z22q0h@t9I z4$5q8Hf2+xU(=Ge){L<#heXOG)%86JXXb+@7n!r77S~!9Re}M ze^SU2U~ISM)JdoA!nPgs{9PnP-(>x#_vxi3OmVQg6%}v^$H&-?*UgFA1Q-9##!j<# z>kYh8TJjJ$P{?9#wNl>_bXz$=obz||8=B&JKHu`jG+Jyt$$)rUdG&$5Li7prbGwk5 zTW+W^5=Ux{_7_fclb@3o#lza-)YeQMQHt|=HKku2_)HnP_(Wpy;M!nu>F57+*)C1Y zr;z{%PNgf~y72VBF}B=4((JPWTnR#+oIN09vELRd{T=2T$*_Ak=6-Qbs+wQ}wr5e^ za4N$|mED8a7kF3Zt@wY>Z|2o7g=7QQ@eq>b9655AmR=IuNFoFYq6$W=K@**E|B}pY z8tJr4=2`4ocUsaq#+K?qC{!+Nq6I}G^Y@Rg9MF#dCdYj0Q428j&3tI|U6>&@Cu1Kw z#uDaBGwL4;2V@-FLDTs3zpxJU7EkdD4!O&c)i2PHQa9)>Yk`b53m)^RQL46u=ihCZ zuR0eu7(iD|%!ZwY#3n~v>h=M@pI_z_iB{&?#|lhd)$XdHu%lCB(e9TA?kBhF^ft|^ z)Wo9}VZrwf^Yg;yo14UH;09yCWOC{Qc+5I}Xkh@JsTB>6XC7&!IWH@o@RL-RSQL|?I-3~`@9I$)jo;!3F6nYl7-vVRig)vVoL9oH`4J^YDyu4I# ziG`@`^2gUf{liun-+fP{ANpAo_Swx@(DhT~^WBCt-9o}|V|KQBclYSGOAelVS~~nqQi02{n)3~mdF5;3T7=Fm`VzB%OV&a6sf0E& z{`|Wyi&%dQV=1{q$W~{5u)W$sG_g{!#3xQauTW3pKu>$x4Jzu&p>39lbS$R#DXcbj zR!GkT!0TsF8@E@FpmelPzo_9@S9hHK164{j?vE z5%qfx7hYrxMAEs7K>TuC~Ny z0qu9xHpLUy)d19D^O#s0ZRr^9YsG~K(UV*Sks_FLT-!?_IfE&8)_NPzLkbaDaS>oT zOB_qPEDaxait`HIg8D`gSReVcstuW~!@gnO0)Z4N>um{lTUBqJCO*sJCLD`-%;sXh zZ;HNgbwrUG?xNA_#}AL8L?5@~4{ZPV3+VtZB9eZ(CaX3>QFTdHxA^_Bp}jA>-v3+S zZTt=yk(?x8?>V-0a4Ra>bJ%RS{Al(eh2Ov-qkCW%tM5DwnJ|?-5Re#G8X!NqF5yV~ z`s?$(RfX`>rvCLeGZ`sz?rP5+CtK9Fn4M@06l!v^I)rP_-=GB0IS3%6Dy%*>I z?8}@rHJ`X;gIS&AcQ!sZ*PmXK!gd=O)GhAN`Idl!aveMwfXu0ak@Dzlu*M9y=O)hg{Wp#ZVegeW z+T`XYD6&)<;|p);YOL&WE^wU?=AtwiB_}q4c>^m_0ME{>XR_)z*#@!DlZQ6Vu^67y ziNtWXkQ~4tbr9*m)9llYWeZMZKJ|_2IuM0RE1<88#TgtZzPI;Ewj{gc^ZY&B7e5h5 z2#{dx7v#cjV$!8)`_b5eKolNLr%}CeDi2Tq6;I1j!0(&MMt9Lb^w##`#|EYl%0^*G zpYZDK_(0Cbn8TSv5SlplX|z8<>#U$>Wpx}jctfU>EP(fJl#TTb z!m;KiG}ah|;h%Jox~bAD*w=OkqY!kRh}L`M_(u^7Obe3>e3TL4$^D$td=DlxtLR}{ z>SpN=X7ybUC~Ec_dr`j#g9Dre<~sJ%_6hppe%3#;Wc7@jKGa0&mD;!a6n=fA{5ymu zC`b{X@BI9sQ^Nu$NTgw}>bGT&<|fVt7ag*q;uo)(8Rz|$SVte|xfS4OxFH;~^jOR- zFDvhzg9TpWM10Yhb0o<7E9qx=H{`I{^YbekhjQRO(U!8g`=A7)nQ8yi{K{XY4p#(; zf1NqO^zhsNb>@`Z-zdFOC_n^O8P8N1`9TM&hQW8JhqJcZ@-uZS@| zpxb%gbRE=NALiDh*;>JuT>>-xCi!N4%yGBkV}X6MKP4HK9VP8f&>s&hvVX(VXkXvw z3DJe%VEk5)f!bG9rr4LPY_FbUGF0;!`##xm)fQ53bmfqCc7_mTY&?!O9+9B*BG_f- zi!OB*FjQd>!bW!J^iK4J&@*f}&Cwk23$0JXS9#h!Bs}@H)41E|=0HjgveAT+ZRJdY z)-5-#y}m9JR)=PaZiw_7IW1!b)}a`(z#)&8j)HM?+Hl!zAjf?Xm4LYfu#kLWf!U`5 zJar7(z54;>%7X~?bBDEEMO@sI1~wMfLVUikjBlrdZKdey6K@MReTUTIaNIkw>MZZO z5|&CEmS*)i8bz}gx0rG}Gss_LaGX)b#U4N2QhIX?@fV_7R4yP$3(O7wQq7Z~?C9g# zgu!AmEnX0FoNaEwGN>#5bIi?JT6%=DspKLq4>(-xax~1@hRh`;rYg&&)Vmqg?vHX& zQ;7fZ_Tc}>yy_sxS(}pR;JQD z{_Z}&#B%9&dOL`%f^bMuBQ@&ywfdvd z9Ot_yf8q&7+uqo)QR?n3&qQwEVj;2LpEnWtyv)eGRIHkF70;xGySM zAmcq2)NrzW%H>vEjm)i+=n0`M!RZUhp|#=;&}L088#XL? zmH8PTm5VB?YD&%G|6oc0Ea?LCXl%|>F<8CU2#sR~8h9zwlpF>$z55sDFm<@)g$M6F zJ6_P6i-w?L&{~jhUw(2a#pjEPc{|fI&h4x9c(E%fRw1!X#F?#RQ zB+~Z}0MVL$T-{i&<-$^OMhWKj>13t;r&oY$c{L%two`c>i zV@hlU8(@mwBV&!khoTOAKN9fX^fkAfzQ_OkNBqKc6{-6rwJ<{4NkX9_{{Xp` z6!Q>;6CoiX&&AHs1`q#ul~o{JXFlGkU5P+uqtrnNZq@r${~O!X%Astm(LH#Hf!1C_ zR>xu78K59nHgL`n|SafN2V~16By`pB;Sq+!lGJh>l9r! zeuvMvc#dU=s5_0h&l#s9s7Z1){t%nTAHnk0f&$gy5>kV1`f{~DMz`N@b{Im~0uov} zwmdT-PIFN_*gX?-gP9*+>z|@xh;il4cezj(_7tOVR@!CE_}$dR@3pwkxxDLhEhNAG zA+b#O`SY(JN6;kfJsRj6`0@T5js@P2WfYzBuO|7ozrTKA)6@Tr;F|guTlW7WxR!r| zC=XHB78jELgu#dnzd`UwD1hJ~m`GF8>XpgMir&##p|}F6Fq4t-uhfH4|GHtnmD=L^ zYuDzNWBk-n?}MNhA7j!T%nE23oD>-z0`J)Bf zv5m=Sll3d@BM{^zV-g;#xJ`jFWBOgm{gKONcG3uc^zCDA`4<|T96ilfTGejCf4@Gq zTN8QxeaM@%(`)8wGmAU`@QA0v?2?sMggP^rSN3dSW0O5@%%{4!k+^_4Xpaye$ZLGF z1ozvZM*b#uh~E#oy-i#}J_;gH8GAK`Zyi&7`L4_+6pYz1dYu$@og@?A2c+_E83-q- zHeQ;s{BfWefr!4@I9ZzBr+4!1Qv&Pwqsx=#Zr_7fLFAVYwnOoR$?X9tYqKRyWBc|= z>EC`+LPau%=NI%q%q&G&#e#&iVTRTp{Tq`p1j{Biz&=6)ij>0ZR1+tHal9ui8rmj7 z6S-njjqjU}r*ArE;*E|XtW2+}cPpEI$8yBUf}$Xe2AyzT*Z6hF5kLvT&^mi)v28Y` zHu((!v?&FO-iqoAUGW|c&q;4Oi6M-Xgt+H7YVwkPoj6RKh<38xxic0b3K*%wI&8Id zJhkA37xL!iJ=9?f!#n2!`YS10mt22>;~JXonc@ADL;viIPCvc^6G@RG%=&4e+EpQb zKV63z=`D!KYk+a>tQZEr{mJK4CkWA29-`8DjMHCzEoKb(dx9jGOFA7CwTuxd)nKN~ zEQ{+cVrJ7npwYBfLF#1(PMGdcxaR&g^ZcfL_Wob=)kL*H4xVE}|0E?oz(3QGl$8g2 z3L2ueYOcV>=c>V{<8kwv=Bb4eQBRhSoa?v}^4vm5h4YF=lu>fP(5{RK6`~x(D%r!% zVj#CJ#YyY_6sLbOt<42ZFh%Dc>+JuDb0X~f8r~5lR4j-)A%g8eupd``r1rS-3$|Vq z67fOvvO|21*)+_=IB-X#B_ty>X*5U2Echy8k6aFuvvqtG{MR%&IZkLz67=5^P zz~ES3b3quv**E91)E#d%S9%%LAf;$0VOtKBlvIh==0tRTqUB&$guRH>&&!Eci2tH% z$k@|Cyf=4IPiky_ri(Ipr|hAz7|1tD^Xcva|1^GS1_aYADBB~7bqZK~J3wjFdhx}k z-HPW@>1#h(z{f~R>9T|Z!a}dnML<+9V534q zj6LHwp8la22&O;VBvIS4+6a^szkgpLw|Z9^7S)_sK*#5nUk#jPoD-m|^$h-I?)@hq zW~J_T+G3AQj4h@8*nmG5HBGoxrPK}0ZnA-y>pdtt#sk0tz`#GV%1cA$ZABkWvWG1= zh**wIpISL%VV>ary!!>5Fklg1lCs2^Q=yt~=?4E&q5jPfe-?P=X}^@r*mIqhN9k1$ z-J~3nByJsnXnH=nuXylx@w+5tnUq!)i83gLGNN@)wNS?yF)tiF|ELB6@yWAerN@Xs zNWQ{N_`!5&B6HPdurPs)@-J|v`sh^$nUQ7ZxQ*iMlH}G3ug^KiA73J#ZW@zNRU;4M z@T*NbWg#ij0bQOADhjP=U>TaqIp4$&&O#cSKp?q~kA%*-L~^!#26qsJ6B;Z&S)X@X z#(L~iy}+AvEKmKCe~#u2bU?-l*!+#uZDywpJek=5o9L?-F~$}#9S6v|P-BCA6~I$_ zu<|8r@A$}xApmrH$ywTu6+tyl$)*=cls^$I5#1g_L@>e-d`O7W8NK#4xQxg z&lle1|mBh2#6!S~Eai;PhW3(I>$ihH9rr+$l+V1Akhyw3$; zJ3~8%^S&AbA?uh zW70e=1VR|ySlFFv3cD*1Er>8`8NEZ&6uEQQZzopp7i)Q?j9T8lrGMgxM|m11y=BD2 zMyu*k3#Ynd+`I37RVzR`2-r*a%|4d(-3@wmB^rZ<7pw;FXg5$}I3=i*U zIs8MAXyw%D!=STxC#DiDCa4R4fmtqfGW?kufS=5iTW== zLW)qYhY1xfn-Y}IJ0WrWmHyj_VrqYuNNg;KTy)LWuh)P3MWNW81bB%q!bvBWBCcaS zgW43NTOIf5y3brcGY_pNbAh~*qeD0SzwVFj!cvnGZk)Io^S`;=MS{}(E-2%Y`36Zv z;Qzi6Wu&tHV#@aviqVO=E_$h>^RiKX#e1MV=n~)=%}Mq*4u~Zn;7r*6&Dq$WB^pOx zTwrdgxkne%1nPC2&2+&N732KJhtEl8+Y|fhUg^v!lk)-0&}b#p|CMR!k*T}H!u>Vx ziF6Uq#N|{1Hp zaUNfe#d5`dMJI$M-&q+-L&yCoVTIJQ<(ZcKsT1ii-^1eYs%agQRoFQJvs`0D{}CY_ zj@tCjqcJ!|EM|8w-;GbpM}_((u1ap{yb_R!h#R+|OlN2rwh-;e9( zv$!O@Iwo3{r^t&VkZ-))yBl-m-elVHeS=u+@{Ith~j+)ueHTzew(Z5#Z@TbMsAqcX@LUe;PSuySZPG_pf8)S4R@>gE8Bvy4#z~tAy7}md8_BYD${c$0NP> z*QcR&*Y7I?pJ9ETf@dC`EP`+k*h0HwRbF{UP$n}1f4U4-1eUyyRY9NQar{LaQ#P zhs704zscH#luLogZgpU=O zR&Nex1c`&A<^<&pekho=`o`Sb6=OT)pVJyH)PG!yF|yzm;>K z4R_H~+)-dO1|d1O-@OK&X;61gN3FuKpf~~kshD$ub3ELFGAK}EC8H^zMt8D85w8ue zC86SM^^9C;=+@YhOsiZ+iow!$N+R%u<8eG!{C%kS-2URij#*8`61=_&#d1*DExu0~ zS~j~Ttj|oE(&ilnE2)`x@rxVtUbXma`+X8eLYJLJsu|?!x;21^l8sJzV7Z^_>Td{S zp_Ddmphj^D6b%)P!lEnxd$Ep~JEQDo@B}X=`-FKSAZ>eL){Z{q$=vykQ zO?*aF5L)#U+y5C(G9jPv56M)pDwI#{y|u$&@M1n_w9iC+(8ib&lbIp3M?-@TfyV^I ze-8^I)>7_!#d6Q@I_-0bN1mIeaYT_b9Py>tO^{8gwZ%KI8Mz85wb5h^z}MOk2g_nQ zx*i>E=4q(&Da3sEucZ7$38?PKQ4H;Kb)D(YAv6Ud(GxV zz+1Hv{FKsDo!};AIMC8o>s5FQaq)Z6CS)|^en z16-k_tSYr0e9>t)j1Xc32_n+#0k7W^k~1bVf-tv|s+sb|8xqvmOv1N%lA{*ik}tLf z9GtWNGDRRV$rafL@K|{NK&uS zMINhav-X*F|2r0iy&6^3HfIDpt&=9U>Q$R5hSp(PD7Eg^PYBZzTay5Ow^j!fS!;7F zh$c!H>qbm*nq&k$(w%s)RKsa!3xFYrq6>=~*6zopRr;!qVAG*3jf-O;9MBLJ6riEs74T4 z;%2%RGJ~M}rD8iYXB`o)wag@y3}O)-7(USfzlLj&)7boJ0DWE6tLMN@g7%a48ElS) z0?n&~08!M2Lc)V+S4hbMBOK1|kadxQcKY*?zu|U6!{}Zjkq$l26bWGn>^q4qqkQCY*Kpj+chp6$a`Ntq2OPc!qSXx$ZBx zJKc(4-^!Hz560dCD3YaV*hP17SaflBcO3?IcV}^T_r(`j92R$XTU-}+cXxMp{yFb? z&-uQ4)QZA4ZPLiJuKdkU;qb#R_mVypVYuIEs5WDD zea@tE{_KUd(P=vnh(WJU^sG;<@mP>q#CKQg@Cj#18*TjTs74hNK_gu5lO~i1rXa>C zC<$td7{9QgVEmxLq{bO*y7w%+a%Jx;P-j+IT!Gv#9d6(V*mC_~cml?F2!-RwL8)1m z>V$^QZg3b;q)#yeD$>sWXlnzAITbvPeAf&-h4#H%i{y?qUy2Izm-kppJJ$mG=;hse z139h^gSbeTawpsn%W2@pmBomzQV$uXrxwn1kW*-eoSuGaR}X&QZ4+v19L^e$@1*ZX z1qemPG3}o%{b`f)wS`4G%nAyMGTzsrw=fb%%|Q~N_9uge@L?BRk#gwBIg41)Fxb=( zCDeU3K)3u|A~`DclbnYSEO8fEiHL^aI(aYE|FwZF^~uWDjF#>>Pbzbuu-AUH$n9oi zf>+xT81&;(KtX=bjk3t~S?x{`jt@}{u+V+<>d3M%5X&;26+nU;G>{ioZ}?b|(=*ev znS4c;;pAs)1SW+p@u!QOk#a^5j!+IN+jCELymNX8wjN+TilmB0v4(uFJGW{JrXmsq z8GV#X`=(boNS}-=Sb!v$Tla)Cx66BHug}19qI4yxNQ_X39XRDfNFV?9N9bp&0UXaL zhU=V=EE*GA5Yx+Ts@`5!i<8-k*Rrj?=)w`4#~P`6`ra)&eI4pHwyVwr;_H;Tkz$I} zqh{5YdbECo#4RR)-Zz}w#j=K zFb(am^O-n=tSSehU-7UBzgNUsks>>|5nR(Klwt)?SFiHp{B3ZZ1y6jqGY- zL#mAQyOiGhM9>jjhUnxU)qWgnOfhciqQ)DNctugAyCrvu3cDb-G+!!dp%KUYh&8z18JwsaA|4v(wJW=t-6MQPcx9Z(9U? zaE3R(EFyjg5&XlQQ_6K0-&DXJ_(>2gp~C9AAI)mUEzKJ8Ey>5AtWPta9{ZE1*nWYW z09xsRh7sHH5b5BCj$dM5yrz}`e&@diZuuoVTJNNzrk@KKj>jKMM)>fBiRdUf=fTv=zy zt~g(htGEmV>j1QplOeKZRs-@=jEv7>OnlkUQgzm0#z=C#FSd)-x=HIuyLEQ|A_6Hy zcImQBU!kuly`WoVO7D9UZv+!k1#_-POU|zp&)P^c zNUIr@i5Am*$JShWzBecjf7kf^=Y=5HbIK}JW;Xeo64h*y+QU|dH^ocH#MYJwl|42b zHKJ->_pr&%PHS+$!*#DLk~LRvJ~C!p^8vluuv!AhN{E2AUM%$LJ)nU`smci8C{E4G zN_uz!rJnZ)0%^DNP6IX!u_x8$Drr$e^rzCYGwa=Xqi(CciJhVmZqLYC#KSTVD+PV$ zOcrhwo96^1d4rySXUcUIsrT<=XObddJwk*#Tg*st-TZ2+(}&AoaPY`SEA9m)>GUT^ z4lNE`Hyrc^rU^I5Ht1LhM!yVG*cW^V1i=ghb#;_&Js$alqL(HQaEp}(V&k|7Yye}2%&K2XR15C8wU)`0 zR{MWS3xeN1(wftY>l=z+j-=lW!CCBS;p4zN4 z8*c*?U|{}c9yA3?lRHftnG#?MHH)5cp@2;-JSWnW#fyF{CAAEiqbK?;b5SgP4t5@G zJ*OGZ?kptI!;PjeK=@K$uzOcnB(N1N1yN3~k&YxSJQw70hx5!|Re!WoJA87NyBa{Z za=>!mDK((8X+f91d;cB|_A!^K_qYiW5VhQQxPE!_&-!cvhf+Sa*?xCK=jnp2ZC3n3hvB0wcU%3&`h6H~ zq=Xnx*3me$#g+{b9ZTh2KYQW8B=J8lnxq1;B@0M(rFe}d-%q>hhOkO#gr8e%{LYt{ z@OCs^_b4vcS3%34vAq4_nbo?@%h=w~6{j9himhzJ+a`^U4H!0T>dGcy&0Lm&VyuYx(m{8S zXr!@WUgUH5@jV7ayG$jMf=Zc*=e6~`N`{a={1;d)Obc<6JR&W$foh1NCksK#?K~3L zc(85{+fj+`R9l`92L7Nc2+b2AcOY-Zoi+HSp7rnp^dxa$?fJXFR(Eql;GznJ6B44z}@>c(o|#O}7{ZD9!+ zgS-%V()EbY!*FNtcDEGW&bCIATHs!A4x0*4Y3S8a$^CBwcOKGU`%u)A=T9IvnlpPz<>3ddc!sU?x*`|DNaE>6)&@b|KXK znU0wExd(#myGV3~fK+a3E~56b+OM0RDS0m)#{2hV^CpZ$&oeg(Iby6kqDldgcxyU~ zRr1XQjV$COKG>gy<#T9Rgh!!Rl=8Ngsrj9;39!4Ij6zWGOTi$1MBxsJEXkOdMWC=@ zFTPAI$as=RJ~RZy#OsG~v;F$rtR9nZ3iwOqRE1RQJ2WZf5OLfBH;O(c(0K1EV={m@3R@gUPt^BBaHJ+bLgF z#`V|Eow5$tL-`rY+H@JUMuu7!e^NMbXqU+;+T(T`ZvUVfGKrXBx<6lV$*jIwcxz72 zY>PQc(-U^d1@j3*G?Bp@8oDaJ-q_oF1DyDGcxw!pE$_+bccPAnLm%4FeyxxsF{%xy z_2H>%Bu@wMdvs_0xI{@f)-WxU`!i__Sw0v^fq+%zs$oCE>#@x*Ka9@nMU*R0aNhd4 z+ecUKHvf$^W>;Fjx{)bU_GrXCnsGAmcQz>Mo|q@wb+hoPi-ntebH>V8ZRty!`a7R( z%WMB&0nfbkz1i9}Y`IQZaK9&wG()yJB*638D9`=F>ou1qGSO*!$ekU$U{yd?lv~`* z`_GXtRq|f={RXv@6$Bd&H7y;{$-$loqkdPe18HnJMEjHz78eI*2V;myHeb^1 z-b0dvI;+*%i4Cs3oadek#Z;G>mG4;pJI;eGJ*C$UvBn$8j5?zkK~!WiE3zW11woq9 z&JVS(%OPHpJEoT%Mm^3Fn-#jS3fI&?y@HGRYMAD2>3M6UgEv`N>t(}2-^6i6rgbvP z6Wvki>A^{g*p#n73TiTkBg}^0AB7Hr)9Vw)QbMcCePfTReu~E77FU&$F|vVqvKFps z$z^tA9+em*%V#;P@U2x|KMK~))@i1sk86kB%eqC#;Ta1Gf=P3Z6Zu+$sW{Ua+j{%P zlz+Ja?W6C1Mt?bxODdjJT>~zNy+;N1R%MNqSJ>4KIslQ%M+~-qkvC1GTGR1#2hfqG z+@MKlvP5gfCAL^4qWd`qLAGlQ3Ng%GMU;PHNs=*|KZd;@E2NcLN=Y2?mww|_Idz~_ zX4oSbKuPTFp4&nw^ryv=kFA$ISO$Z^k>6(+2ssL3vU@ohjc2UcqI}V9ux!4#z59==p0PBAE3P=9q6=Jf`5E_p=jrI!`u3<4LKeEiUxFZ z@M`|W6%8coPV7lbY2I+jb6Rk|*m1GoD4U)clmTy^m(ZMASZvgF#t!#9KN*ePyRKOpNO)y zjCm%$X&by|T51$7sK79am|ReCzzcU0=3BeKH4=J_9jStFIJ zdTh0+QcJa#oOfk25^0?=M}O2t>l1h1?unMN9-Ma0YKG7_uI~?W$GpQ5)c2Xzp2TZo zXF4~;=MOl&Cf|>+<%bjcyM=BejU*8`av2X>(yvuElF$I=9|%++fi4U+S<(uYojD3< zPjL$m2#H=E&X4X~c^kb<62;q8-}y|vb92Sla1TXb0*Lrna;LfO1yT1mKEi_syspV= z7<+54W)kyN@V+g#z(;EaqYEtee;6w#WI{&}-ZcXQE~`efs*5!+D|Nftk}YffmODN+ zNy(2x@m{|1d?9acYb$jFFC==U4Z~(GXS|<6gAzo6YOR*Epp*Tcy9)7T7q**pyBRy; ziR>j*#+lm^7hd!H}r?&p_=8bd$G#1PCRaxczmR7U}okSStdR9MXf z@J|Rbr{e4SHSxKWQw0Ueja>})%Z{Gmni!XweSE4It&%;=7l*5Sa&aT-k5LQYns^xS zYDX-$yuB-DydnAv)Rwz98n zdJ}?!6TksIrS49cn)YrZGA>iNl#%$!-e6XZTEohU!o$liwft3L=Xnp0@7ML^(X=Kv zH28jJc~<-kA>@qvo5vcK_w6IyJ3dY2KC^5{r!u75+g~uP`9>l;S{<`sU#{TfI-bjC zVo$suZ){FWajMA>(=Vy5HTj1BG~Oy`azCOB@F9$E)LTY~DGuz-+PH>TXgFqI;aSIJ)sQvxWO zGV^$mYRhIFsy9!+7aj?2&wvEJqre53m)|@Nq#~S~J z)8ttB{S@EN*6Vn~^}LK2PpcvL4C8E|KBaRjqgTrJDgJGD<6;bU`tsdx!T`0aPq-~c zQ|NVjsaz(?C_xLHyg9$>dHOwwlqS-M@aI7F7SShJoCwt1u$b~$U0QOpfiFl2Eu4mP z=2#QoEF9_b=KM8e#1Nj9PnX>=g+qzOEPp#qYb4{19DX6D+B3DR)GeU;K=+bQaO$ae zptk-Qk|_P#e0#RoJZC@GKmDy4udMoRbH^5oPfU0pl|Ia2tJu8oT#LKqO?*+?`1~?K z9s7CmP=_l{M_zM_8mh{AMbZw>+;mDX>7D)E)pnX(hxN9!Dan()KSq1kH}T>DLHYe#n*TM z-boB4pq1hACY>Wv)oDA75GQ~}1N^(Ft(dL#medXk*_-MGkRBn zU_Z|1)iN}jYqG;(L=~G~zaqelZzfo4Ekowg0j#I1E_VLFqa*2V>hul(2Ao{?D zm0X+fbJRG06$-_;gpr9SUtTCpj1}$BN=6T6yBBFinn#m3`p@}s)4lDhUfyZ@=SzoL zV3n(f)|<|?wOT>{wN8Rhvb{F;<4fIFp4(#Hy{s<=#dtS9h@!#Xk5igS#1+%Y*t_S` zs8g=_pxBpY3wH?v9wbz8DP=Q*lf5ibh%S2vORak_1EuLBHta(qGlR)&af-si3X;g< zJ<(C;d$5;kZ*yxer}EeRjqbGPd>>YFQ8Vcm67#2ifgX*(yo-|5Go zTPaY;NVEA>l+9sFq*z#CN@lFy@%o<7KwXh>-%Gr};WUtJwDSW4KDtp~e41frK=uIOsf3rJJ)6Gn_e0;BH3#Pb^<-Y|Amfg{ExqJo>9URjvUPry zjNb=5MKLzNT+Z-_49$ZO|4$50^pPXH3j-qzsmU2c?v0BvJ+FkWIbPZPgz21`-?3i{ zp{};6YHZs%`?^$6t`0sfLu%}HVKtQx!9^d`C1F{IvnSlyMDN^)J0&~FQej-I-3Ste zBQ{)xG98o6t3A|B3S0YQWOn&J52ZqGHngND1Q4Dal`!fDW2X*KlQY9aWnZr-Jv zWHP_8sf`n=7JLD3M^tGvA)b<{+0oVCzwR6;XQ#TD z9GpjZ4+Fp5u96#5BtP2AGI(NliOB}PxDfk}ORej(1P!+-pT0g)IGW?J9u(f_$-vO6 z9Z_}YbGyg+ z=)0YRUxD~uDU#1%SqSs zO~@w@*ZM|UGa!l-y!0YCGbqg-vZ$<}Ox)R)cd6+zuGouKuA@T_JhM+PecwqZ2rYDQ zF6hGYA0NCPt9##B>uPSY-Bq3q8#wetAFc$E*h1nPxFR*J%)Z%E`|%C-0J48d8+o~t zdxSc1E$34>$l=WB>xNw4W7ej7+L*l7sC?zJ-{vvZ6kN;)P3aG=^okR2Be8UFs0>m) z+8X%@o>r4iUw@<4ola~vamCeJ(9uxmELwo$fF^Dn<;+Cj!%bLAEo8MLzdapwqutXf zRr1SqLz=hgxOw52LZeKk;-FX-)RfwWo8K+LUrT2F!YaFi=t{!mGsTu^X|ek;F$w(G zymVXADBD#1JkI#@NNm=utfde(hb;iD{2fu`Y&emw5Yh+gxfhf7hvz=$9bqFM@xc5> zAWFFV9sT=#>Dz^iN2}x*g9{BU-w=>smX)9}u|@jN;jBdhXijr{&eh--GhTSNg}405 zP~wRCxv{9mJUx?cAm;u&iJBtH^rD;TNVI`Lk(I{-yzG~VlE*ezD~%qRlOsIx=$D); z>)}js5^`fR0%zE3m`JmkadLC&t-}uCuc;6}7A#ZheaS%iuOUL4n~i{rN2^` zp9xIWSVN>u^F?UM$f{YIg6K!?^IGw{MnxnntdAxaOBn|Z`pzA_$Zh#X_SYQDIr>;x zHG{{mRD}PRqjD{3j`Hq*dn$3>-ozZamTR``&(N1z@6N!#{n11^wU@s@!K9Zb$`u+2 z7`^|dsP2w-6i9A7iY*)^owK0}o=@)^HsuJ5%YvNi#P>D|G!uFH<5=% zxN?mYLi9r-W1tZI(fWqixgLz;*z0Qc`o&4#SjircRk75ADUK3b#hBwb!ZRQ31mM(& z?=Kyq-!*9$pMN9zy$K;&SdW+ffm+AUu=jn+_fc$4)fQ~phIUfOWN5AuK2ZUY_CQ=Y z{sjqs83Gd010$x@2W0WcE2jH(Zf$G6Gvo1h*Mwt|1;=`dDcw6TJgIWz!=YhH$_Ax2 zK$9Pr4L@07d{32JYs!(D(NrtvS-|!DO8&)g-vMIRdO$K$HgDxg^;dt&1JB$k4cVG6WG?XEdURY8x2Hqf2HnFk zG#|3;la$c$LQQSRu9&l1KW=C9_*UbClB!KqUucq^$kjr8m_FM)yN4Xz*|Z-eK5>^1 zxq0gT@vsc=>(P#<%vRK~*IYa2mZb|UA@fR$GJ5dRzr`9{+8BD#mPOaE<()*UoQXFImmqT+J-u zx~OZ;n^5hPkBimBwfw^g_QVP(GAI87Wdr)Eh+1)pT~KO(jw?n=jBu5*IE2C0JvGUu zWQyUAm?-z%mZ>plB}-Iv{nHEN$-%x%paXq!YYUd3kw#Mc_k>L;SJQLSfeKkxhj#>} z0O`fo8-NWc?_rmK$^EDK54y0&fSs>k=398fd{)d{9x#@VZ9oZ@Z_t=KzV);M?W`hKp&I>4VCMZq0+)>`J3ksEsLnnA|r+OjBK z6`V@5@bep&8wRVT*Z|b+5N^_69%)Cd|9Yg6g4Ng9^G4#A`yGpeG_DPaPd9L-z^Gtj0)2qBhEq`&qSqCRPfo%iJY{Q#X~V-)^}Cc83wb zndVL1QCn2RdZLRA1V8k=i_oyaPEpB{@9H{_0X?47Yb2)3`|A&2n~y2jsU}Ay&Gt1C zrJq;rLP4s(k|-1?eNjxO4IV6=>KPx}+M}czu>Ry_OIMH$k-$8GTID`TYqQFfDhMaA z_lwa^W?Yi53I%ghM-R#EsJ%Q*{r=WGgxeLm+xJ7<>R(p84V)xcRMbyc3@m9nq4 zZaaTUv99IamZjGAZv}^KK59VFME+-nl}VSBX*qB#ms7{z7?$Dhz58py853uS1VgE( zEndq=4Vh&hNSN>rF!WV|HCX}p|m=t+K8amb|xsB~ph zAb)+=&3fPA7t4eoX1fWbeV1z|X?t~K49{f0OejalyGRs5f+)Bm4{B`4ha@7kA!RsHip2#r++jAG#4+?^>bbwWj1*P-dO@T_iVcrrPwr)IC%<@W%a8j& z-SQzns6et)(Ds&m#gp;k{=yTN;#8j>i7y$%16BYPhYsVcBa{2rB5w!-5i5I!8|n-* z$j-K++x5mt#2H#aV!LVt{P#(;7EBz>$zl|4wlT(Lw=}#^>*T#KZk`{zCM8lWvNG zT>{!Cqr}R!NT`qr99Iu588@s~%NIn7?{HCJ4DbK_{Vi8Y;@u+IM zg*En*bq{fr%b_HcEp97}mS?OVf!n-e)IRQ1Vdr4Wt`x^=R$ik!T;6Wg5I^%J?xpK% z_;QnueNZqoPwqf}u4J-6tt-w68hifhyRI6ZTdK;%RC9EA=I&PJ$)xrdoQZpYv_yh5 z*Kc6x83x5Di^zoTAKr}fQ1ilX4_@e}%FGUqd^lrJN=gTpt-DZ2Cha5l)0s%H5A!bV z@st4rH1CmH>iS6yB(YB^6qjO|fvKPXUW*s$emGvuL+j^y)_wO6h;Wvo0`9CR5 z9Kl*3CM}I}L_)`HGOb=#x$wP!GzZrMSYXQ3PKPH0KM2Az$p{ZvONA!8f&Mn9HTEQ_@1@&vSYH_0a_lI zRYv!=^z)=p*DZ>IEheKiDL6N}@yeNBpZSVkDb`(Y1^AC+ekrYJW6i)OdmRd@<4S~i}iu^CQgldS3p=+`9Rt&fEj zfMfDxW^BSs|0)0QDSbHe&>Z~%0-eZ? ze87%I`F&(!B7>9YtO&wcTIJTCD1)R2Kv9MO+n5f6C34LFxTKxLX9OJlPu%Yfwn~vq z?AvSpFk=l+~KG)DkMnyF6sI_cFO zS5{b@3);_MqSSQbpi22LF6JP}ZA$%1(`jwM^)t$RAK!r3(kDK1I^Zl;Mv)AXNE&}Z z&rD@CQB9wbdH_3P4OL-k22i&L*|#NZHmlrpdHe13*!t;;z&tHt-o&Wy=liyc!e0#3 z6aN|`YkQ|MaN8kwXXKi@Dgys;Ocuff%tvc1@4>&zeTGofqqKI8VSOYB# z2x|~;e(k#TyzcOcwaaj(ly|Rq?~Z@5u1g}1>#mPP;R#Z-d?;I<#7g)^k(%Np-cm4; zwfT8m93Q5A6d27VKa!9cN84dMwl8!XN>Ocbg1okmug)`1pWNRqX?sxyLsUM)x25q& zP8IaWCw02)@K!8ghk{9$H!)151)-$AXoxToN<$luwD2@P=lH(a2l+bNQOH*8Q$pMc zBY;P2jyUVCTrS*rY#b49^_{2L%k<_={QQODRt(Dx5R_0~l{3t^=?pDm{@YjvDWBp3 zp5N)1*_`evm1TP}f8b^{%5hZKD5c*0Q{6UCt0~w-B({)qF$4?|k1ZLR32S0OA%j-} z$#jwf(=B=n32Uzm5h*)PWyZE}Q4ZC00pp_f*NMVglePh@Ln$qVJ{fXS0M64Y@jWIt zhKeF^Hv_=rTORM>dn{G*DwNJ z{{#_sQQU^#6ytl|$oL!)PsqX7h~%DYb1AG8(GB zHru};3|94`=2P$^Ij_90cEA-~(X~3Fx!axNt#5GS>8>xRpbB{lK~OV`)%u;c{cJyY zD)M^8#zZ?amni)a1J)fzh&#e0z@esOeY&JP`ZrhsoKVbx6X-j1sPXRnV$PzZbG508 z(8|K46Dg&XCoA7|x+pC33%9sUW4#?3k|4L^cM$Ehvy$3G;d}2wa$pFW0iAKu%)3Jp z^2wu2Yx>cNy5UnX*qaS>9=oKmjG97&{DI>}+(JjccD(i^R{GX$U)o??_yL=iX`kTQ zkx-GUCV;!qY&YUyDy=YAx9vN-;6bxB;#PA_?CK+1C}=*?vy*F4fEe4C~#iV?G7SBhpY5bcif-`OyXCO%-!LHyarT8j_{( z>QhFdUd!p^E}DmA6Pqi=PfCm(X6!G3p|AyoG2e4f4O3yD!l@`4J-%z;PIm1{bDkY| zd9K;ssAZbxG*zRHG;v{8&VA!{K-0vR98M>r_@pfuE{eMoozt_LV|hzHCX@AwnubYB zReVj!^Xc~GHY2|$-U%=n$+uPiJks-`<646wZAe!aN6L(z3=@&oJ-sI>bDA%zt#7}o zH<8b{^X*a7`QRs$Ggmy@PMFx;H|RrRzo^O>zn3-jtvN5x0~qX7y*P0LJcwsF+e3~;z@JfZhm*PD z;&&AHI!8uc*1XEb{x8VI+1!EIAg4XK4~}#a7`gZ=<`3|4b?T-?8ABn|lY?Y#mFWN) zQwVIQoiKAKRT)0CK+v>0^f?=MFQ_KHR!d?^PFVYr5}|l1|1Y-#7v=+ZJfI|ANF0^$ z#QX&je<(kPOYH|nCX_Cerx^c=+b7jyY2(6BfxIum=ll()PAgT#$I=b2u3RVkjGLE! zyd3a=*q(4FMo0Uw74pFT_~wxsSSsStm3N+-U1{sbA>X8e&J5jQKol`eSa2DBT7y2H z=sd>*Kw$Kcqcg%}$oiM%%u>Sn;v(w@*ivWbCeC*iAIbSo8a!?^)Hjq&j2ixbAqa60 z92X1C=Nk}gnD_>QzhXz9VDsrx2Iz*Q*6O9gfjr&*5db@dkpdpy*g1jyIEzs&z@Ls1 zQ&DQ(I!A8%62B0p;Q}5t>+g3Ui}x;&j0u|={cthnh2$c?HOnVHz1)qNQIb?RO~lkN z`^~A<{nu$Uqccu2=$iizs>22u9%Lr?MeC~+)HurVVOLRPC*T&BP#qjbF>;;N8npb? zp@otYo2M<}-M*JtgD6(_LW&3cX}1UKn=263aoMVJVCF$Qy8Js%6Ktb0BxtdA^k`Ikh=1sVCL?ftZ}2^pRC_rCX!Xolkm!LLe`;7L6S0MD}dsqfn`# zd|CGGm~DEW(b%&Z!^wu+qZ1%;e=weC2mi!-pOc!^ODBt(QsNKtA01nkQ7dTLx5nEBGu_7C2f`}1)>7pjBU!Uc(5$L;S_7v8&g4qUQ;JqpGhQky z4(A~9xE|?x1s6ClUX2&RGSI@vY1OV?0i2g%mU>QHvmUNR_O1erOU&w6xHB42&+gQx z!UE~2V7?voWA{cQeusN-Zj9-)LC#wkr=a&C2xC)rt4P49&)i1pDFh8jFD>zuUD9_+ zp$|{}2i(?Sx?R)cphPAZFZ)wP4;O~g*SOZllNIJ9lvcPdH)homyuk&q{!yMgbi6>% zTg=sKx(|1S3HOT16aMI7^x09Z2hWuYj-$kd6cNa*il_P&ign$x(G796S*i6j-n6qa z+{ZqofrsaN=vuYF+P(XhW%7pH z(h{QX{fzqcnF8=H1R=zDM>DA$l`OLS6=P$b)2XpaiR^ET0`z$+H38Ya8Jqt`6j1o_ zMElV=zZ@!w`fnYcd7=J#OlW8Wpj8IHY})7f0#12s6bXs%$5(_KC%M zTE+J=A?(Ae1uy<4`nB7`U|;&xIZkVI>0cqg5)pj%9M0L1cxe>$eoLx*mCsv2&hktp zmP$!2qhL1sm-aCD?v8l~jj$8k8@t%S--ESKzWIRuac|cX2G^i3hF!Q%ofcMQr40@( zFCJy6W1Ni@NB@sBM9zJkFGZiO?SRR>b@Y3$3n@J35X46P@vj#Kj~}h0jhvRnS6*;_ zPugN{0@6apU*(^Km4}ja%5CqL8ULY30*IQ9U9*b_c!PI~I`pOJgX@h*2US>&K%uvsvfavE{#)1#kjD@wCw89Jg5?{gi{wt)vICJ|k1! zi7R8zxySajpjyHhO+SLR<-}uh%MYdLL&TNfCK>VobqLT!qd#&M>UnLu*}$%Jxf;i2G_LJ zA4e)WWODy)$<46wP}}E{C&BF-K2;xZ-I7I||B>8bS~9zcNQ*W2;z{*tpi@UY$m5?{ zV4{Zua0suqc*}GNYLIs zT7BK>%l-k5j-x&kQp(Tv)-{9+(HyKNDks9@_gle93FXr?Kd?_B$0~HHVwM`z37RHE z{}~8~NhVLiI|*Ai;7K$cKDq!n9X5MqEVSI>Cj6irkGGE~+>4(Jx|1ZJC$Yd~e~_BL zR07PcnjDhiDK9SXlPYFio*@W-bzlzS_MAJOe*C_41q1~>UANUIp4giC%I6s;&Szbb zzQSw~G}`*dn!Nr{ zt8De70PkpH>Q4%R!!^Tc`KbACf9u{E|7(bD_m}G>9r|)8+iJR{uD@8lDJ+pp$m*AG z+}7Q1$HC#0ofQb6?hXBVt~iY)DE)(wcm8u6j(ZXsv>L;#;HVq9sodq>^N^`2LB|R+ z5iU(^rw7U}`O*B0W15x6m=3ldHp<>jwlUleIf>eEgqeg@L@qy(DK~74?|?jhd#u7f z=Edy`qA?y>gm#^1BFFWnh41t87L)E-Z2aFlt1i7Zz5c7c-SHHry-ZVi51@rxIi04H zLxWm}Q(UfQy`fwz?;-Bh=dR464hqiIy!`0OyY6x@rL2~b%&{@+GDp1E>EWR)=&LRG zK=-`rFn#sr4l%e}!6ASxyW5-fW=cNTdir)xaGosPb9c$ZdBSLB4*zQD8ISD7tm{Qe zpcMG8UtSt5E)Dj&5YEJWdnIMd9=Y zpP0T^!WnD+2-xC(Xfla?x)fveqQi#_xCn--<&iOL+l{ELPplfHZ}XYyP6?HLxQ_8Y zW57^*d|)C>+Ht@kx2k{V1CAyY;X5rb=u}sqq2c;9y0poyx|3V!J0jSqtmfsMGhi`j zEWP-Zr#s*TPyzCGcRk5_R-#r(KXh3~S`TxM=Uv|3BndAf3T}}ITcDl%p7KW3m%;QV zpRdxQFI=$)r5=FD2Z8UtbT6^MVO%%&n}{f3HeUE$Jzv$nv@5x+y?WlZYRPlQj;!4T zqr{8?@MIp&xk=s(1<<*VpV3R(6S1gch+hhPIqF zrMa=%?{Mos5cVU#fS$O02ZJ{wTabLnv!X+5aHHK?-*y$z&e1m{sK@H+Yb3L0NBiS% z`k887cgtQ3e*&Nh=~UJ3(SJ{W3oaUvpqu`5Z6LwQ_&UCidWl2;{DG`aRsEH&t^ENB z@$vFj!B44P>X%-fgV;vqx2M!mT)Pzoh+(sY)8xGcm+2M{U5g;X9mt$*!gGHv1;3=u z1;Kt+-(LG9)NjYDM2>pqej8g6!c>~pA1@W%6uy`K0HOr3N7g&)Cg1sf^|e>$Q zXLv9|(|5XRdLk!EA2$>;y?B^rzi(0~ep%a(FNpB0ekNNNQGUL61EwtF0gkss_oLT4 zc3Et754bNE>k131jOB!R13>9rBEPRsbRPtoz4caWujKzVD7L=L5KqQKB>V)?k4fyZ z)>dtPv%@uh>qkuzAyvIqJ>&`Wvia)k7Ra+5?LBs@NMZ3>h|4$c6I$@sbE_&txFHYn z^1ib%%NhYx`oSaIn{X*Wc;5|RvW!CrC!T7QZ_X2@x!(l5)ngWQNpjC76*Uil;?WI| z`6X2{&H)&$6;Ky8+Gd?A}48Ma0CRTUtce*c4Ags_IO$R>Y$nECy`73 z%{&CVn`_Jg#b;#wc+|g5NslSdu z*qfI3>B=fCvI>VDk5zNfAq^Lcbr6}nLd7|+9-wmsU%}DgfXr~-;CRCDQ~fb__s_`j z%(7Gu0Osn!f|pb5S~!dl7!A8~kkQt=eKIpNbzYaSZg6K7HKaw{A(KH;xTgM0+kFtAo24`>^iIs?yA9j3lP6eB!J-@Tfd$KB+9>=?=iM( zDAu(u)N7o@`CIX@ft2hY4i&$+G)?r$)EkY4Sjsy) z&3)kVXiA9}_esXNm_Y8Qm6-cVI`oY$>pGa|0_ zb!~cxkg+^nL&=IT?&d-htj^c@Vge&BNYGu(ij z>S3^h-=Xvv&%8#cYKQh1b27Yeew~P6*l{xO?O`G0>8kyY{YhG@iu+^3H9M}prokht zugLwq+do!l&H&FRPkw&B9pBq^-BN9E{j3I2cCgYkIvw*nlT8p{SP7Q`zeAX~=2N-_m;*r)+ z4d1;IzDjI+oIB=be+J~xbMQA$hCBX@>8NuY4-w+Fa?bDO3}J_*5fN(KWp| z7$xV~8B!)Z=#n0xG(=Jlan4p#G-c7WrCY@I^K$2~k)z{J=tT*H1bp=sZezt)KFs}z z(INhOZkrFF*98H-Y9hrc@IYmbyF{v#q#1@8oY}<5NL^y0R5FCm7s1ih5aZ*Z& z%0&#FKpJ9INtkBGleh9d64m+%?U&PKvx~R$H$6HQ>Jqq=oi4@v*bUP-4X4S79e)@W z0yWK;i#;+_iy75gihz*OpJAwJ_YKhX%s3iP0l{=@(tijT3tYgfhel=8Q!K8PYbp6K zAWg%5D++#yx)@*jtw=z!I)4XC41N1^?UT^z<3yWcM8C_>7^73JJP&ps2B)cPj3>%) z&9k>~LNA)OhE66P*US~(>q8KZ2VOlWlWa~xn#xer5Jrl)NDqc8NdcBJWQ0ftt`!(v z3l3F!g*UylmL0>qF$xzUSHQq*knW#~U(vQe?$GLALp`*LXAsnTVXwaJTPo@a?Jq!t z0s{r{$0eN2@z!Pww8rIss=>OXhUUti?A^A$Q*axQ#(vQ5jOEe+(0o!M|C(MPHbZS~ zAG@$hZP7p$kBudhY|ANS13RNz&XcD+$8FF8Ks6Ia+bd1+h!xwu+A(*iD{M&2wH;-q zT%n@_1>X*XnQ!htGg#5&Jkf5UI6ub_gS6|!9y*QbB1s*Qm#v7dHH>8U>e-_xDlQ*p ziH#!)91%BZ4z1VrCSzoZj}Y4riIRw)|04E_Kby&@+&|wO)){y=;DdfG@MU-Z)4DHdT*+r`i52@NW$_aj zQd&^K)wl{Sz`J^Wxa+lYz^d%hebA8^^3@5lXt(n}O?wySqawr^zFsfTnyc;=RSv(P zcLxRW-?RRkT7CR9IS1e9{{2OOsOcRgJoE1d^Vi>2zd5IgUzG0LC@wD!52+b6Q2+JF z{w~004@dRZSuGQFsUG^@60(6XGqV3w04na!|EstlYER}V#jlY<4`}}u6mWu_GY9)m zu@HX{LlkcR{pP>bj4rSol|_&INtD;xs-kk; zi6*>64;L1AH787u1xag*E2ipb{P5ru`As$~`_fNagJaurflOk1%~WbZyvAgnebwB@ zSnOAD9G0r7&RIADGj_C?(vuh&ZCsVBEL0LH!?M)f<6?~86di5?v+jR%RnV{b`3Qq7 z#eGiTny9>IX8ZrJ^_Ed_G+Wd#1Sd#>JHg%E3GNO-g2UkM?hxEv1Hs+hb7SRF5%`bu?_$!004=9!dM3G@Q6W!(5aIYajI3pKKz z^m0O{D3epZ{DjJ@)c^UlkAFZ^&6OwjnP8N_#z=}?!*9FjxuKY9$HZLYBc+sK&^Qu& zXk&ZW=-Uo_9}Y3FBct*=*?+ozDX@^o5)asb|Fb<(@-B~iSeE7;qgbe#`GCY~_}~sb zD`|=Op`W{5hy`HYU|$bPsm+|*UERm-4xGjq^*T$+r{5~jd%>l|4m3?Z^)&OE?9A%LzWT^YAaY1y$<9eGRyRFT;@g@7Vj= z+tv`3XZyv%laf!1LRJkbLf+KxrZ`%;MMs;UGNEv+%wHr`(S9*!miBZStI-ce=R@=P zOrDaX*oJfmi-lS2hSYeNRN67UyeW1GJv`zgt;pJBQsXA8IkQ(rtUiU<8TKoQ)=PV& zV(uwDgY9!%YB{c=X3^vPW0|}`Q5lXqRkrNOCxva$&0dRZfT5PA`Mx7Z;}pE@WBHP6 zOO6%U47PtEHm;rd)(@zO3cbkq#sp$>N+4dr<~iA=#>Z@U?-y)4qm@^Bon(|D%s$m^ z<8uU(sGOf+lm`IGgk+OG5*lNUpvL~u3-VaaPG9|0^Tr^_j~Wfs1Ts-+efy;cZRv&j z1g8@)#&Y1`d~F>ex;>3;PX>IE8`psGRfKjwadOkR@xo&%YRa)P@4zfw7IPoLz4Pm^ z97;m%8(qpwG~DE^Yxfr=ZcIG`9@DkC$+KL2fo`r9iOoTJ{35g8ekqr;+E0nC6GCyy zsyf`GGUK!`-0DykA@SGFxu~S4DeZ$3^xQCfkT%f}{NM>{T$Jx8)zwkoe2uicmIyO{ zU{D~YGNlmpt4=Q@kL~I{&nCv0Flb5=sCY%rY$jBwg8L%6eX1zv#;Q>m)Wt&%Y;x^V zSO23hBK;;WSc-wK^O-Tz-b}11bn&RD>$~YWfCWKJ8C9AVtEbBGuNy9vsiw1f?DDRt z&6Vm^Vs`5O>jnzMUB7^&Mi{@|1^}|mZG)h=>|jaNg$spl6pT-JghFyvbD>e)VsHxM^hT>F3)at$HU5|f9HT)#D#;sXeYy&8T zpy2j9hs}5B9j4EW-8x^3E17oojJdhvS^x500u;N^r!2_@grgoNG2)5simUAOOC+Qk z95i5C?mrgU`EFdy7qxrUtquo$YVXz>gG!KzYOe1uO7y5mH1CiYpVH!9CmMEsfJ^J- zms{k`_L?OAvw6m*rKQUvl!djp zNiaPA*+4Gdru(X>1B+cJKD(T+tR4^&o>kRw+k<#rNOp>?JXUT7rJ$l;lNcZv2uPBV z)dcDqk*PWW{AIr=95n3XIPd!I1)NdWGDC4^meV2Y=pc78aE^=N+)I+S^R{D(lAo%6 z%oO_5%;F3dTOGt%w2(=`v8oz-D8i>o8p#~%QKq^nh(?9st8T#4>0TDKQe~KM9|*Og z=fekZ?~w0OY)KZ=GE)V|Mk`uk6WDM!?MRUOhbB(Crb>=>r<|i&nPvwyvq&TbO_wm) zkLzPV+^Cgk3R#1#fnCGUhkOtRldY~LY(#|OrB68<@E?!HrAO}RE010-6g0P;C7@N( z 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 From 84acb971a0bb3a70022aed9e75810d4607783fdb Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 3 Jan 2021 20:36:04 +0100 Subject: [PATCH 138/142] More code for allocations_familiales --- .../decrets_divers.catala_fr | 20 +- .../allocations_familiales/metadata.catala_fr | 266 +++++---------- .../securite_sociale_L.catala_fr | 310 +++++++----------- .../securite_sociale_R.catala_fr | 41 +-- .../tests/tests_ouverture_droits.catala_fr | 32 +- src/catala/catala_surface/desugaring.ml | 4 +- src/catala/scope_language/scope_to_dcalc.ml | 12 +- 7 files changed, 245 insertions(+), 440 deletions(-) diff --git a/examples/allocations_familiales/decrets_divers.catala_fr b/examples/allocations_familiales/decrets_divers.catala_fr index 6e89db38..5400a2bd 100644 --- a/examples/allocations_familiales/decrets_divers.catala_fr +++ b/examples/allocations_familiales/decrets_divers.catala_fr @@ -10,12 +10,12 @@ Au titre de l’année 2020, l’article 81 de la loi du 24 décembr Le montant précité de la base mensuelle de calcul des allocations familiales (BMAF), en pourcentage duquel sont fxés les montants des prestations familiales, est ainsi porté de 413,16 € à 414,4 € au 1er avril 2020. /* -# champ d'application CalculAllocationsFamiliales : -# définition prestations_familiales.base_mensuelle -# sous condition -# date_calcul >= |01/04/2020| et -# date_calcul < |01/04/2021| -# conséquence égal à 414,4 € +champ d'application PrestationsFamiliales : + définition base_mensuelle + sous condition + date_courante >=@ |01/04/2020| et + date_courante <@ |01/04/2021| + conséquence égal à 414,4 € */ Des règles spécifques s’appliquent par ailleurs aux prestations familiales suivantes en métropole tout comme dans les collectivités de Guadeloupe, Guyane, Martinique, La Réunion, Saint-Barthélemy et à Saint-Martin : l’article 37 de la LFSS pour 2018 a prévu une mesure d’harmonisation du barème de l’allocation de base (AB), de la prime à la naissance et de la prime à l’adoption sur celui du complément familial. Cette réforme est applicable aux enfants nés ou adoptés à compter du 1er avril 2018 et en conséquence à l’ensemble des enfants à compter du 1er avril 2021. @@ -108,14 +108,6 @@ Je vous demande de bien vouloir transmettre à la connaissance des or @@Décret n° 2019-1387 du 18 décembre 2019 portant relèvement du salaire minimum de croissance@@ -@@Début métadonnées@@ -/* -déclaration champ d'application Smic : - contexte résidence contenu Collectivité - contexte brut_horaire contenu argent -*/ -@@Fin métadonnées@@ - @Article 1|LEGIARTI000039640195|01/01/2020@ A compter du 1er janvier 2020, pour les catégories de travailleurs mentionnés à l' article L. 2211-1 du code du travail , le montant du salaire minimum de croissance est relevé dans les conditions ci-après : 1° En métropole, en Guadeloupe, en Guyane, en Martinique, à La Réunion, à Saint-Barthélemy, à Saint-Martin et à Saint-Pierre-et-Miquelon, son montant est porté à 10,15 € l'heure ; diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index fe3bc4ab..28b1a7b7 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -1,24 +1,26 @@ @@Début métadonnées@@ /* -# déclaration structure Personne : -# donnée prénom contenu texte -# donnée nom contenu texte -# donnée date_de_naissance contenu date +déclaration structure Personne: + donnée numéro_sécurité_sociale contenu entier -# déclaration structure ParentsGardeAlternée : -# donnée parent1 contenu Personne -# donnée parent2 contenu Personne +déclaration énumération GardeAlternée : + -- OuiPartageAllocations + -- OuiAllocataireUnique + -- NonGardeUnique -# déclaration énumération PriseEnCharge : -# -- Complète contenu Personne -# -- GardeAlternée contenu ParentsGardeAlternée +déclaration énumération PriseEnChargeServiceSociaux: + -- OuiAllocationVerséeÀLaFamille + -- OuiAllocationVerséeAuxServicesSociaux + -- NonPriseEnChargeFamille déclaration structure Enfant : donnée fin_obligation_scolaire contenu date donnée rémuneration_mensuelle contenu argent + donnée date_de_naissance contenu date donnée âge contenu entier - # donnée prise_en_charge contenu PriseEnCharge - # condition confié_service_social + donnée garde_alternée contenu GardeAlternée + donnée pris_en_charge_par_services_sociaux contenu + PriseEnChargeServiceSociaux déclaration énumération Collectivité : -- Guadeloupe @@ -31,198 +33,82 @@ déclaration énumération Collectivité : -- SaintPierreEtMiquelon -- Mayotte -# déclaration structure Ménage : -# donnée enfants contenu collection Enfant -# donnée parent_en_charge contenu Personne dépend de Enfant -# donnée enfant_plus_âgé contenu Enfant -# donnée parents contenu collection Personne -# donnée parent1 contenu Personne -# donnée parent2 contenu Personne -# donnée résidence contenu Collectivité -# # Le mot optionnel permet de prévoir le cas où le -# # ménage n'a pas d'enfants +déclaration champ d'application Smic : + contexte résidence contenu Collectivité + contexte brut_horaire contenu argent -# déclaration champ d'application MénageBienFormé : -# contexte ménage contenu Ménage +déclaration énumération PriseEnCompteÉvaluationMontant: + -- Complète + -- Partagée -# champ d'application MénageBienFormé : -# assertion nombre de parents > 0 et nombre de parents <= 2 +déclaration énumération VersementAllocations: + -- Normal + -- AllocationVerséeAuxServicesSociaux -# # Les champs parent1 et parent2 sont cohérents -# assertion ménage.parent1 dans ménage.parents -# assertion ( -# selon ménage.parent2 sous forme -# -- Présent de parent2 : -# parent2 dans ménage.parents et parent2 != ménage.parent1 -# -- Absent : vrai -# ) +déclaration énumération ÂgeAlternatif: + -- Absent + -- Présent contenu entier -# # Dans la traduction informatique, le ménage est en charge de chacun -# # des enfants -# assertion (pour tout enfant dans enfants on a -# selon enfant.prise_en_charge sous forme -# -- Complète de parent : parent dans ménage.parents -# -- GardeAlternée de parents_garde_alternée : -# parents_garde_alternée.parent1 dans ménage.parents ou -# parents_garde_alternée.parent2 dans ménage.parents -# ) +déclaration énumération ÉlémentPrestationsFamiliales: + -- PrestationAccueilJeuneEnfant + -- AllocationsFamiliales + -- ComplémentFamilial + -- AllocationLogement + -- AllocationÉducationEnfantHandicapé + -- AllocationSoutienFamilial + -- AllocationRentréeScolaire + -- AllocationJournalièrePresenceParentale -# # parent_en_charge permet de savoir quel parent du ménage -# # est en charge de quel enfant -# définition parent_en_charge de enfant égal à ( -# selon enfant.prise_en_charge sous forme -# -- Complète de parent : parent -# -- GardeAlternée de parents_garde_alternée : ( -# si parents_garde_alternée.parent1 dans ménage.parents -# alors parents_garde_alternée.parent1 -# sinon parents_garde_alternée.parent2 -# )) +déclaration champ d'application PrestationsFamiliales: + contexte droit_ouvert condition dépend de Enfant + contexte conditions_hors_âge condition dépend de Enfant + contexte plafond_l512_3_2 contenu argent + contexte âge_l512_3_2 contenu entier + contexte âge_l512_3_2_alternatif contenu ÂgeAlternatif + contexte régime_outre_mer_l751_1 condition + contexte date_courante contenu date + contexte prestation_courante contenu ÉlémentPrestationsFamiliales + contexte résidence contenu Collectivité + contexte smic champ d'application Smic + contexte base_mensuelle contenu argent -# # Lorsqu'un enfant est confié au service social, il ne peut être -# # en garde alternée -# assertion pour tout enfant dans enfants on a -# si enfant.confié_service_social -# alors enfant.prise_en_charge = Complète contenu service_social -# sinon vrai +champ d'application PrestationsFamiliales: + définition smic.résidence égal à résidence -# déclaration énumération Prestation: -# -- PrestationAccueilJeuneEnfant -# -- AllocationFamiliale -# -- ComplémentFamilial -# -- AllocationLogement -# -- AllocationÉducationEnfantHandicapé -# -- AllocationSoutienFamilial -# -- AllocationRentréeScolaire -# -- AllocationJournalièrePresenceParentale +déclaration champ d'application AllocationFamilialesAvril2008: + contexte âge_limite_alinéa_1_l521_3 contenu entier -# déclaration structure PrestationsFamiliales : -# condition conditions_hors_âge dépend de Enfant -# condition droits_ouverts dépend de Enfant -# donnée base_mensuelle contenu argent -# donnée base_mensuelle_dom contenu argent +déclaration champ d'application AllocationsFamiliales: + contexte enfants_à_charge contenu collection Enfant + contexte ressources_ménage contenu argent + contexte prise_en_compte contenu + PriseEnCompteÉvaluationMontant dépend de Enfant + contexte versement contenu + VersementAllocations dépend de Enfant -# déclaration énumération ChargeAllocation : -# -- Complète -# -- Partagée + contexte droit_ouvert_base condition + contexte droit_ouvert_majoration condition dépend de Enfant + contexte montant_versé_base contenu argent -# déclaration structure AllocationsFamiliales : -# condition droits_ouverts -# donnée date_ouverture_droits contenu date -# condition conditions_hors_âge dépend de Enfant -# donnée base contenu argent -# donnée avec_garde_alternée contenu argent -# donnée montant_versé contenu argent -# donnée récipiendaire_par_enfant contenu Personne dépend de Enfant -# donnée charge_par_enfant contenu ChargeAllocation dépend de Enfant -# donnée rapport_enfants_total_moyen contenu décimal -# donnée nombre_total_enfants contenu entier -# donnée nombre_moyen_enfants contenu décimal -# donnée montant_premier_enfant contenu argent -# donnée montant_deuxieme_enfant contenu argent -# donnée montant_troisième_enfant_et_plus contenu argent + contexte droit_ouvert_forfaitaire condition dépend de Enfant + contexte montant_versé_forfaitaire contenu argent -# déclaration structure AllocationForfaitaire : -# condition droits_ouverts dépend de Enfant -# donnée montant_versé contenu argent + contexte montant_versé_majorations contenu argent -# déclaration énumération ChoixParentAllocataire : -# -- UnParent contenu Personne -# -- DeuxParents + contexte droit_ouvert_complément condition + contexte montant_versé_complément contenu argent -# déclaration structure AllocationsGardeAlternée : -# donnée choix_allocataire contenu ChoixParentAllocataire -# dépend de Enfant -# condition unique_allocataire dépend de Enfant -# condition allocataire_double dépend de Enfant -# condition demande_conjointe_partage_charge dépend de Enfant -# condition desaccord_charge dépend de Enfant + contexte prestations_familiales champ d'application PrestationsFamiliales + contexte version_avril_2008 champ d'application AllocationFamilialesAvril2008 + contexte conditions_hors_âge condition dépend de Enfant -# déclaration structure MajorationsAllocationsFamiliales : -# condition droits_ouverts dépend de Enfant -# donnée base_par_enfant contenu argent dépend de Enfant -# donnée avec_garde_alternée contenu argent dépend de Enfant -# donnée montant_versé contenu argent + contexte nombre_enfants_l512_1 contenu entier + contexte âge_limite_alinéa_1_l521_3 contenu entier dépend de Enfant + contexte nombre_enfants_alinéa_2_l521_3 contenu entier + contexte est_enfant_le_plus_âgé contenu booléen dépend de Enfant -# déclaration structure ComplémentDégressif : -# condition droits_ouverts dépend de argent -# donnée dépassement contenu argent dépend de argent -# donnée pour_allocation_forfaitaire contenu argent -# donnée pour_allocations_familiales_et_majorations contenu argent -# donnée montant_versé contenu argent - -# déclaration structure TitreI: -# condition droits_ouverts_allocations_familiales dépend de Personne - -# déclaration structure L511_1: -# donnée prestation_courante contenu Prestation - -# déclaration structure L512_3 : -# donnée âge_limite_alinéa_2 contenu entier -# donnée âge_limite_alinéa_2_alternatif contenu entier -# condition âge_limite_alinéa_2_alternatif_utilisé -# donnée plafond_rémunération_mensuelle_alinéa_2 contenu argent - -# déclaration structure L521_1 : -# donnée nombre_minimum_enfants contenu argent -# donnée ressources_ménage contenu argent - -# déclaration structure L521_3 : -# donnée âge_limite_alinéa_1 contenu entier dépend de Enfant -# donnée minimum_alinéa_2 contenu argent - -# déclaration structure L751_1 : -# condition régime_outre_mer - -# déclaration structure D521_3 : -# donnée plafond_I contenu argent -# donnée plafond_II contenu argent - -# déclaration structure SMIC : -# donnée brut_horaire contenu argent dépend de Collectivité - -# déclaration champ d'application CalculPrestationsFamiliales : -# # Les règles déclarées dans PrestationsFamiliales pourront utiliser -# # ménage et l512_3 et leur données associées -# contexte date_calcul contenu date -# contexte ménage contenu Ménage -# contexte prestations_familiales contenu PrestationsFamiliales -# contexte l511_1 contenu L511_1 -# contexte l512_3 contenu L512_3 -# contexte ménage_bien_formé champ d'application MénageBienFormé - -# champ d'application CalculPrestationsFamiliales: -# définition ménage_bien_formé.ménage égal à ménage - -# déclaration champ d'application CalculAllocationsFamilialesAvril2008 : -# contexte l521_3 contenu L521_3 - -# déclaration champ d'application CalculAllocationsFamiliales : -# contexte date_calcul contenu date -# contexte ménage contenu Ménage -# contexte allocations_familiales contenu AllocationsFamiliales -# contexte allocation_forfaitaire contenu AllocationForfaitaire -# contexte allocations_garde_alternée contenu AllocationsGardeAlternée -# contexte majorations_allocations_familiales -# contenu MajorationsAllocationsFamiliales -# contexte smic contenu SMIC - -# contexte titre_I contenu TitreI -# contexte l521_1 contenu L521_1 -# contexte l521_3 contenu L521_3 -# contexte l751_1 contenu L751_1 -# contexte d521_1 contenu D521_1 -# contexte d521_3 contenu D521_3 -# contexte calcul_prestations_familiales -# champ d'application CalculPrestationsFamiliales -# contexte calcul_avril_2008 -# champ d'application CalculAllocationsFamilialesAvril2008 - -# champ d'application CalculAllocationsFamiliales: -# définition calcul_prestations_familiales.ménage égal à ménage -# définition calcul_prestations_familiales.date_calcul égal à date_calcul -# # AllocationsFamiliales est un cas particulier de PrestationsFamiliales, -# # le dernier est donc inclus dans l'autre. Il est nécessaire de préciser -# # que les deux contextes parlent du même ménage pour caractériser -# # l'inclusion. +champ d'application AllocationsFamiliales: + définition prestations_familiales.prestation_courante égal à + AllocationsFamiliales */ @@Fin métadonnées@@ diff --git a/examples/allocations_familiales/securite_sociale_L.catala_fr b/examples/allocations_familiales/securite_sociale_L.catala_fr index e6e41461..39443f6a 100644 --- a/examples/allocations_familiales/securite_sociale_L.catala_fr +++ b/examples/allocations_familiales/securite_sociale_L.catala_fr @@ -30,49 +30,19 @@ Les prestations familiales comprennent : 9°) l'allocation journalière de présence parentale. /* -déclaration énumération ÉlémentPrestationsFamiliales: - -- PrestationAccueilJeuneEnfant - -- AllocationsFamiliales - -- ComplémentFamilial - -- AllocationLogement - -- AllocationÉducationEnfantHandicapé - -- AllocationSoutienFamilial - -- AllocationRentréeScolaire - -- AllocationJournalièrePresenceParentale +# Voir l'énumération ÉlémentPrestationsFamiliale */ @@Chapitre 2 : Champ d'application@@++++ -@@Début métadonnées@@ -/* -déclaration énumération ÂgeAlternatif: - -- Absent - -- Présent contenu entier - -déclaration champ d'application OuvertureDroitPrestationsFamiliales: - contexte droits_ouverts condition dépend de Enfant - contexte conditions_hors_âge condition dépend de Enfant - contexte plafond_l512_3_2 contenu argent - contexte âge_l512_3_2 contenu entier - contexte âge_l512_3_2_alternatif contenu ÂgeAlternatif - contexte date_courante contenu date - contexte prestation_courante contenu ÉlémentPrestationsFamiliales - contexte résidence contenu Collectivité - contexte smic champ d'application Smic - -champ d'application OuvertureDroitPrestationsFamiliales: - définition smic.résidence égal à résidence -*/ -@@Fin métadonnées@@ - @Article L512-3|LEGIARTI000038834523@ Sous réserve des règles particulières à chaque prestation, ouvre droit aux prestations familiales : 1°) tout enfant jusqu'à la fin de l'obligation scolaire ; /* -champ d'application OuvertureDroitPrestationsFamiliales : - règle droits_ouverts de enfant sous condition +champ d'application PrestationsFamiliales : + règle droit_ouvert de enfant sous condition (date_courante <=@ enfant.fin_obligation_scolaire) conséquence rempli */ @@ -80,7 +50,7 @@ champ d'application OuvertureDroitPrestationsFamiliales : 2°) après la fin de l'obligation scolaire, et jusqu'à un âge limite, tout enfant dont la rémunération éventuelle n'excède pas un plafond. /* -champ d'application OuvertureDroitPrestationsFamiliales : +champ d'application PrestationsFamiliales : # 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 @@ -88,7 +58,7 @@ champ d'application OuvertureDroitPrestationsFamiliales : (enfant.rémuneration_mensuelle <=€ plafond_l512_3_2) conséquence rempli - règle droits_ouverts de enfant sous condition + règle droit_ouvert de enfant sous condition (date_courante >@ enfant.fin_obligation_scolaire) et (conditions_hors_âge de enfant) et (enfant.âge <= âge_l512_3_2) @@ -99,7 +69,7 @@ Toutefois, pour l'attribution du complément familial et de l'allocation de logement mentionnés aux 3° et 4° de l'article L. 511-1 , l'âge limite peut être différent de celui mentionné au 2° du présent article. /* -champ d'application OuvertureDroitPrestationsFamiliales : +champ d'application PrestationsFamiliales : définition âge_l512_3_2 sous condition (selon âge_l512_3_2_alternatif sous forme -- Présent de âge : vrai @@ -119,19 +89,10 @@ champ d'application OuvertureDroitPrestationsFamiliales : @Article L521-1|LEGIARTI000029963006@ Les allocations familiales sont dues à partir du deuxième enfant à charge. /* -# champ d'application CalculAllocationsFamiliales : -# règle allocations_familiales.droits_ouverts sous condition -# nombre de ménage.enfants >= 2 -# conséquence rempli - -# # Les droits doivent être ouverts pour appliquer le champ -# # CalculAllocationsFamiliales. Si cette condition n'est pas remplie, -# # alors il est inutile de calculer le reste -# assertion allocations_familiales.droits_ouverts -# # Le champ d'application CalculAllocationsFamiliales inclus -# # PrestationsFamiliales, mais à condition que la prestation courante -# # soit cohérente -# définition l511_1.prestation_courante égal à AllocationFamiliale +champ d'application AllocationsFamiliales : + règle droit_ouvert_base sous condition + nombre de enfants_à_charge >= 2 + conséquence rempli */ Une allocation forfaitaire par enfant d'un montant fixé par décret est versée @@ -142,24 +103,22 @@ limite mentionné au 2° de l'article L. 512-3 . Cette allocation est versée à la condition que le ou les enfants répondent aux conditions autres que celles de l'âge pour l'ouverture du droit aux allocations familiales. /* -# champ d'application CalculAllocationsFamiliales : -# assertion fixé allocation_forfaitaire.montant_versé par décret +champ d'application AllocationsFamiliales : + assertion fixé montant_versé par décret -# # Ici, l'ouverture du droit aux allocations familiales est conditionné -# # au fait d'avoir deux enfants à charges qui répondent aux conditions -# # d'ouverture du droit à une prestation familiale. Pour cette raison, -# # nous nous référons ici aux conditions_hors_âge de prestations_familiales -# # et non pas de allocations_familiales -# règle allocations_familiales.conditions_hors_âge de enfant sous condition -# prestations_familiales.conditions_hors_âge de enfant -# conséquence rempli + # Ici, l'ouverture du droit aux allocations familiales est conditionné + # au fait d'avoir deux enfants à charges qui répondent aux conditions + # d'ouverture du droit à une prestation familiale. Pour cette raison, + # nous nous référons ici aux conditions_hors_âge de prestations_familiales + règle conditions_hors_âge de enfant sous condition + prestations_familiales.conditions_hors_âge de enfant + conséquence rempli -# règle allocation_forfaitaire.droits_ouverts de enfant sous condition -# (nombre de ménage.enfants >= l512_1.nombre_minimum_enfants) et -# (enfant dans ménage.enfants) et -# (enfant.âge = l512_3.âge_limite_alinéa_2) et -# (allocations_familiales.conditions_hors_âge de enfant) -# conséquence rempli + règle droit_ouvert_forfaitaire de enfant sous condition + (nombre de enfants_à_charge >= nombre_enfants_l512_1) et + (enfant.âge = prestations_familiales.âge_l512_3_2) et + (conditions_hors_âge de enfant) + conséquence rempli */ Le montant des allocations mentionnées aux deux premiers alinéas du présent @@ -167,21 +126,19 @@ article, ainsi que celui des majorations mentionnées à l'article L. 521-3 varient en fonction des ressources du ménage ou de la personne qui a la charge des enfants, selon un barème défini par décret. /* -# champ d'application CalculAllocationsFamiliales : -# assertion fixé allocations_familiales.montant_versé par décret -# assertion varie allocations_familiales.montant_versé avec -# l521_1.ressources_ménage -# assertion fixé majorations_allocations_familiales.montant_versé par décret -# assertion varie majorations_allocations_familiales.montant_versé avec -# l521_1.ressources_ménage +champ d'application AllocationsFamiliales : + assertion fixé montant_versé_base par décret + assertion varie montant_versé_base avec ressources_ménage + assertion fixé montant_versé_majorations par décret + assertion varie montant_versé_majorations avec ressources_ménage */ Le montant des allocations familiales varie en fonction du nombre d'enfants à charge. /* -# champ d'application CalculAllocationsFamiliales : -# assertion varie allocations_familiales.montant_versé avec -# nombre de ménage.enfants +champ d'application AllocationsFamiliales : + assertion varie montant_versé_base.montant_versé avec + nombre de enfants_à_charge */ Les niveaux des plafonds de ressources, qui varient en fonction du nombre @@ -203,24 +160,20 @@ sont définies par décret. # est assez important et nous avons choisi de ne pas l'inclure dans ce # document. -# champ d'application CalculAllocationsFamiliales : -# assertion fixé complément_dégressif.montant_versé par décret +champ d'application AllocationsFamiliales : + assertion fixé montant_versé_complément par décret */ @Article L521-2|LEGIARTI000006743210@ Les allocations sont versées à la personne qui assume, dans quelques conditions que ce soit, la charge effective et permanente de l'enfant. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.charge_par_enfant de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (enfant.prise_en_charge sous forme Complète) -# conséquence égal à Complète +champ d'application AllocationsFamiliales : + étiquette définition_prise_en_compte + définition prise_en_compte de enfant égal à Complète -# définition allocations_familiales.récipiendaire_par_enfant de enfant -# sous condition enfant dans ménage.enfants -# conséquence égal à ménage.parent_en_charge + étiquette définition_versement + définition versement de enfant égal à Normal */ En cas de résidence alternée de l'enfant au domicile de chacun des parents telle @@ -232,47 +185,41 @@ désaccord sur la désignation de l'allocataire. Un décret en Conseil d'Etat fi les conditions d'application du présent alinéa. /* -# champ d'application CalculAllocationsFamiliales : -# # Premier cas : garde alternée, parents désignent un unique allocataire -# règle allocations_garde_alternée.unique_allocataire de enfant sous condition -# (enfant dans ménage.enfants) et -# (enfant.prise_en_charge sous forme GardeAlternée) et -# ((allocations_garde_alternée.choix_allocataire de enfant) -# sous forme Présent) et -# ((allocations_garde_alternée.choix_allocataire de enfant) -> Présent -# sous forme UnParent) et -# (((allocations_garde_alternée.choix_allocataire de enfant) -> Présent -> UnParent) -# dans ménage.parents) -# conséquence rempli +champ d'application AllocationsFamiliales : + # Premier cas : garde alternée, parents désignent un unique allocataire + exception définition_prise_en_compte + définition prise_en_compte de enfant sous condition + selon enfant.garde_alternée sous forme + -- OuiAllocataireUnique: vrai + -- OuiPartageAllocations: faux + -- NonGardeUnique: faux + conséquence égal à Complète -# définition allocations_familiales.charge_par_enfant de enfant -# sous condition allocations_garde_alternée.unique_allocataire de enfant -# conséquence égal à Complète + exception définition_versement + définition versement de enfant sous condition + selon enfant.garde_alternée sous forme + -- OuiAllocataireUnique: vrai + -- OuiPartageAllocations: faux + -- NonGardeUnique: faux + conséquence égal à Normal -# # Deuxième cas : garde alternée, parents partagent la charge pour -# # l'allocation -# règle allocations_garde_alternée.allocataire_double de enfant sous condition -# (enfant dans ménage.enfants) et -# (enfant.prise_en_charge sous forme GardeAlternée) et -# (enfant.choix_allocataire_garde_alternée sous forme Présent) et -# (enfant.choix_allocataire_garde_alternée -> Présent sous forme DeuxParents) -# conséquence rempli + # Deuxième cas : garde alternée, parents partagent la charge pour + # l'allocation + exception définition_prise_en_compte + définition prise_en_compte de enfant sous condition + selon enfant.garde_alternée sous forme + -- OuiPartageAllocations: vrai + -- OuiAllocataireUnique: faux + -- NonGardeUnique: faux + conséquence égal à Partagée -# définition allocations_familiales.charge_par_enfant de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (allocations_garde_alternée.allocataire_double de enfant) -# conséquence égal à Partagée - -# définition allocations_familiales.charge_par_enfant de enfant sous condition -# (enfant dans ménage.enfants) et -# (enfant.prise_en_charge sous forme GardeAlternée) et -# (allocations_garde_alternée.demande_conjointe_partage_charge de enfant ou -# allocations_garde_alternée.desaccord_charge de enfant) -# conséquence égal à Partagée - - -# Quelles variables fixées par R521_2 ? + exception définition_versement + définition versement de enfant sous condition + selon enfant.garde_alternée sous forme + -- OuiPartageAllocations: vrai + -- OuiAllocataireUnique: faux + -- NonGardeUnique: faux + conséquence égal à Partagée */ Lorsque la personne qui assume la charge effective et permanente de l'enfant ne @@ -280,15 +227,7 @@ remplit pas les conditions prévues au titre I du présent livre pour l'ouvertur du droit aux allocations familiales, ce droit s'ouvre du chef du père ou, à défaut, du chef de la mère. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.récipiendaire_par_enfant de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (titre_I.droits_ouverts_allocations_familiales de -# (ménage.parent_en_charge de enfant)) -# conséquence égal à ménage.parent1 - # ménage.parent1 est le père ou à défaut la mère - # (ménage.parent2 est optionnel) +# Non formalisé pour le calcul du montant des allocations */ Lorsqu'un enfant est confié au service d'aide sociale à l'enfance, les @@ -305,18 +244,14 @@ charge morale ou matérielle de l'enfant ou en vue de faciliter le retour de l'enfant dans son foyer. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.charge_par_enfant de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (enfant.confié_service_social) -# conséquence égal à Complète - -# définition allocations_familiales.récipiendaire_par_enfant de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (enfant.confié_service_social) -# conséquence égal à service_social +champ d'application AllocationsFamiliales : + exception définition_versement + définition versement de enfant sous condition + selon enfant.pris_en_charge_par_services_sociaux sous forme + -- OuiAllocationVerséeAuxServicesSociaux: vrai + -- OuiAllocationVerséeÀLaFamille: faux + -- NonPriseEnChargeFamille: faux + conséquence égal à AllocationVerséeAuxServicesSociaux */ Un décret en Conseil d'Etat fixe les conditions d'application du présent @@ -339,26 +274,24 @@ d) enfants confiés à un service public, à une institution privée, à un part l'exception du plus âgé, ouvre droit à partir d'un âge minimum à une majoration des allocations familiales. /* -# champ d'application CalculAllocationsFamiliales : -# règle majorations_allocations_familiales.droits_ouverts de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (enfant != ménage.enfant_plus_âgé) et -# (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) -# conséquence rempli +champ d'application AllocationsFamiliales : + règle droit_ouvert_majoration de enfant + sous condition + (non (est_enfant_le_plus_âgé de enfant)) et + (enfant.âge >= âge_limite_alinéa_1_l521_3 de enfant) + conséquence rempli */ Toutefois, les personnes ayant un nombre déterminé d'enfants à charge bénéficient de ladite majoration pour chaque enfant à charge à partir de l'âge mentionné au premier alinéa. /* -# champ d'application CalculAllocationsFamiliales : -# règle majorations_allocations_familiales.droits_ouverts de enfant -# sous condition -# (enfant dans ménage.enfants) et -# (nombre de ménage.enfants >= l521_3.minimum_alinéa_2) et -# (enfant.âge >= l521_3.âge_limite_alinéa_1 de enfant) -# conséquence rempli +champ d'application AllocationsFamiliales : + règle droit_ouvert_majoration de enfant + sous condition + (nombre de enfants_à_charge >= nombre_enfants_alinéa_2_l521_3) et + (enfant.âge >= âge_limite_alinéa_1_l521_3 de enfant) + conséquence rempli */ @@Titre 5 : Dispositions communes@@+++ @@ -371,14 +304,13 @@ mensuelles de calcul revalorisées au 1er avril de chaque année par application du coefficient mentionné à l'article L. 161-25 . /* # Idem que L521-1, on ne formalise pas ici l'évolution de la BMPA -# champ d'application PrestationsFamiliales : -# assertion fixé prestations_familiales.base_mensuelle par décret +champ d'application PrestationsFamiliales : + assertion fixé prestations_familiales.base_mensuelle par décret */ @@Livre 7 : Régimes divers - Dispositions diverses@@++ -@@Titre 5 : Dispositions particulières à la Guadeloupe, à la Guyane, à la -Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin@@+++ +@@Titre 5 : Dispositions particulières à la Guadeloupe, à la Guyane, à la Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin@@+++ @@Chapitre 1er : Généralités@@++++ @@ -388,15 +320,15 @@ en Martinique, à La Réunion, à Saint-Barthélemy et à Saint-Martin à l'ensemble des bénéficiaires de la législation générale de sécurité sociale, y compris les membres des professions agricoles. /* -# champ d'application CalculPrestationsFamiliales : -# règle l751_1.régime_outre_mer sous condition -# (ménage.résidence = Guadeloupe) ou -# (ménage.résidence = Guyane) ou -# (ménage.résidence = Martinique) ou -# (ménage.résidence = LaRéunion) ou -# (ménage.résidence = SaintBarthélemy) ou -# (ménage.résidence = SaintMartin) -# conséquence rempli +champ d'application PrestationsFamiliales : + règle régime_outre_mer_l751_1 sous condition + (résidence = Guadeloupe) ou + (résidence = Guyane) ou + (résidence = Martinique) ou + (résidence = LaRéunion) ou + (résidence = SaintBarthélemy) ou + (résidence = SaintMartin) + conséquence rempli */ @@Chapitre 5 : Prestations familiales et prestations assimilées@@++++ @@ -410,9 +342,7 @@ La base de calcul des prestations familiales est la même que celle qui est fixée en application de l'article L. 551-1 . /* -# champ d'application CalculPrestationsFamiliales : -# définition prestations_familiales.base_mensuelle_dom égal à -# prestations_familiales.base_mensuelle +# Aucun changement dans le code, puisque les articles restent applicables */ @Article L755-11|LEGIARTI000031323803@ @@ -430,11 +360,11 @@ longtemps que le présent chapitre V est applicable. Les allocations familiales sont dues, pour tout enfant, à la personne qui a effectivement la charge de celui-ci. /* -# champ d'application CalculAllocationsFamiliales : -# règle allocations_familiales.droits_ouverts sous condition -# (l751_1.régime_outre_mer) et -# (nombre de ménage.enfants >= 1) -# conséquence rempli +champ d'application AllocationsFamiliales: + règle droit_ouvert_base sous condition + prestations_familiales.régime_outre_mer_l751_1 et + (nombre de enfants_à_charge >= 1) + conséquence rempli */ Toutefois, les quatre derniers alinéas de l'article L. 521-1 ne sont pas applicables lorsque le ménage ou la personne a un seul enfant à charge. @@ -442,16 +372,14 @@ applicables lorsque le ménage ou la personne a un seul enfant à charge. # Ceci concerne l'ouverture du droit à l'allocation forfaitaire # et au complément dégressif. -# champ d'application CalculAllocationsFamiliales : -# règle allocation_forfaitaire.droits_ouverts de enfant sous condition -# (l751_1.régime_outre_mer) et -# (nombre de ménage.enfants = 1) -# conséquence non rempli +champ d'application AllocationsFamiliales : + règle droit_ouvert_forfaitaire de enfant sous condition + prestations_familiales.régime_outre_mer_l751_1 et + (nombre de enfants_à_charge = 1) + conséquence non rempli -# règle -# complément_dégressif.droits_ouvert de allocation -# sous condition -# (l751_1.régime_outre_mer) et -# (nombre de ménage.enfants = 1) -# conséquence non rempli + règle droit_ouvert_complément sous condition + prestations_familiales.régime_outre_mer_l751_1 et + (nombre de enfants_à_charge = 1) + conséquence non rempli */ diff --git a/examples/allocations_familiales/securite_sociale_R.catala_fr b/examples/allocations_familiales/securite_sociale_R.catala_fr index 23022496..2ee905bc 100644 --- a/examples/allocations_familiales/securite_sociale_R.catala_fr +++ b/examples/allocations_familiales/securite_sociale_R.catala_fr @@ -11,7 +11,7 @@ Les enfants ouvrent droit aux prestations familiales jusqu'à l'âge de vingt ans sous réserve que leur rémunération n'excède pas le plafond fixé au deuxième alinéa du présent article. /* -champ d'application OuvertureDroitPrestationsFamiliales : +champ d'application PrestationsFamiliales : définition âge_l512_3_2 égal à 20 */ @@ -20,7 +20,7 @@ un mois, à 55 % du salaire minimum interprofessionnel de croissance défini aux articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169. /* -champ d'application OuvertureDroitPrestationsFamiliales : +champ d'application PrestationsFamiliales : définition plafond_l512_3_2 égal à (smic.brut_horaire *€ 55 %) *€ 169,0 */ @@ -42,15 +42,15 @@ L'âge mentionné au premier alinéa de l'article L. 521-3 à partir duquel les enfants ouvrent droit à la majoration des allocations familiales est fixé à 14 ans. /* -# champ d'application CalculAllocationsFamiliales : -# définition l521_3.âge_limite_alinéa_1 de enfant égal à 14 an +champ d'application AllocationsFamiliales : + définition âge_limite_alinéa_1_l521_3 de enfant égal à 14 */ Le nombre minimum d'enfants à charge, mentionné au deuxième alinéa de l'article L. 521-3 ouvrant droit à ladite majoration pour chaque enfant est fixé à trois. /* -# champ d'application CalculAllocationsFamiliales : -# définition l521_3.minimum_alinéa_2 égal à 3 +champ d'application AllocationsFamiliales : + définition nombre_enfants_alinéa_2_l521_3 égal à 3 */ NOTA : Décret n° 2008-409 du 28 avril 2008 JORF du 29 avril 2008 art. 2 : Les @@ -61,15 +61,15 @@ le onzième anniversaire est postérieur au 30 avril 2008. # version du corpus législatif dont un morceau s'applique encore. Nous avons # choisi de montrer ce vieux champ d'application ici plutôt qu'à côté du texte # du décret de 2008 pour des raisons de place seulement. -# champ d'application CalculAllocationFamilialesAvril2008: -# # Âge limite avant décret n° 2008-409 du 28 avril 2008 -# définition l521_3.minimum_alinéa_2 de enfant égal à 16 an +champ d'application AllocationFamilialesAvril2008: + # Âge limite avant décret n° 2008-409 du 28 avril 2008 + définition âge_limite_alinéa_1_l521_3 égal à 16 -# champ d'application CalculAllocationsFamiliales : -# définition l521_3.minimum_alinéa_2 de enfant -# sous condition (enfant.date_naissance + 11 an <= |30/04/2008|) -# conséquence égal à -# calcul_avril_2008.l521_3.minimum_alinéa_2 de enfant +champ d'application AllocationsFamiliales : + définition âge_limite_alinéa_1_l521_3 de enfant + sous condition (enfant.date_de_naissance +@ 11 an <=@ |30/04/2008|) + conséquence égal à + version_avril_2008.âge_limite_alinéa_1_l521_3 */ @Article R521-2|LEGIARTI000006750608@ Dans les situations visées au deuxième alinéa de l'article L. 521-2 , @@ -84,19 +84,6 @@ une demande conjointe de partage. /* # Le fait que l'allocataire dans le cas d'un commun accord soit celui des # deux parents désigné par l'accord est déjà modélisé dans L512-2. - -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.charge_par_enfant de enfant sous condition -# (enfant dans ménage.enfants) et -# (enfant.prise_en_charge sous forme GardeAlternée) et -# ( -# (allocations_garde_alternée.demande_conjointe_partage_charge) ou -# ( -# (non allocations_garde_alternée.demande_conjointe_partage_charge) et -# (enfant.choix_allocataire_garde_alternée sous forme Absent) -# ) -# ) -# conséquence égal à Partagée */ Lorsque les parents ont désigné un allocataire unique ou fait une demande diff --git a/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr index 56b946fe..f7c17485 100644 --- a/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr +++ b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr @@ -4,31 +4,43 @@ /* déclaration champ d'application Test1: - contexte f champ d'application OuvertureDroitPrestationsFamiliales + contexte f champ d'application PrestationsFamiliales champ d'application Test1: définition f.âge_l512_3_2_alternatif égal à Absent - définition f.date_courante égal à |01/01/2020| + définition f.date_courante égal à |01/05/2020| définition f.prestation_courante égal à AllocationsFamiliales définition f.résidence égal à Métropole - assertion (f.droits_ouverts de Enfant { - -- fin_obligation_scolaire : |01/08/2021| + assertion (f.droit_ouvert de Enfant { + -- fin_obligation_scolaire : |01/08/2023| + -- date_de_naissance: |01/01/2007| -- âge: 13 -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique }) - assertion (non (f.droits_ouverts de Enfant { + assertion (non (f.droit_ouvert de Enfant { -- fin_obligation_scolaire : |01/08/2019| - -- âge: 17 + -- date_de_naissance: |01/01/2003| + -- âge: 18 -- rémuneration_mensuelle: 1000€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique })) - assertion (f.droits_ouverts de Enfant { + assertion (f.droit_ouvert de Enfant { -- fin_obligation_scolaire : |01/08/2019| - -- âge: 17 + -- date_de_naissance: |01/01/2003| + -- âge: 18 -- rémuneration_mensuelle: 400€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique }) - assertion (non (f.droits_ouverts de Enfant { - -- fin_obligation_scolaire : |01/08/2019| + assertion (non (f.droit_ouvert de Enfant { + -- fin_obligation_scolaire : |01/08/2016| + -- date_de_naissance: |01/01/1999| -- âge: 21 -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique })) */ \ No newline at end of file diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index b7821a43..f16caf8c 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -515,11 +515,11 @@ let process_default (ctxt : Name_resolution.context) (scope : Scopelang.Ast.Scop | Scopelang.Ast.TArrow (t_in, _), Some param_uid -> Some (Pos.unmark param_uid, t_in) | Scopelang.Ast.TArrow _, None -> Errors.raise_spanned_error - "this definition has a function type but the parameter is missing" + "This definition has a function type but the parameter is missing" (Pos.get_position (Bindlib.unbox cons)) | _, Some _ -> Errors.raise_spanned_error - "this definition has a parameter but its type is not a function" + "This definition has a parameter but its type is not a function" (Pos.get_position (Bindlib.unbox cons)) | _ -> None); exception_to_rule; diff --git a/src/catala/scope_language/scope_to_dcalc.ml b/src/catala/scope_language/scope_to_dcalc.ml index 41a771b3..17a7cf1c 100644 --- a/src/catala/scope_language/scope_to_dcalc.ml +++ b/src/catala/scope_language/scope_to_dcalc.ml @@ -92,8 +92,8 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po try Ast.StructFieldMap.find field_name e_fields with Not_found -> Errors.raise_spanned_error - (Format.asprintf "The field %a does not belong to the structure %a" - Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) + (Format.asprintf "Missing field for structure %a: \"%a\"" + Ast.StructName.format_t struct_name Ast.StructFieldName.format_t field_name) (Pos.get_position e) in let field_d = translate_expr ctx field_e in @@ -107,8 +107,8 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po in if Ast.StructFieldMap.cardinal remaining_e_fields > 0 then Errors.raise_spanned_error - (Format.asprintf "Missing fields for structure %a: %a" Ast.StructName.format_t - struct_name + (Format.asprintf "The fields \"%a\" do not belong to the structure %a" + Ast.StructName.format_t struct_name (Format.pp_print_list ~pp_sep:(fun fmt () -> Format.fprintf fmt ", ") (fun fmt (field_name, _) -> @@ -123,7 +123,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po try List.assoc field_name (List.mapi (fun i (x, y) -> (x, (y, i))) struct_sig) with Not_found -> Errors.raise_spanned_error - (Format.asprintf "The field %a does not belong to the structure %a" + (Format.asprintf "The field \"%a\" does not belong to the structure %a" Ast.StructFieldName.format_t field_name Ast.StructName.format_t struct_name) (Pos.get_position e) in @@ -138,7 +138,7 @@ let rec translate_expr (ctx : ctx) (e : Ast.expr Pos.marked) : Dcalc.Ast.expr Po try List.assoc constructor (List.mapi (fun i (x, y) -> (x, (y, i))) enum_sig) with Not_found -> Errors.raise_spanned_error - (Format.asprintf "The constructor %a does not belong to the enum %a" + (Format.asprintf "The constructor \"%a\" does not belong to the enum %a" Ast.EnumConstructor.format_t constructor Ast.EnumName.format_t enum_name) (Pos.get_position e) in From e94356bd0b4c7e92b88ede529f23e916787e2bd7 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Mon, 4 Jan 2021 00:13:59 +0100 Subject: [PATCH 139/142] First working prototype of allocations familiales implementation --- examples/Makefile | 2 +- .../allocations_familiales/metadata.catala_fr | 73 ++- .../securite_sociale_D.catala_fr | 329 +++++++------- .../securite_sociale_L.catala_fr | 4 +- .../securite_sociale_R.catala_fr | 65 ++- .../tests_allocations_familiales.catala_fr | 70 +++ .../tests/tests_ouverture_droits.catala_fr | 77 ++-- src/catala/catala_surface/ast.ml | 7 +- src/catala/catala_surface/desugaring.ml | 26 +- src/catala/catala_surface/lexer.ml | 12 + src/catala/catala_surface/lexer_en.ml | 12 + src/catala/catala_surface/lexer_fr.ml | 12 + src/catala/catala_surface/parser.messages | 418 +++++++++--------- src/catala/catala_surface/parser.mly | 6 + src/catala/catala_surface/parser_errors.ml | 238 +++++----- src/catala/default_calculus/ast.ml | 1 + src/catala/default_calculus/interpreter.ml | 1 + src/catala/default_calculus/print.ml | 5 +- src/catala/default_calculus/typing.ml | 1 + src/catala/driver.ml | 9 +- 20 files changed, 784 insertions(+), 584 deletions(-) create mode 100644 examples/allocations_familiales/tests/tests_allocations_familiales.catala_fr diff --git a/examples/Makefile b/examples/Makefile index 3dd08560..a14778fa 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -13,7 +13,7 @@ RESET := $(shell tput -Txterm sgr0) # Running legislation unit tests ################################ -# Usage `make ..` +# Usage `make ...run` # This Makefile rule assumes the following directory structure: # foo_example # tests/ diff --git a/examples/allocations_familiales/metadata.catala_fr b/examples/allocations_familiales/metadata.catala_fr index 28b1a7b7..d5ce3b4e 100644 --- a/examples/allocations_familiales/metadata.catala_fr +++ b/examples/allocations_familiales/metadata.catala_fr @@ -78,37 +78,102 @@ champ d'application PrestationsFamiliales: déclaration champ d'application AllocationFamilialesAvril2008: contexte âge_limite_alinéa_1_l521_3 contenu entier +déclaration énumération StockageEnfant: + -- PasEnfant + -- UnEnfant contenu Enfant + +déclaration champ d'application EnfantLePlusÂgé: + contexte enfants contenu collection Enfant + contexte est_le_plus_âgé contenu booléen dépend de Enfant + +champ d'application EnfantLePlusÂgé: + définition est_le_plus_âgé de enfant égal à + faux # TODO: changer! + déclaration champ d'application AllocationsFamiliales: contexte enfants_à_charge contenu collection Enfant + contexte date_courante contenu date + contexte résidence contenu Collectivité contexte ressources_ménage contenu argent contexte prise_en_compte contenu PriseEnCompteÉvaluationMontant dépend de Enfant contexte versement contenu VersementAllocations dépend de Enfant + contexte montant_versé contenu argent + contexte droit_ouvert_base condition contexte droit_ouvert_majoration condition dépend de Enfant contexte montant_versé_base contenu argent + contexte montant_avec_garde_alternée_base contenu argent + contexte montant_initial_base contenu argent + contexte montant_initial_base_premier_enfant contenu argent + contexte montant_initial_base_deuxième_enfant contenu argent + contexte montant_initial_base_troisième_enfant_et_plus contenu argent + contexte rapport_enfants_total_moyen contenu décimal + contexte nombre_moyen_enfants contenu décimal + contexte nombre_total_enfants contenu décimal contexte droit_ouvert_forfaitaire condition dépend de Enfant contexte montant_versé_forfaitaire contenu argent - contexte montant_versé_majorations contenu argent + contexte montant_versé_majoration contenu argent + contexte montant_avec_garde_alternée_majoration contenu argent dépend de Enfant + contexte montant_initial_majoration contenu argent dépend de Enfant contexte droit_ouvert_complément condition - contexte montant_versé_complément contenu argent + contexte montant_versé_complément_pour_base_et_majoration contenu argent + contexte montant_base_complément_pour_base_et_majoration contenu argent + contexte montant_versé_complément_pour_forfaitaire contenu argent + contexte dépassement_plafond_ressources contenu argent dépend de argent contexte prestations_familiales champ d'application PrestationsFamiliales contexte version_avril_2008 champ d'application AllocationFamilialesAvril2008 - contexte conditions_hors_âge condition dépend de Enfant + contexte enfant_le_plus_âgé champ d'application EnfantLePlusÂgé - contexte nombre_enfants_l512_1 contenu entier + contexte conditions_hors_âge condition dépend de Enfant + contexte nombre_enfants_l521_1 contenu entier contexte âge_limite_alinéa_1_l521_3 contenu entier dépend de Enfant contexte nombre_enfants_alinéa_2_l521_3 contenu entier contexte est_enfant_le_plus_âgé contenu booléen dépend de Enfant + contexte plafond_I_d521_3 contenu argent + contexte plafond_II_d521_3 contenu argent + + +## Code non défini dans la loi +champ d'application PrestationsFamiliales: + définition âge_l512_3_2_alternatif égal à Absent champ d'application AllocationsFamiliales: définition prestations_familiales.prestation_courante égal à AllocationsFamiliales + définition prestations_familiales.date_courante égal à + date_courante + définition prestations_familiales.résidence égal à + résidence + + assertion (pour tout enfant dans enfants_à_charge on a + prestations_familiales.droit_ouvert de enfant) + + définition enfant_le_plus_âgé.enfants égal à enfants_à_charge + définition est_enfant_le_plus_âgé de enfant égal à + enfant_le_plus_âgé.est_le_plus_âgé de enfant + + définition montant_versé_base égal à + si droit_ouvert_base alors montant_avec_garde_alternée_base sinon 0€ + définition montant_versé_majoration égal à + si droit_ouvert_base alors + somme argent pour enfant dans enfants_à_charge de + montant_avec_garde_alternée_majoration de enfant + sinon 0€ + + définition montant_versé égal à + si droit_ouvert_base alors + montant_versé_base +€ + montant_versé_majoration +€ + montant_versé_forfaitaire +€ + montant_versé_complément_pour_base_et_majoration +€ + montant_versé_complément_pour_forfaitaire + sinon 0€ */ @@Fin métadonnées@@ diff --git a/examples/allocations_familiales/securite_sociale_D.catala_fr b/examples/allocations_familiales/securite_sociale_D.catala_fr index d8c8dd18..a0a28dd1 100644 --- a/examples/allocations_familiales/securite_sociale_D.catala_fr +++ b/examples/allocations_familiales/securite_sociale_D.catala_fr @@ -13,12 +13,11 @@ familiales et de la majoration pour âge prévue à l'article L. 521-3 est défini selon le barème suivant : /* # Composantes des allocations familiales -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.base sous condition -# allocations_familiales.droits_ouverts -# conséquence égal à -# allocations_familiales.montant_deuxieme_enfant + -# allocations_familiales.montant_troisième_enfant_et_plus +champ d'application AllocationsFamiliales : + étiquette définition_montant_initial_base + définition montant_initial_base égal à + montant_initial_base_deuxième_enfant +€ + montant_initial_base_troisième_enfant_et_plus */ 1° Lorsque le ménage ou la personne a disposé d'un montant de ressources inférieur ou égal au plafond défini au I de l'article D. 521-3, les taux @@ -26,37 +25,37 @@ servant au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 32 % pour le deuxième enfant à charge ; /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_deuxieme_enfant sous condition -# l521_1.ressources_ménage <= d521_3.plafond_I -# conséquence égal à -# si nombre de ménage.enfants >= 2 -# alors prestations_familiales.base_mensuelle * 32 % -# sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_deuxième_enfant sous condition + ressources_ménage <=€ plafond_I_d521_3 + conséquence égal à + si nombre de enfants_à_charge >= 2 + alors prestations_familiales.base_mensuelle *€ 32 % + sinon 0 € */ b) 41 % pour le troisième enfant à charge et chacun des suivants. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_troisième_enfant_et_plus -# sous condition -# l521_1.ressources_ménage <= d521_3.plafond_I -# conséquence égal à -# si nombre de ménage.enfants >= 3 -# alors prestations_familiales.base_mensuelle * 41 % * ( -# (nombre de ménage.enfants) - 2 -# ) sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_troisième_enfant_et_plus + sous condition + ressources_ménage <=€ plafond_I_d521_3 + conséquence égal à + si nombre de enfants_à_charge >= 3 + alors (prestations_familiales.base_mensuelle *€ 41 %) *€ ( + entier_vers_décimal de ((nombre de enfants_à_charge) - 2) + ) sinon 0 € */ La majoration pour âge est fixée à 16 % de la base mensuelle de calcul des prestations familiales ; /* -# champ d'application CalculAllocationsFamiliales : -# définition -# majorations_allocations_familiales.base_par_enfant de enfant -# sous condition -# l521_1.ressources_ménage <= d521_3.plafond_I -# conséquence égal à -# prestations_familiales.base_mensuelle * 16 % +champ d'application AllocationsFamiliales : + définition montant_initial_majoration de enfant + sous condition + ressources_ménage <=€ plafond_I_d521_3 et + (nombre de enfants_à_charge >= 2) + conséquence égal à + prestations_familiales.base_mensuelle *€ 16 % */ 2° Lorsque le ménage ou la personne a disposé d'un montant de ressources supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal @@ -65,39 +64,38 @@ allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 16 % pour le deuxième enfant à charge ; /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_deuxieme_enfant sous condition -# (l521_1.ressources_ménage > d521_3.plafond_I) et -# (l521_1.ressources_ménage <= d521_3.plafond_II) -# conséquence égal à -# si nombre de ménage.enfants >= 2 -# alors prestations_familiales.base_mensuelles * 32 % -# sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_deuxième_enfant sous condition + (ressources_ménage >€ plafond_I_d521_3) et + (ressources_ménage <=€ plafond_II_d521_3) + conséquence égal à + si nombre de enfants_à_charge >= 2 + alors prestations_familiales.base_mensuelle *€ 32 % + sinon 0 € */ b) 20,5 % pour le troisième enfant à charge et chacun des suivants. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_troisième_enfant_et_plus -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_I) et -# (l521_1.ressources_ménage <= d521_3.plafond_II) -# conséquence égal à -# si nombre de ménage.enfants >= 3 -# alors prestations_familiales.base_mensuelle * 20,5 % * ( -# (nombre de ménage.enfants) - 2 -# ) sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_troisième_enfant_et_plus + sous condition + (ressources_ménage >€ plafond_I_d521_3) et + (ressources_ménage <=€ plafond_II_d521_3) + conséquence égal à + si nombre de enfants_à_charge >= 3 + alors (prestations_familiales.base_mensuelle *€ 20,5 %) *€ ( + entier_vers_décimal de ((nombre de enfants_à_charge) - 2) + ) sinon 0 € */ La majoration pour âge est fixée à 8 % de la base mensuelle de calcul des prestations familiales ; /* -# champ d'application CalculAllocationsFamiliales : -# définition -# majorations_allocations_familiales.base_par_enfant de enfant -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_I) et -# (l521_1.ressources_ménage <= d521_3.plafond_II) -# conséquence égal à -# prestations_familiales.base_mensuelle * 8 % +champ d'application AllocationsFamiliales : + définition montant_initial_majoration de enfant sous condition + (ressources_ménage >€ plafond_I_d521_3) et + (ressources_ménage <=€ plafond_II_d521_3) et + (nombre de enfants_à_charge >= 2) + conséquence égal à + prestations_familiales.base_mensuelle *€ 8 % */ 3° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -106,36 +104,35 @@ au calcul des allocations familiales sont fixés, en pourcentage de la base mensuelle prévue à l'article L. 551-1, à : a) 8 % pour le deuxième enfant à charge ; /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_deuxieme_enfant sous condition -# (l521_1.ressources_ménage > d521_3.plafond_II) -# conséquence égal à -# si nombre de ménage.enfants >= 2 -# alors prestations_familiales.base_mensuelle * 8 % -# sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_deuxième_enfant sous condition + (ressources_ménage >€ plafond_II_d521_3) + conséquence égal à + si nombre de enfants_à_charge >= 2 + alors prestations_familiales.base_mensuelle *€ 8 % + sinon 0 € */ b) 10,25 % pour le troisième enfant à charge et chacun des suivants. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.montant_troisième_enfant_et_plus -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_II) -# conséquence égal à -# si nombre de ménage.enfants >= 3 -# alors prestations_familiales.base_mensuelle * 10,25 % * ( -# (nombre de ménage.enfants) - 2 -# ) sinon 0 € +champ d'application AllocationsFamiliales : + définition montant_initial_base_troisième_enfant_et_plus + sous condition + (ressources_ménage >€ plafond_II_d521_3) + conséquence égal à + si nombre de enfants_à_charge >= 3 + alors (prestations_familiales.base_mensuelle *€ 10,25 %) *€ ( + entier_vers_décimal de ((nombre de enfants_à_charge) - 2) + ) sinon 0 € */ La majoration pour âge est fixée à 4 % de la base mensuelle de calcul des prestations familiales. /* -# champ d'application CalculAllocationsFamiliales : -# définition -# majorations_allocations_familiales.base_par_enfant de enfant -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_II) -# conséquence égal à -# prestations_familiales.base_mensuelle * 4 % +champ d'application AllocationsFamiliales : + définition montant_initial_majoration de enfant sous condition + (ressources_ménage >€ plafond_II_d521_3) et + (nombre de enfants_à_charge >= 2) + conséquence égal à + prestations_familiales.base_mensuelle *€ 4 % */ II.-En application du sixième alinéa de l'article L. 521-1, le montant @@ -150,42 +147,33 @@ Ce complément dégressif est égal, pour chaque mois, au douzième de la différence entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. /* -# champ d'application CalculAllocationsFamiliales : -# définition complément_dégressif.dépassement de allocation -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_I) et -# (l521_1.ressources_ménage <= d521_3.plafond_I + 12 * allocation) -# conséquence égal à -# d521_3.plafond_I + 12 * allocation - l521_1.ressources_ménage +champ d'application AllocationsFamiliales : + exception base_dépassement + définition dépassement_plafond_ressources de allocation + sous condition + (ressources_ménage >€ plafond_I_d521_3) et + (ressources_ménage <=€ plafond_I_d521_3 +€ allocation *€ 12,0 ) + conséquence égal à + plafond_I_d521_3 +€ allocation *€ 12,0 -€ ressources_ménage -# définition complément_dégressif.dépassement de allocation -# sous condition -# (l521_1.ressources_ménage > d521_3.plafond_II) et -# (l521_1.ressources_ménage <= d521_3.plafond_II + 12 * allocation) -# conséquence égal à -# d521_3.plafond_II + 12 * allocation - l521_1.ressources_ménage + exception base_dépassement + définition dépassement_plafond_ressources de allocation + sous condition + (ressources_ménage >€ plafond_II_d521_3) et + (ressources_ménage <=€ plafond_II_d521_3 +€ allocation *€ 12,0) + conséquence égal à + plafond_II_d521_3 +€ allocation *€ 12,0 -€ ressources_ménage -# # Dans les autres cas, le dépassement est nul -# définition complément_dégressif.dépassement de allocations égal à 0 € + # Dans les autres cas, le dépassement est nul + étiquette base_dépassement + définition dépassement_plafond_ressources de allocations égal à 0 € -# règle complément_dégressif.droits_ouverts de allocation -# sous condition complément_dégressif.dépassement de allocation > 0 € -# conséquence rempli + définition montant_versé_complément_pour_base_et_majoration égal à + (dépassement_plafond_ressources de + montant_base_complément_pour_base_et_majoration) *€ (1,0 /. 12,0) -# définition -# complément_dégressif.pour_allocations_familiales_et_majorations -# sous condition complément_dégressif.droits_ouverts de complément_dégressif.base -# conséquence égal à -# (complément_dégressif.dépassement de complément_dégressif.base) / 12 - -# définition complément_dégressif.base -# égal à -# (si allocations_familiales.droits_ouverts alors -# allocations_familiales.montant_versé -# sinon 0 €) + -# (si majorations_allocations_familiales.droits_ouverts alors -# majorations_allocations_familiales.montant_versé -# sinon 0 €) + définition montant_base_complément_pour_base_et_majoration égal à + montant_versé_base +€ montant_versé_majoration */ @Article D521-2|LEGIARTI000030680324@ @@ -197,13 +185,13 @@ inférieur ou égal au plafond défini au I de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 20,234 % de la base mensuelle de calcul des allocations familiales par enfant ; /* -# champ d'application CalculAllocationsFamiliales : -# définition allocation_forfaitaire.montant_versé sous condition -# l521_1.ressources_ménage <= d521_3.plafond_I -# conséquence égal à -# prestations_familiales.base_mensuelle * 20,234 % * -# nombre pour enfant dans ménage.enfants de -# allocation_forfaitaire.droits_ouverts de enfant +champ d'application AllocationsFamiliales : + définition montant_versé_forfaitaire sous condition + ressources_ménage <=€ plafond_I_d521_3 + conséquence égal à + (prestations_familiales.base_mensuelle *€ 20,234 %) *€ + entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de + droit_ouvert_forfaitaire de enfant) */ 2° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -212,14 +200,14 @@ supérieur au plafond défini au I de l'article D. 521-3 et inférieur ou égal forfaitaire est fixé à 10,117 % de la base mensuelle de calcul des allocations familiales par enfant ; /* -# champ d'application CalculAllocationsFamiliales : -# définition allocation_forfaitaire.montant_versé sous condition -# (l521_1.ressources_ménage > d521_3.plafond_I) et -# (l521_1.ressources_ménage <= d521_3.plafond_II) -# conséquence égal à -# prestations_familiales.base_mensuelle * 10,117 % * -# nombre pour enfant dans ménage.enfants de -# allocation_forfaitaire.droits_ouvert de enfant +champ d'application AllocationsFamiliales : + définition montant_versé_forfaitaire sous condition + (ressources_ménage >€ plafond_I_d521_3) et + (ressources_ménage <=€ plafond_II_d521_3) + conséquence égal à + (prestations_familiales.base_mensuelle *€ 10,117 %) *€ + entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de + droit_ouvert_forfaitaire de enfant) */ 3° Lorsque le ménage ou la personne a disposé d'un montant de ressources @@ -227,13 +215,13 @@ supérieur au plafond défini au II de l'article D. 521-3, le montant mensuel de l'allocation forfaitaire est fixé à 5,059 % de la base mensuelle de calcul des allocations familiales par enfant. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocation_forfaitaire.montant_versé sous condition -# l521_1.ressources_ménage > d521_3.plafond_II -# conséquence égal à -# prestations_familiales.base_mensuelle * 5,059 % * -# nombre pour enfant dans ménage.enfants de -# allocation_forfaitaire.droits_ouvert de enfant +champ d'application AllocationsFamiliales : + définition montant_versé_forfaitaire sous condition + ressources_ménage >€ plafond_II_d521_3 + conséquence égal à + (prestations_familiales.base_mensuelle *€ 5,059 %) *€ + entier_vers_décimal de (nombre pour enfant dans enfants_à_charge de + droit_ouvert_forfaitaire de enfant) */ II.-En application du sixième alinéa de l'article L. 521-1, le montant mensuel @@ -245,22 +233,17 @@ Ce complément dégressif est égal, pour chaque mois, au douzième de la diffé entre, d'une part, ce plafond de ressources majoré de la somme définie à l'alinéa précédent et, d'autre part, le montant des ressources. /* -# champ d'application CalculAllocationsFamiliales : -# définition -# complément_dégressif.pour_allocation_forfaitaire -# sous condition -# allocation_forfaitaire.droits_ouverts et -# complément_dégressif.droits_ouverts de allocation_forfaitaire.droits_ouverts -# conséquence égal à -# (complément_dégressif.dépassement -# de allocation_forfaitaire.montant_versé) / 12 +champ d'application AllocationsFamiliales : + définition montant_versé_complément_pour_forfaitaire égal à + (dépassement_plafond_ressources de montant_versé_forfaitaire) *€ + (1,0 /. 12,0) */ III.-Le nombre minimum d'enfants à charge mentionné au deuxième alinéa de l'article L. 521-1 est fixé à trois. /* -# champ d'application CalculAllocationsFamiliales : -# définition l521_1.nombre_minimum_enfants égal à 3 +champ d'application AllocationsFamiliales : + définition nombre_enfants_l521_1 égal à 3 */ @Article D521-3|LEGIARTI000030678079@ @@ -268,17 +251,17 @@ l'article L. 521-1 est fixé à trois. I.-Le plafond prévu au 1° du I des articles D. 521-1 et D. 521-2 est fixé à 55 950 euros. Il est majoré de 5 595 euros par enfant à charge. /* -# champ d'application CalculAllocationsFamiliales : -# définition d521_3.plafond_I égal à 55 950 € + -# 5 595 € * nombre de ménage.enfants +champ d'application AllocationsFamiliales : + définition plafond_I_d521_3 égal à 55 950 € +€ + 5 595 € *€ (entier_vers_décimal de (nombre de enfants_à_charge)) */ II.-Le plafond prévu au 2° du I des articles D. 521-1 et D. 521-2 est fixé à 78 300 euros. Il est majoré de 5 595 euros par enfant à charge. /* -# champ d'application CalculAllocationsFamiliales : -# définition d521_3.plafond_II égal à 78 300 € + -# 5 595 € * nombre de ménage.enfants +champ d'application AllocationsFamiliales : + définition plafond_II_d521_3 égal à 78 300 € +€ + 5 595 € *€ (entier_vers_décimal de (nombre de enfants_à_charge)) */ III.-Les montants des plafonds et de leur majoration respective fixés au présent @@ -308,20 +291,17 @@ fixé à 5,88 p. 100 de la base mensuelle prévue à l'article L. 755-3. /* # Composantes des allocations familiales -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.base sous condition -# l751_1.régime_outre_mer et -# allocations_familiales.droits_ouverts -# conséquence égal à -# si nombre de ménage.enfants = 1 alors -# allocations_familiales.montant_premier_enfant -# sinon ( -# allocations_familiales.montant_deuxieme_enfant + -# allocations_familiales.montant_troisième_enfant_et_plus -# ) +champ d'application AllocationsFamiliales : + + exception définition_montant_initial_base + définition montant_initial_base sous condition + prestations_familiales.régime_outre_mer_l751_1 et + nombre de enfants_à_charge = 1 + conséquence égal à + montant_initial_base_premier_enfant -# définition allocations_familiales.montant_premier_enfant égal à -# prestations_familiales.base_mensuelle_dom * 5,88 % + définition montant_initial_base_premier_enfant égal à + prestations_familiales.base_mensuelle *€ 5,88 % # Question : le complément dégressif s'applique-t-il ici ? Car le complément # est basé sur les plafonds du taux de base qui ne s'appliquent pas ici, @@ -331,16 +311,17 @@ La majoration des allocations familiales pour un seul enfant à charge est fixée à 3,69 p. 100 de la base mensuelle prévue à l'article L. 755-3 à partir de onze ans et à 5,67 p. 100 à partir de seize ans. /* -# champ d'application CalculAllocationsFamiliales : -# définition l521_3.âge_limite_alinéa_1 de enfant -# sous condition l751_1.régime_outre_mer -# conséquence égal à 11 an -# définition -# majorations_allocations_familiales.base_par_enfant de enfant -# sous condition -# l751_1.régime_outre_mer et -# (majorations_allocations_familiales.droits_ouverts de enfant) -# conséquence égal à -# prestations_familiales.base_mensuelle_dom * -# (si enfant.âge >= 16 an alors 5,67 % sinon 3,69 %) +champ d'application AllocationsFamiliales : + définition âge_limite_alinéa_1_l521_3 de enfant + sous condition prestations_familiales.régime_outre_mer_l751_1 + conséquence égal à 11 + + définition + montant_initial_majoration de enfant + sous condition + prestations_familiales.régime_outre_mer_l751_1 et + (nombre de enfants_à_charge = 1) + conséquence égal à + prestations_familiales.base_mensuelle *€ + (si enfant.âge >= 16 alors 5,67 % sinon 3,69 %) */ diff --git a/examples/allocations_familiales/securite_sociale_L.catala_fr b/examples/allocations_familiales/securite_sociale_L.catala_fr index 39443f6a..0ec0ed78 100644 --- a/examples/allocations_familiales/securite_sociale_L.catala_fr +++ b/examples/allocations_familiales/securite_sociale_L.catala_fr @@ -90,6 +90,7 @@ champ d'application PrestationsFamiliales : Les allocations familiales sont dues à partir du deuxième enfant à charge. /* champ d'application AllocationsFamiliales : + étiquette définitition_droit_ouvert_base règle droit_ouvert_base sous condition nombre de enfants_à_charge >= 2 conséquence rempli @@ -115,7 +116,7 @@ champ d'application AllocationsFamiliales : conséquence rempli règle droit_ouvert_forfaitaire de enfant sous condition - (nombre de enfants_à_charge >= nombre_enfants_l512_1) et + (nombre de enfants_à_charge >= nombre_enfants_l521_1) et (enfant.âge = prestations_familiales.âge_l512_3_2) et (conditions_hors_âge de enfant) conséquence rempli @@ -361,6 +362,7 @@ Les allocations familiales sont dues, pour tout enfant, à la personne qui a effectivement la charge de celui-ci. /* champ d'application AllocationsFamiliales: + exception définitition_droit_ouvert_base règle droit_ouvert_base sous condition prestations_familiales.régime_outre_mer_l751_1 et (nombre de enfants_à_charge >= 1) diff --git a/examples/allocations_familiales/securite_sociale_R.catala_fr b/examples/allocations_familiales/securite_sociale_R.catala_fr index 2ee905bc..501adc57 100644 --- a/examples/allocations_familiales/securite_sociale_R.catala_fr +++ b/examples/allocations_familiales/securite_sociale_R.catala_fr @@ -21,6 +21,7 @@ articles L. 141-1 à L. 141-9 du code du travail, multiplié par 169. /* champ d'application PrestationsFamiliales : + étiquette définition_plafond_l512_3_2 définition plafond_l512_3_2 égal à (smic.brut_horaire *€ 55 %) *€ 169,0 */ @@ -103,14 +104,12 @@ multiplié par un coefficient résultant du rapport entre le nombre moyen d'enfants et le nombre total d'enfants. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.avec_garde_alternée égal à -# allocations_familiales.base * -# allocations_familiales.rapport_enfants_total_moyen +champ d'application AllocationsFamiliales : + définition montant_avec_garde_alternée_base égal à + montant_initial_base *€ rapport_enfants_total_moyen -# définition allocations_familiales.rapport_enfants_total_moyen égal à -# allocations_familiales.nombre_moyen_enfants / -# allocations_familiales.nombre_total_enfants + définition rapport_enfants_total_moyen égal à + nombre_moyen_enfants /. nombre_total_enfants */ Le nombre moyen d'enfants, pour chaque foyer, est obtenu en faisant la somme @@ -120,21 +119,21 @@ du nombre d'enfants à charge dans les conditions suivantes : 2° Les autres enfants à charge comptent pour 1. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.nombre_moyen_enfants égal à -# somme entier pour enfant dans ménage.enfants de ( -# selon enfant.prise_en_charge sous forme -# -- Complète : 1 -# -- GardeAlternée de parents : 0,5 -# ) +champ d'application AllocationsFamiliales : + définition nombre_moyen_enfants égal à + somme décimal pour enfant dans enfants_à_charge de ( + selon (prise_en_compte de enfant) sous forme + -- Complète : 1,0 + -- Partagée : 0,5 + ) */ Le nombre total d'enfants, pour chaque foyer, est obtenu en faisant la somme du ou des enfants en résidence alternée et, le cas échéant, du ou des autres enfants à charge. /* -# champ d'application CalculAllocationsFamiliales : -# définition allocations_familiales.nombre_total_enfants égal à -# nombre de ménage.enfants +champ d'application AllocationsFamiliales : + définition nombre_total_enfants égal à + entier_vers_décimal de (nombre de enfants_à_charge) */ @Article R521-4|LEGIARTI000006750613@ @@ -143,7 +142,7 @@ nombre d'enfants à charge est évalué dans les conditions prévues au premier alinéa de l'article R. 521-3. /* -# ménage.enfants ne contient que des enfants à charge donc rien à formaliser +# enfants_à_charge ne contient que des enfants à charge donc rien à formaliser # ici */ @@ -151,16 +150,15 @@ Lorsque le ou les enfants ouvrant droit à ladite majoration sont en résidence alternée, le montant servi au titre de cette majoration est réduit de moitié. /* -# champ d'application CalculAllocationsFamiliales : -# définition -# majorations_allocations_familiales.avec_garde_alternée de enfant -# sous condition enfant dans ménage.enfants -# conséquence égal à ( -# selon enfant.prise_en_charge sous forme -# -- Complète : majorations_allocations_familiales.base_par_enfant -# -- GardeAlternée de parents: -# majorations_allocations_familiales.base_par_enfant / 2 -# ) +champ d'application AllocationsFamiliales : + définition + montant_avec_garde_alternée_majoration de enfant + sous condition enfant dans enfants_à_charge + conséquence égal à ( + selon (prise_en_compte de enfant) sous forme + -- Complète : montant_initial_majoration de enfant + -- Partagée : montant_initial_majoration de enfant *€ 50% + ) */ @@Livre 7 : Régimes divers - Dispositions diverses@@++ @@ -175,9 +173,10 @@ L. 512-3 est égal, pour un mois, à 55 % du salaire minimum de croissance en vigueur dans chacun des départements mentionnés à l'article L. 751-1 , multiplié par 169. /* -# champ d'application CalculAllocationsFamiliales : -# définition l512_3.plafond_rémunération_mensuelle_alinéa_2 -# sous condition l751_1.régime_outre_mer -# conséquence égal à -# 55 % * smic.brut_horaire de ménage.résidence * 169 +champ d'application PrestationsFamiliales : + exception définition_plafond_l512_3_2 + définition plafond_l512_3_2 + sous condition régime_outre_mer_l751_1 + conséquence égal à + (smic.brut_horaire *€ 55%) *€ 169,0 */ diff --git a/examples/allocations_familiales/tests/tests_allocations_familiales.catala_fr b/examples/allocations_familiales/tests/tests_allocations_familiales.catala_fr new file mode 100644 index 00000000..f217f05e --- /dev/null +++ b/examples/allocations_familiales/tests/tests_allocations_familiales.catala_fr @@ -0,0 +1,70 @@ +@@Inclusion: ../allocations_familiales.catala_fr@@ + +@Tests@ + +/* +déclaration champ d'application Données: + contexte enfant1 contenu Enfant + contexte enfant2 contenu Enfant + contexte enfant3 contenu Enfant + +champ d'application Données: + définition enfant1 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2023| + -- date_de_naissance: |01/01/2007| + -- âge: 13 + -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + définition enfant2 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2021| + -- date_de_naissance: |01/01/2009| + -- âge: 15 + -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: OuiPartageAllocations + } + définition enfant3 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- date_de_naissance: |01/01/2003| + -- âge: 18 + -- rémuneration_mensuelle: 400€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + +déclaration champ d'application Test1: + contexte f champ d'application AllocationsFamiliales + contexte données champ d'application Données + +champ d'application Test1: + définition f.enfants_à_charge égal à + [données.enfant1;données.enfant2;données.enfant3] + définition f.ressources_ménage égal à 30 000 € + définition f.date_courante égal à |01/05/2020| + définition f.résidence égal à Métropole + assertion f.montant_versé = 417,51€ + +déclaration champ d'application Test2: + contexte f champ d'application AllocationsFamiliales + contexte données champ d'application Données + +champ d'application Test2: + définition f.enfants_à_charge égal à [données.enfant1] + définition f.ressources_ménage égal à 30 000 € + définition f.date_courante égal à |01/05/2020| + définition f.résidence égal à Guyane + assertion f.montant_versé = 39,63€ + +déclaration champ d'application Test3: + contexte f champ d'application AllocationsFamiliales + contexte données champ d'application Données + +champ d'application Test3: + définition f.enfants_à_charge égal à [données.enfant1; données.enfant3] + définition f.ressources_ménage égal à 67 250 € + définition f.date_courante égal à |01/05/2020| + définition f.résidence égal à Métropole + assertion f.montant_versé = 388,29€ +*/ \ No newline at end of file diff --git a/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr index f7c17485..3d4cee22 100644 --- a/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr +++ b/examples/allocations_familiales/tests/tests_ouverture_droits.catala_fr @@ -3,7 +3,48 @@ @Tests@ /* +déclaration champ d'application Données: + contexte enfant1 contenu Enfant + contexte enfant2 contenu Enfant + contexte enfant3 contenu Enfant + contexte enfant4 contenu Enfant + +champ d'application Données: + définition enfant1 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2023| + -- date_de_naissance: |01/01/2007| + -- âge: 13 + -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + définition enfant2 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- date_de_naissance: |01/01/2003| + -- âge: 18 + -- rémuneration_mensuelle: 1000€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + définition enfant3 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2019| + -- date_de_naissance: |01/01/2003| + -- âge: 18 + -- rémuneration_mensuelle: 400€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + définition enfant4 égal à Enfant { + -- fin_obligation_scolaire : |01/08/2016| + -- date_de_naissance: |01/01/1999| + -- âge: 21 + -- rémuneration_mensuelle: 0€ + -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille + -- garde_alternée: NonGardeUnique + } + déclaration champ d'application Test1: + contexte données champ d'application Données contexte f champ d'application PrestationsFamiliales champ d'application Test1: @@ -11,36 +52,8 @@ champ d'application Test1: définition f.date_courante égal à |01/05/2020| définition f.prestation_courante égal à AllocationsFamiliales définition f.résidence égal à Métropole - assertion (f.droit_ouvert de Enfant { - -- fin_obligation_scolaire : |01/08/2023| - -- date_de_naissance: |01/01/2007| - -- âge: 13 - -- rémuneration_mensuelle: 0€ - -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille - -- garde_alternée: NonGardeUnique - }) - assertion (non (f.droit_ouvert de Enfant { - -- fin_obligation_scolaire : |01/08/2019| - -- date_de_naissance: |01/01/2003| - -- âge: 18 - -- rémuneration_mensuelle: 1000€ - -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille - -- garde_alternée: NonGardeUnique - })) - assertion (f.droit_ouvert de Enfant { - -- fin_obligation_scolaire : |01/08/2019| - -- date_de_naissance: |01/01/2003| - -- âge: 18 - -- rémuneration_mensuelle: 400€ - -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille - -- garde_alternée: NonGardeUnique - }) - assertion (non (f.droit_ouvert de Enfant { - -- fin_obligation_scolaire : |01/08/2016| - -- date_de_naissance: |01/01/1999| - -- âge: 21 - -- rémuneration_mensuelle: 0€ - -- pris_en_charge_par_services_sociaux: NonPriseEnChargeFamille - -- garde_alternée: NonGardeUnique - })) + assertion (f.droit_ouvert de données.enfant1) + assertion (non (f.droit_ouvert de données.enfant2)) + assertion (f.droit_ouvert de données.enfant3) + assertion (non (f.droit_ouvert de données.enfant4)) */ \ No newline at end of file diff --git a/src/catala/catala_surface/ast.ml b/src/catala/catala_surface/ast.ml index 00ac832e..edcd1934 100644 --- a/src/catala/catala_surface/ast.ml +++ b/src/catala/catala_surface/ast.ml @@ -87,9 +87,12 @@ type binop = type unop = Not | Minus of op_kind -type builtin_expression = Cardinal +type builtin_expression = Cardinal | IntToDec -type aggregate_func = AggregateSum of primitive_typ | AggregateCount +type aggregate_func = + | AggregateSum of primitive_typ + | AggregateCount + | AggregateExtremum of bool (* true if max *) * primitive_typ type literal_date = { literal_date_day : int Pos.marked; diff --git a/src/catala/catala_surface/desugaring.ml b/src/catala/catala_surface/desugaring.ml index f16caf8c..980f048b 100644 --- a/src/catala/catala_surface/desugaring.ml +++ b/src/catala/catala_surface/desugaring.ml @@ -98,12 +98,14 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) | Number ((Dec (i, f), _), Some (Percent, _)) -> let digits_f = - int_of_float (ceil (float_of_int (Z.log2up f) *. log 2.0 /. log 10.0)) + 2 - (* because of % *) + try int_of_float (ceil (float_of_int (Z.log2 f) *. log 2.0 /. log 10.0)) + with Invalid_argument _ -> 0 in Scopelang.Ast.ELit (Dcalc.Ast.LRat - Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f)))) + (Q.div + Q.(of_bigint i + (of_bigint f / of_bigint (Z.pow (Z.of_int 10) digits_f))) + (Q.of_int 100))) | Bool b -> Scopelang.Ast.ELit (Dcalc.Ast.LBool b) | MoneyAmount i -> Scopelang.Ast.ELit @@ -357,6 +359,9 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LRat Q.zero), Pos.get_position op') | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> Bindlib.box (Scopelang.Ast.ELit (Dcalc.Ast.LMoney Z.zero), Pos.get_position op') + | Ast.Aggregate (Ast.AggregateExtremum _) -> + Errors.raise_spanned_error "Unsupported feature: minimum and maximum" + (Pos.get_position op') | Ast.Aggregate (Ast.AggregateSum t) -> Errors.raise_spanned_error (Format.asprintf "It is impossible to sum two values of type %a together" @@ -385,6 +390,9 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti | Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> make_body (Dcalc.Ast.Add Dcalc.Ast.KRat) | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> make_body (Dcalc.Ast.Add Dcalc.Ast.KMoney) | Ast.Aggregate (Ast.AggregateSum _) -> assert false (* should not happen *) + | Ast.Aggregate (Ast.AggregateExtremum _) -> + Errors.raise_spanned_error "Unsupported feature: minimum and maximum" + (Pos.get_position op') | Ast.Aggregate Ast.AggregateCount -> Bindlib.box_apply2 (fun predicate acc -> @@ -425,6 +433,9 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti | Ast.Aggregate (Ast.AggregateSum Ast.Integer) -> make_f Dcalc.Ast.TInt | Ast.Aggregate (Ast.AggregateSum Ast.Decimal) -> make_f Dcalc.Ast.TRat | Ast.Aggregate (Ast.AggregateSum Ast.Money) -> make_f Dcalc.Ast.TMoney + | Ast.Aggregate (Ast.AggregateExtremum _) -> + Errors.raise_spanned_error "Unsupported feature: minimum and maximum" + (Pos.get_position op') | Ast.Aggregate (Ast.AggregateSum _) -> assert false (* should not happen *) | Ast.Aggregate Ast.AggregateCount -> make_f Dcalc.Ast.TInt in @@ -472,6 +483,7 @@ let rec translate_expr (scope : Scopelang.Ast.ScopeName.t) (ctxt : Name_resoluti ((Scopelang.Ast.EOp (Dcalc.Ast.Ternop Dcalc.Ast.Fold), pos), [ f; init; collection ]), pos )) f collection init + | Builtin IntToDec -> Bindlib.box (Scopelang.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.IntToRat), pos) | Builtin Cardinal -> Bindlib.box (Scopelang.Ast.EOp (Dcalc.Ast.Unop Dcalc.Ast.Length), pos) | _ -> Name_resolution.raise_unsupported_feature "desugaring not implemented for this expression" pos @@ -582,7 +594,13 @@ let process_def (precond : Scopelang.Ast.expr Pos.marked Bindlib.box option) let parent_rule = match def.Ast.definition_exception_to with | None -> None - | Some label -> Some (Desugared.Ast.IdentMap.find (Pos.unmark label) scope_ctxt.label_idmap) + | Some label -> + Some + ( try Desugared.Ast.IdentMap.find (Pos.unmark label) scope_ctxt.label_idmap + with Not_found -> + Errors.raise_spanned_error + (Format.asprintf "Unknown label: \"%s\"" (Pos.unmark label)) + (Pos.get_position label) ) in let x_def = Desugared.Ast.RuleMap.add rule_name diff --git a/src/catala/catala_surface/lexer.ml b/src/catala/catala_surface/lexer.ml index d35b6b1b..08739052 100644 --- a/src/catala/catala_surface/lexer.ml +++ b/src/catala/catala_surface/lexer.ml @@ -77,6 +77,9 @@ let token_list : (string * token) list = ("param", CONTEXT); ("decreasing", DECREASING); ("increasing", INCREASING); + ("int_to_dec", INT_TO_DEC); + ("maximum", MAXIMUM); + ("minimum", MAXIMUM); ("of", OF); ("set", COLLECTION); ("enum", ENUM); @@ -290,6 +293,15 @@ let rec lex_code (lexbuf : lexbuf) : token = | "|]" -> update_acc lexbuf; CONSEQUENCE + | "int_to_dec" -> + update_acc lexbuf; + INT_TO_DEC + | "maximum" -> + update_acc lexbuf; + MAXIMUM + | "minimum" -> + update_acc lexbuf; + MINIMUM | "number" -> update_acc lexbuf; CARDINAL diff --git a/src/catala/catala_surface/lexer_en.ml b/src/catala/catala_surface/lexer_en.ml index 78bda516..48ebbab6 100644 --- a/src/catala/catala_surface/lexer_en.ml +++ b/src/catala/catala_surface/lexer_en.ml @@ -70,6 +70,9 @@ let token_list_en : (string * token) list = ("and", AND); ("or", OR); ("not", NOT); + ("integer_to_decimal", INT_TO_DEC); + ("maximum", MAXIMUM); + ("minimum", MAXIMUM); ("number", CARDINAL); ("year", YEAR); ("month", MONTH); @@ -244,6 +247,15 @@ let rec lex_code_en (lexbuf : lexbuf) : token = | "not" -> L.update_acc lexbuf; NOT + | "integer_to_decimal" -> + L.update_acc lexbuf; + INT_TO_DEC + | "maximum" -> + L.update_acc lexbuf; + MAXIMUM + | "minimum" -> + L.update_acc lexbuf; + MINIMUM | "number" -> L.update_acc lexbuf; CARDINAL diff --git a/src/catala/catala_surface/lexer_fr.ml b/src/catala/catala_surface/lexer_fr.ml index 87cace82..58ef35a4 100644 --- a/src/catala/catala_surface/lexer_fr.ml +++ b/src/catala/catala_surface/lexer_fr.ml @@ -69,6 +69,9 @@ let token_list_fr : (string * token) list = ("ou", OR); ("non", NOT); ("nombre", CARDINAL); + ("entier_vers_décimal", INT_TO_DEC); + ("maximum", MAXIMUM); + ("minimum", MINIMUM); ("an", YEAR); ("mois", MONTH); ("jour", DAY); @@ -251,6 +254,15 @@ let rec lex_code_fr (lexbuf : lexbuf) : token = | "nombre" -> L.update_acc lexbuf; CARDINAL + | "maximum" -> + L.update_acc lexbuf; + MAXIMUM + | "minimum" -> + L.update_acc lexbuf; + MINIMUM + | "entier_vers_d", 0xE9, "cimal" -> + L.update_acc lexbuf; + INT_TO_DEC | "vrai" -> L.update_acc lexbuf; TRUE diff --git a/src/catala/catala_surface/parser.messages b/src/catala/catala_surface/parser.messages index b6ffb9f5..47aa8d6c 100644 --- a/src/catala/catala_surface/parser.messages +++ b/src/catala/catala_surface/parser.messages @@ -1,6 +1,6 @@ source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE LAW_TEXT END_CODE ## -## Ends in an error in state: 327. +## Ends in an error in state: 332. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE option(law_text) . END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -12,7 +12,7 @@ expected a metadata-closing tag source_file_or_master: BEGIN_METADATA BEGIN_CODE END_CODE YEAR ## -## Ends in an error in state: 326. +## Ends in an error in state: 331. ## ## metadata_block -> BEGIN_CODE option(law_text) code END_CODE . option(law_text) END_METADATA [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -72,7 +72,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT TEXT YEAR ## -## Ends in an error in state: 320. +## Ends in an error in state: 325. ## ## nonempty_list(enum_decl_line) -> enum_decl_line . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(enum_decl_line) -> enum_decl_line . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] @@ -85,7 +85,7 @@ expected another enum case, or a new declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 315. +## Ends in an error in state: 320. ## ## enum_decl_line_payload -> CONTENT . typ [ SCOPE END_CODE DECLARATION ALT ] ## @@ -97,7 +97,7 @@ expected a content type source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 314. +## Ends in an error in state: 319. ## ## enum_decl_line -> ALT constructor . option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -109,7 +109,7 @@ expected a payload for your enum case, or another case or declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON ALT YEAR ## -## Ends in an error in state: 313. +## Ends in an error in state: 318. ## ## enum_decl_line -> ALT . constructor option(enum_decl_line_payload) [ SCOPE END_CODE DECLARATION ALT ] ## @@ -121,7 +121,7 @@ expected the name of an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 312. +## Ends in an error in state: 317. ## ## code_item -> DECLARATION ENUM constructor COLON . nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -133,7 +133,7 @@ expected an enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM CONSTRUCTOR YEAR ## -## Ends in an error in state: 311. +## Ends in an error in state: 316. ## ## code_item -> DECLARATION ENUM constructor . COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -145,7 +145,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION ENUM YEAR ## -## Ends in an error in state: 310. +## Ends in an error in state: 315. ## ## code_item -> DECLARATION ENUM . constructor COLON nonempty_list(enum_decl_line) [ SCOPE END_CODE DECLARATION ] ## @@ -157,7 +157,7 @@ expected the name of your enum source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONDITION YEAR ## -## Ends in an error in state: 305. +## Ends in an error in state: 310. ## ## scope_decl_item -> CONTEXT ident CONDITION . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -169,7 +169,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT TEXT YEAR ## -## Ends in an error in state: 303. +## Ends in an error in state: 308. ## ## scope_decl_item -> CONTEXT ident CONTENT typ . option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -181,7 +181,7 @@ expected the next context item or a dependency declaration for this item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT CONTENT YEAR ## -## Ends in an error in state: 302. +## Ends in an error in state: 307. ## ## scope_decl_item -> CONTEXT ident CONTENT . typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -193,7 +193,7 @@ expected the type of this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 307. +## Ends in an error in state: 312. ## ## nonempty_list(scope_decl_item) -> scope_decl_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_decl_item) -> scope_decl_item . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -206,7 +206,7 @@ expected another scope context item or the end of the scope declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT SCOPE YEAR ## -## Ends in an error in state: 300. +## Ends in an error in state: 305. ## ## scope_decl_item -> CONTEXT ident SCOPE . constructor [ SCOPE END_CODE DECLARATION CONTEXT ] ## @@ -218,7 +218,7 @@ expected the name of the subscope for this context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT IDENT YEAR ## -## Ends in an error in state: 299. +## Ends in an error in state: 304. ## ## scope_decl_item -> CONTEXT ident . CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT ident . SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -232,7 +232,7 @@ expected the kind of this context item: is it a condition, a sub-scope or a data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON CONTEXT YEAR ## -## Ends in an error in state: 298. +## Ends in an error in state: 303. ## ## scope_decl_item -> CONTEXT . ident CONTENT typ option(struct_scope_func) [ SCOPE END_CODE DECLARATION CONTEXT ] ## scope_decl_item -> CONTEXT . ident SCOPE constructor [ SCOPE END_CODE DECLARATION CONTEXT ] @@ -246,7 +246,7 @@ expected the name of this new context item source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 297. +## Ends in an error in state: 302. ## ## code_item -> DECLARATION SCOPE constructor COLON . nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -258,7 +258,7 @@ expected a context item introduced by "context" source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE CONSTRUCTOR YEAR ## -## Ends in an error in state: 296. +## Ends in an error in state: 301. ## ## code_item -> DECLARATION SCOPE constructor . COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -270,7 +270,7 @@ expected a colon followed by the list of context items of this scope source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION SCOPE YEAR ## -## Ends in an error in state: 295. +## Ends in an error in state: 300. ## ## code_item -> DECLARATION SCOPE . constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] ## @@ -282,7 +282,7 @@ expected the name of the scope you are declaring source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS COLLECTION YEAR ## -## Ends in an error in state: 282. +## Ends in an error in state: 287. ## ## typ -> collection_marked . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONTEXT CONDITION ALT ] ## @@ -295,7 +295,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS TEXT YEAR ## -## Ends in an error in state: 290. +## Ends in an error in state: 295. ## ## list(struct_scope) -> struct_scope . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -307,7 +307,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT DEPENDS YEAR ## -## Ends in an error in state: 286. +## Ends in an error in state: 291. ## ## struct_scope_func -> DEPENDS . typ [ SCOPE END_CODE DECLARATION DATA CONTEXT CONDITION ] ## @@ -319,7 +319,7 @@ expected the type of the parameter of this struct data function source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION IDENT YEAR ## -## Ends in an error in state: 285. +## Ends in an error in state: 290. ## ## struct_scope -> struct_scope_base . option(struct_scope_func) [ SCOPE END_CODE DECLARATION DATA CONDITION ] ## @@ -331,7 +331,7 @@ expected a new struct data, or another declaration or scope use source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON CONDITION YEAR ## -## Ends in an error in state: 292. +## Ends in an error in state: 297. ## ## struct_scope_base -> condition_pos . ident [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -343,7 +343,7 @@ expected the name of this struct condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT CONTENT YEAR ## -## Ends in an error in state: 278. +## Ends in an error in state: 283. ## ## struct_scope_base -> DATA ident CONTENT . typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -355,7 +355,7 @@ expected the type of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA IDENT YEAR ## -## Ends in an error in state: 277. +## Ends in an error in state: 282. ## ## struct_scope_base -> DATA ident . CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -367,7 +367,7 @@ expected the type of this struct data, introduced by the content keyword source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON DATA YEAR ## -## Ends in an error in state: 276. +## Ends in an error in state: 281. ## ## struct_scope_base -> DATA . ident CONTENT typ [ SCOPE END_CODE DEPENDS DECLARATION DATA CONDITION ] ## @@ -379,7 +379,7 @@ expected the name of this struct data source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 275. +## Ends in an error in state: 280. ## ## code_item -> DECLARATION STRUCT constructor COLON . list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -391,7 +391,7 @@ expected struct data or condition source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT CONSTRUCTOR YEAR ## -## Ends in an error in state: 274. +## Ends in an error in state: 279. ## ## code_item -> DECLARATION STRUCT constructor . COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -403,7 +403,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION STRUCT YEAR ## -## Ends in an error in state: 273. +## Ends in an error in state: 278. ## ## code_item -> DECLARATION STRUCT . constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## @@ -415,7 +415,7 @@ expected the struct name source_file_or_master: LAW_ARTICLE BEGIN_CODE DECLARATION YEAR ## -## Ends in an error in state: 272. +## Ends in an error in state: 277. ## ## code_item -> DECLARATION . STRUCT constructor COLON list(struct_scope) [ SCOPE END_CODE DECLARATION ] ## code_item -> DECLARATION . SCOPE constructor COLON nonempty_list(scope_decl_item) [ SCOPE END_CODE DECLARATION ] @@ -429,7 +429,7 @@ expected the kind of the declaration (struct, scope or enum) source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION CARDINAL THEN ## -## Ends in an error in state: 243. +## Ends in an error in state: 248. ## ## nonempty_list(scope_item) -> scope_item . [ SCOPE END_CODE DECLARATION ] ## nonempty_list(scope_item) -> scope_item . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] @@ -441,23 +441,23 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 62, spurious reduction of production primitive_expression -> CARDINAL -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression -## In state 237, spurious reduction of production assertion_base -> expression -## In state 238, spurious reduction of production assertion -> option(condition_consequence) assertion_base -## In state 242, spurious reduction of production scope_item -> ASSERTION assertion +## In state 67, spurious reduction of production primitive_expression -> CARDINAL +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression +## In state 242, spurious reduction of production assertion_base -> expression +## In state 243, spurious reduction of production assertion -> option(condition_consequence) assertion_base +## In state 247, spurious reduction of production scope_item -> ASSERTION assertion ## expected a new scope use item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT BY YEAR ## -## Ends in an error in state: 234. +## Ends in an error in state: 239. ## ## assertion -> FIXED qident BY . ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -469,7 +469,7 @@ expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED IDENT WITH_V ## -## Ends in an error in state: 233. +## Ends in an error in state: 238. ## ## assertion -> FIXED qident . BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -480,15 +480,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 232, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 224, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the legislative text by which the value of the variable is fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION FIXED YEAR ## -## Ends in an error in state: 232. +## Ends in an error in state: 237. ## ## assertion -> FIXED . qident BY ident [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -500,7 +500,7 @@ expected the name of the variable that should be fixed source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL CONSEQUENCE BY ## -## Ends in an error in state: 236. +## Ends in an error in state: 241. ## ## assertion -> option(condition_consequence) . assertion_base [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -512,9 +512,9 @@ expected an expression for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION CARDINAL THEN ## -## Ends in an error in state: 240. +## Ends in an error in state: 245. ## -## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## condition_consequence -> condition . CONSEQUENCE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FILLED FALSE EXISTS DEFINED_AS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## condition @@ -523,21 +523,21 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 62, spurious reduction of production primitive_expression -> CARDINAL -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression -## In state 231, spurious reduction of production condition -> UNDER_CONDITION expression +## In state 67, spurious reduction of production primitive_expression -> CARDINAL +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression +## In state 236, spurious reduction of production condition -> UNDER_CONDITION expression ## expected a consequence for this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION UNDER_CONDITION YEAR ## -## Ends in an error in state: 230. +## Ends in an error in state: 235. ## ## condition -> UNDER_CONDITION . expression [ CONSEQUENCE ] ## @@ -549,7 +549,7 @@ expected an expression for this condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT UNDER_CONDITION ## -## Ends in an error in state: 220. +## Ends in an error in state: 225. ## ## assertion -> VARIES qident . WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -560,15 +560,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 232, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 224, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected an indication about what this variable varies with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V TRUE THEN ## -## Ends in an error in state: 222. +## Ends in an error in state: 227. ## ## assertion -> VARIES qident WITH_V base_expression . option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -579,15 +579,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression ## expected an indication about the variation sense of the variable, or a new scope item source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES IDENT WITH_V YEAR ## -## Ends in an error in state: 221. +## Ends in an error in state: 226. ## ## assertion -> VARIES qident WITH_V . base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -599,7 +599,7 @@ the variable varies with an expression that was expected here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION VARIES YEAR ## -## Ends in an error in state: 218. +## Ends in an error in state: 223. ## ## assertion -> VARIES . qident WITH_V base_expression option(variation_type) [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -611,7 +611,7 @@ expecting the name of the varying variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON ASSERTION YEAR ## -## Ends in an error in state: 217. +## Ends in an error in state: 222. ## ## scope_item -> ASSERTION . assertion [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -623,7 +623,7 @@ expected an expression that shoud be asserted during execution source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT DEFINED_AS YEAR ## -## Ends in an error in state: 265. +## Ends in an error in state: 270. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS . expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -635,7 +635,7 @@ expected an expression for the definition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT OF IDENT DECREASING ## -## Ends in an error in state: 263. +## Ends in an error in state: 268. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) . option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -647,7 +647,7 @@ expected a expression for defining this function, introduced by the defined as k source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT UNDER_CONDITION CARDINAL CONSEQUENCE DECREASING ## -## Ends in an error in state: 264. +## Ends in an error in state: 269. ## ## definition -> option(label) option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) . DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -659,7 +659,7 @@ expected an expression for the consequence of this definition under condition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION IDENT WITH_V ## -## Ends in an error in state: 262. +## Ends in an error in state: 267. ## ## definition -> option(label) option(exception_to) DEFINITION qident . option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -670,15 +670,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 232, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 224, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected the defined as keyword to introduce the definition of this variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON DEFINITION YEAR ## -## Ends in an error in state: 261. +## Ends in an error in state: 266. ## ## definition -> option(label) option(exception_to) DEFINITION . qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -690,7 +690,7 @@ expected the name of the variable you want to define source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION IDENT DEFINED_AS ## -## Ends in an error in state: 248. +## Ends in an error in state: 253. ## ## definition -> option(label) option(exception_to) . DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) option(exception_to) . RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -703,7 +703,7 @@ expected a rule or a definition after the exception declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON EXCEPTION YEAR ## -## Ends in an error in state: 246. +## Ends in an error in state: 251. ## ## exception_to -> EXCEPTION . ident [ RULE DEFINITION ] ## @@ -715,7 +715,7 @@ expected the label to which the exception is referring back source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL IDENT DEFINED_AS ## -## Ends in an error in state: 245. +## Ends in an error in state: 250. ## ## definition -> option(label) . option(exception_to) DEFINITION qident option(definition_parameters) option(condition_consequence) DEFINED_AS expression [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## rule -> option(label) . option(exception_to) RULE rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] @@ -728,7 +728,7 @@ expected a rule or a definition after the label declaration source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON LABEL YEAR ## -## Ends in an error in state: 215. +## Ends in an error in state: 220. ## ## label -> LABEL . ident [ RULE EXCEPTION DEFINITION ] ## @@ -740,7 +740,7 @@ expected the name of the label source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT DOT YEAR ## -## Ends in an error in state: 228. +## Ends in an error in state: 233. ## ## separated_nonempty_list(DOT,ident) -> ident DOT . separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## @@ -752,7 +752,7 @@ expected a struct field or a sub-scope context item after the dot source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT NOT FALSE ## -## Ends in an error in state: 254. +## Ends in an error in state: 259. ## ## rule_consequence -> option(NOT) . FILLED [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -764,7 +764,7 @@ expected the filled keyword the this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF IDENT YEAR ## -## Ends in an error in state: 250. +## Ends in an error in state: 255. ## ## rule -> option(label) option(exception_to) RULE rule_expr . option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -776,7 +776,7 @@ expected the expression of the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT OF YEAR ## -## Ends in an error in state: 257. +## Ends in an error in state: 262. ## ## definition_parameters -> OF . ident [ UNDER_CONDITION NOT FILLED DEFINED_AS ] ## @@ -788,7 +788,7 @@ expected the name of the parameter for this dependent variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT UNDER_CONDITION TRUE CONSEQUENCE FALSE ## -## Ends in an error in state: 251. +## Ends in an error in state: 256. ## ## rule -> option(label) option(exception_to) RULE rule_expr option(condition_consequence) . rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -800,7 +800,7 @@ expected filled or not filled for a rule consequence source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT WITH_V ## -## Ends in an error in state: 256. +## Ends in an error in state: 261. ## ## rule_expr -> qident . option(definition_parameters) [ UNDER_CONDITION NOT FILLED ] ## @@ -811,15 +811,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 227, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident -## In state 219, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) +## In state 232, spurious reduction of production separated_nonempty_list(DOT,ident) -> ident +## In state 224, spurious reduction of production qident -> separated_nonempty_list(DOT,ident) ## expected a condition or a consequence for this rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE IDENT YEAR ## -## Ends in an error in state: 227. +## Ends in an error in state: 232. ## ## separated_nonempty_list(DOT,ident) -> ident . [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] ## separated_nonempty_list(DOT,ident) -> ident . DOT separated_nonempty_list(DOT,ident) [ WITH_V UNDER_CONDITION OF NOT FILLED DEFINED_AS BY ] @@ -832,7 +832,7 @@ expected a condition or a consequence for this rule, or the rest of the variable source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON RULE YEAR ## -## Ends in an error in state: 249. +## Ends in an error in state: 254. ## ## rule -> option(label) option(exception_to) RULE . rule_expr option(condition_consequence) rule_consequence [ SCOPE RULE LABEL EXCEPTION END_CODE DEFINITION DECLARATION ASSERTION ] ## @@ -844,7 +844,7 @@ expected the name of the variable subject to the rule source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 214. +## Ends in an error in state: 219. ## ## code_item -> SCOPE constructor option(scope_use_condition) COLON . nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -856,7 +856,7 @@ expected a scope use item: a rule, definition or assertion source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CARDINAL YEAR ## -## Ends in an error in state: 62. +## Ends in an error in state: 67. ## ## aggregate_func -> CARDINAL . [ FOR ] ## primitive_expression -> CARDINAL . [ WITH THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -869,7 +869,7 @@ expected the keyword following cardinal to compute the number of elements in a s source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT TRUE YEAR ## -## Ends in an error in state: 160. +## Ends in an error in state: 165. ## ## enum_inject_content -> CONTENT small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -883,7 +883,7 @@ the expression for the content of the enum case is already well-formed, expected source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR CONTENT YEAR ## -## Ends in an error in state: 159. +## Ends in an error in state: 164. ## ## enum_inject_content -> CONTENT . small_expression [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -896,7 +896,7 @@ expected an expression for the content of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL ALT YEAR ## -## Ends in an error in state: 88. +## Ends in an error in state: 93. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field ALT . separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] ## @@ -908,7 +908,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON CARDINAL THEN ## -## Ends in an error in state: 87. +## Ends in an error in state: 92. ## ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . [ RBRACKET ] ## separated_nonempty_list(ALT,struct_content_field) -> struct_content_field . ALT separated_nonempty_list(ALT,struct_content_field) [ RBRACKET ] @@ -920,20 +920,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 62, spurious reduction of production primitive_expression -> CARDINAL -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 151, spurious reduction of production struct_content_field -> ident COLON logical_expression +## In state 67, spurious reduction of production primitive_expression -> CARDINAL +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 156, spurious reduction of production struct_content_field -> ident COLON logical_expression ## expected another structure field or the closing bracket source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT COLON YEAR ## -## Ends in an error in state: 91. +## Ends in an error in state: 96. ## ## struct_content_field -> ident COLON . logical_expression [ RBRACKET ALT ] ## @@ -945,7 +945,7 @@ expected the expression for this struct field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT IDENT YEAR ## -## Ends in an error in state: 90. +## Ends in an error in state: 95. ## ## struct_content_field -> ident . COLON logical_expression [ RBRACKET ALT ] ## @@ -957,7 +957,7 @@ expected a colon source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET ALT YEAR ## -## Ends in an error in state: 86. +## Ends in an error in state: 91. ## ## struct_or_enum_inject_content -> LBRACKET ALT . separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -969,7 +969,7 @@ expected the name of the structure field source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR LBRACKET YEAR ## -## Ends in an error in state: 85. +## Ends in an error in state: 90. ## ## struct_or_enum_inject_content -> LBRACKET . ALT separated_nonempty_list(ALT,struct_content_field) RBRACKET [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -981,7 +981,7 @@ expected structure fields introduced by -- source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION CONSTRUCTOR YEAR ## -## Ends in an error in state: 84. +## Ends in an error in state: 89. ## ## struct_or_enum_inject -> constructor . struct_or_enum_inject_content [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -993,7 +993,7 @@ expected a payload for the enum case constructor, or the rest of the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN CARDINAL SUCH THAT YEAR ## -## Ends in an error in state: 175. +## Ends in an error in state: 180. ## ## expression -> exists_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1005,9 +1005,9 @@ expected an expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE SUCH YEAR ## -## Ends in an error in state: 181. +## Ends in an error in state: 186. ## -## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression SUCH . THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression SUCH @@ -1017,9 +1017,9 @@ expected a keyword to complete the "such that" construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN TRUE WITH ## -## Ends in an error in state: 180. +## Ends in an error in state: 185. ## -## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN primitive_expression . SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN primitive_expression @@ -1028,16 +1028,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression ## expected a keyword to form the "such that" expression for the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT IN YEAR ## -## Ends in an error in state: 179. +## Ends in an error in state: 184. ## -## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident IN . primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident IN @@ -1047,9 +1047,9 @@ expected an expression that designates the set subject to the existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS IDENT YEAR ## -## Ends in an error in state: 178. +## Ends in an error in state: 183. ## -## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked ident . IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked ident @@ -1059,9 +1059,9 @@ expected the "in" keyword to continue this existential test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION EXISTS YEAR ## -## Ends in an error in state: 177. +## Ends in an error in state: 182. ## -## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## exists_prefix -> exists_marked . ident IN primitive_expression SUCH THAT [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## exists_marked @@ -1071,7 +1071,7 @@ expected an identifier that will designate the existential witness for the test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN CARDINAL WE_HAVE YEAR ## -## Ends in an error in state: 168. +## Ends in an error in state: 173. ## ## expression -> forall_prefix . expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1083,9 +1083,9 @@ expected an expression for the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN TRUE WITH ## -## Ends in an error in state: 172. +## Ends in an error in state: 177. ## -## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN primitive_expression . WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN primitive_expression @@ -1094,16 +1094,16 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression ## expected the "we have" keyword for this universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT IN YEAR ## -## Ends in an error in state: 171. +## Ends in an error in state: 176. ## -## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident IN . primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident IN @@ -1113,9 +1113,9 @@ expected the expression designating the set on which to perform the universal te source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL IDENT YEAR ## -## Ends in an error in state: 170. +## Ends in an error in state: 175. ## -## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked ident . IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked ident @@ -1125,9 +1125,9 @@ expected the "in" keyword for the rest of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR ALL YEAR ## -## Ends in an error in state: 169. +## Ends in an error in state: 174. ## -## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MATCH LSQUARE LPAREN INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] +## forall_prefix -> for_all_marked . ident IN primitive_expression WE_HAVE [ VERTICAL TRUE SUM NOT MONEY_AMOUNT MINUSMONEY MINUSDURATION MINUSDEC MINUS MINIMUM MAXIMUM MATCH LSQUARE LPAREN INT_TO_DEC INT_LITERAL IF IDENT FOR FALSE EXISTS DECIMAL_LITERAL CONSTRUCTOR CARDINAL ] ## ## The known suffix of the stack is as follows: ## for_all_marked @@ -1137,7 +1137,7 @@ expected an identifier for the bound variable of the universal test source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION FOR YEAR ## -## Ends in an error in state: 57. +## Ends in an error in state: 62. ## ## for_all_marked -> FOR . ALL [ IDENT ] ## @@ -1149,7 +1149,7 @@ expected the "all" keyword to mean the "for all" construction of the universal t source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE SCOPE ## -## Ends in an error in state: 183. +## Ends in an error in state: 188. ## ## expression -> IF expression . THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1160,20 +1160,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression ## expected the "then" keyword as the conditional expression is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE ELSE YEAR ## -## Ends in an error in state: 186. +## Ends in an error in state: 191. ## ## expression -> IF expression THEN expression ELSE . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1185,7 +1185,7 @@ expected an expression for the "else" branch of this conditional construction source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN TRUE THEN ## -## Ends in an error in state: 185. +## Ends in an error in state: 190. ## ## expression -> IF expression THEN expression . ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1196,20 +1196,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression ## expected the "else" branch of this conditional expression as the "then" branch is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF TRUE THEN YEAR ## -## Ends in an error in state: 184. +## Ends in an error in state: 189. ## ## expression -> IF expression THEN . expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1221,7 +1221,7 @@ expected an expression the for the "then" branch of the conditiona source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION IF YEAR ## -## Ends in an error in state: 55. +## Ends in an error in state: 60. ## ## expression -> IF . expression THEN expression ELSE base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1233,7 +1233,7 @@ expected an expression for the test of the conditional source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION INT_LITERAL WITH_V ## -## Ends in an error in state: 75. +## Ends in an error in state: 80. ## ## literal -> num_literal . option(unit_literal) [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1245,7 +1245,7 @@ expected a unit for this literal, or a valid operator to complete the expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN TRUE THEN ## -## Ends in an error in state: 188. +## Ends in an error in state: 193. ## ## atomic_expression -> LPAREN expression . RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1256,20 +1256,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression ## unmatched parenthesis that should have been closed by here source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION LPAREN YEAR ## -## Ends in an error in state: 53. +## Ends in an error in state: 57. ## ## atomic_expression -> LPAREN . expression RPAREN [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1281,7 +1281,7 @@ expected an expression inside the parenthesis source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WE_HAVE ## -## Ends in an error in state: 196. +## Ends in an error in state: 201. ## ## expression -> MATCH primitive_expression . WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1292,14 +1292,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression ## expected the "with patter" keyword to complete the pattern matching expression source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON NOT TRUE OR ## -## Ends in an error in state: 199. +## Ends in an error in state: 204. ## ## match_arms -> ALT match_arm . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1310,20 +1310,20 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 150, spurious reduction of production logical_expression -> logical_unop compare_expression -## In state 203, spurious reduction of production match_arm -> constructor_binding COLON logical_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 155, spurious reduction of production logical_expression -> logical_unop compare_expression +## In state 208, spurious reduction of production match_arm -> constructor_binding COLON logical_expression ## expected another match case or the rest of the expression since the previous match case is complete source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR COLON YEAR ## -## Ends in an error in state: 202. +## Ends in an error in state: 207. ## ## match_arm -> constructor_binding COLON . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1335,7 +1335,7 @@ expected an expression for this pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF CONSTRUCTOR YEAR ## -## Ends in an error in state: 207. +## Ends in an error in state: 212. ## ## optional_binding -> OF constructor . constructor_binding [ COLON ] ## @@ -1347,7 +1347,7 @@ expected a colon or a binding for the enum constructor payload source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF IDENT YEAR ## -## Ends in an error in state: 201. +## Ends in an error in state: 206. ## ## match_arm -> constructor_binding . COLON logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1359,7 +1359,7 @@ expected a colon and then the expression for this matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR OF YEAR ## -## Ends in an error in state: 205. +## Ends in an error in state: 210. ## ## optional_binding -> OF . ident [ COLON ] ## optional_binding -> OF . constructor constructor_binding [ COLON ] @@ -1372,7 +1372,7 @@ expected an identifier for this enum case binding source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT CONSTRUCTOR YEAR ## -## Ends in an error in state: 204. +## Ends in an error in state: 209. ## ## constructor_binding -> constructor . optional_binding [ COLON ] ## @@ -1384,7 +1384,7 @@ expected a binding for the constructor payload, or a colon and the matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH ALT YEAR ## -## Ends in an error in state: 198. +## Ends in an error in state: 203. ## ## match_arms -> ALT . match_arm match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1396,7 +1396,7 @@ expected the name of the constructor for the enum case in the pattern matching source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH TRUE WITH YEAR ## -## Ends in an error in state: 197. +## Ends in an error in state: 202. ## ## expression -> MATCH primitive_expression WITH . match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1408,7 +1408,7 @@ expected a pattern matching case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MATCH YEAR ## -## Ends in an error in state: 51. +## Ends in an error in state: 55. ## ## expression -> MATCH . primitive_expression WITH match_arms [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ] ## @@ -1420,7 +1420,7 @@ expected an expression to match with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION MINUS YEAR ## -## Ends in an error in state: 63. +## Ends in an error in state: 68. ## ## sum_expression -> sum_unop . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1432,7 +1432,7 @@ expected an expression to take the opposite of source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION NOT YEAR ## -## Ends in an error in state: 149. +## Ends in an error in state: 154. ## ## logical_expression -> logical_unop . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1461,7 +1461,7 @@ expected the "for" keyword to spell the aggregation source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ARROW YEAR ## -## Ends in an error in state: 69. +## Ends in an error in state: 74. ## ## small_expression -> small_expression ARROW . constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1473,7 +1473,7 @@ expected a constructor, to get the payload of this enum case source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE ASSERTION ## -## Ends in an error in state: 213. +## Ends in an error in state: 218. ## ## code_item -> SCOPE constructor option(scope_use_condition) . COLON nonempty_list(scope_item) [ SCOPE END_CODE DECLARATION ] ## @@ -1484,22 +1484,22 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression -## In state 129, spurious reduction of production mult_expression -> base_expression -## In state 116, spurious reduction of production sum_expression -> mult_expression -## In state 92, spurious reduction of production compare_expression -> sum_expression -## In state 152, spurious reduction of production logical_expression -> compare_expression -## In state 167, spurious reduction of production expression -> logical_expression -## In state 211, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression -## In state 212, spurious reduction of production option(scope_use_condition) -> scope_use_condition +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression +## In state 134, spurious reduction of production mult_expression -> base_expression +## In state 121, spurious reduction of production sum_expression -> mult_expression +## In state 97, spurious reduction of production compare_expression -> sum_expression +## In state 157, spurious reduction of production logical_expression -> compare_expression +## In state 172, spurious reduction of production expression -> logical_expression +## In state 216, spurious reduction of production scope_use_condition -> UNDER_CONDITION expression +## In state 217, spurious reduction of production option(scope_use_condition) -> scope_use_condition ## expected a colon after the scope use precondition source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE DOT YEAR ## -## Ends in an error in state: 67. +## Ends in an error in state: 72. ## ## small_expression -> small_expression DOT . ident [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] ## @@ -1511,7 +1511,7 @@ expected an identifier standing for a struct field or a subscope name source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE IN YEAR ## -## Ends in an error in state: 165. +## Ends in an error in state: 170. ## ## base_expression -> primitive_expression IN . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1523,7 +1523,7 @@ expected an expression standing for the set you want to test for membership source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE INCREASING ## -## Ends in an error in state: 129. +## Ends in an error in state: 134. ## ## mult_expression -> base_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## mult_expression -> base_expression . mult_op mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1535,15 +1535,15 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression -## In state 71, spurious reduction of production base_expression -> primitive_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression +## In state 76, spurious reduction of production base_expression -> primitive_expression ## expected an operator to compose the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE MULT YEAR ## -## Ends in an error in state: 136. +## Ends in an error in state: 141. ## ## mult_expression -> base_expression mult_op . mult_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1555,7 +1555,7 @@ expected an expression on the right side of the multiplication or division opera source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE NOT_EQUAL YEAR ## -## Ends in an error in state: 115. +## Ends in an error in state: 120. ## ## compare_expression -> sum_expression compare_op . compare_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1567,7 +1567,7 @@ expected an expression on the right side of the comparison operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OF YEAR ## -## Ends in an error in state: 74. +## Ends in an error in state: 79. ## ## base_expression -> primitive_expression OF . base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1579,7 +1579,7 @@ expected an expression for the argument of this function call source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE OR YEAR ## -## Ends in an error in state: 155. +## Ends in an error in state: 160. ## ## logical_expression -> compare_expression logical_op . logical_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET LABEL EXCEPTION END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION ALT ] ## @@ -1591,7 +1591,7 @@ expected an expression on the right side of the logical operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE PLUS YEAR ## -## Ends in an error in state: 127. +## Ends in an error in state: 132. ## ## sum_expression -> mult_expression sum_op . sum_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET OR NOT_EQUAL LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DEFINITION DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1603,7 +1603,7 @@ expected an expression on the right side of the sum or minus operator source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WE_HAVE ## -## Ends in an error in state: 71. +## Ends in an error in state: 76. ## ## base_expression -> primitive_expression . [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## base_expression -> primitive_expression . OF base_expression [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] @@ -1617,14 +1617,14 @@ source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION ## This implies that, although the LR(1) items shown above provide an ## accurate view of the past (what has been recognized so far), they ## may provide an INCOMPLETE view of the future (what was expected next). -## In state 66, spurious reduction of production primitive_expression -> small_expression +## In state 71, spurious reduction of production primitive_expression -> small_expression ## expected an operator to compose the expression on the left with source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE WITH YEAR ## -## Ends in an error in state: 72. +## Ends in an error in state: 77. ## ## base_expression -> primitive_expression WITH . constructor [ THEN SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## @@ -1636,7 +1636,7 @@ expected an enum constructor to test if the expression on the left source_file_or_master: LAW_ARTICLE BEGIN_CODE SCOPE CONSTRUCTOR UNDER_CONDITION TRUE YEAR ## -## Ends in an error in state: 66. +## Ends in an error in state: 71. ## ## primitive_expression -> small_expression . [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION AND ALT ] ## small_expression -> small_expression . ARROW constructor [ WITH WE_HAVE THEN SUCH SEMICOLON SCOPE RULE RSQUARE RPAREN RBRACKET PLUSMONEY PLUSDURATION PLUSDEC PLUSDATE PLUS OR OF NOT_EQUAL MULTMONEY MULTDEC MULT MINUSMONEY MINUSDURATION MINUSDEC MINUSDATE MINUS LESSER_MONEY LESSER_EQUAL_MONEY LESSER_EQUAL_DURATION LESSER_EQUAL_DEC LESSER_EQUAL_DATE LESSER_EQUAL LESSER_DURATION LESSER_DEC LESSER_DATE LESSER LABEL INCREASING IN GREATER_MONEY GREATER_EQUAL_MONEY GREATER_EQUAL_DURATION GREATER_EQUAL_DEC GREATER_EQUAL_DATE GREATER_EQUAL GREATER_DURATION GREATER_DEC GREATER_DATE GREATER EXCEPTION EQUAL END_CODE ELSE DOT DIVMONEY DIVDEC DIV DEFINITION DECREASING DECLARATION CONSEQUENCE COLON ASSERTION ARROW AND ALT ] @@ -1758,7 +1758,7 @@ expected the name of the scope you want to use source_file_or_master: LAW_ARTICLE BEGIN_CODE YEAR ## -## Ends in an error in state: 336. +## Ends in an error in state: 341. ## ## law_article_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA BEGIN_CODE ] ## @@ -1770,7 +1770,7 @@ expected a declaration or a scope use source_file_or_master: LAW_ARTICLE LAW_TEXT YEAR ## -## Ends in an error in state: 341. +## Ends in an error in state: 346. ## ## law_articles_items -> law_article_item . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1782,7 +1782,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_ARTICLE YEAR ## -## Ends in an error in state: 335. +## Ends in an error in state: 340. ## ## source_file_article -> law_article . law_articles_items [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## @@ -1794,7 +1794,7 @@ expected a code block, a metadata block, more law text or a heading source_file_or_master: LAW_HEADING YEAR ## -## Ends in an error in state: 330. +## Ends in an error in state: 335. ## ## source_file_after_text -> source_file_item . list(law_intermediate_text) source_file_after_text [ # ] ## @@ -1806,7 +1806,7 @@ expected an article title, another heading or some text source_file_or_master: LAW_TEXT YEAR ## -## Ends in an error in state: 345. +## Ends in an error in state: 350. ## ## list(law_intermediate_text) -> law_intermediate_text . list(law_intermediate_text) [ LAW_INCLUDE LAW_HEADING LAW_ARTICLE EOF BEGIN_METADATA ] ## diff --git a/src/catala/catala_surface/parser.mly b/src/catala/catala_surface/parser.mly index 42296c41..24346a9a 100644 --- a/src/catala/catala_surface/parser.mly +++ b/src/catala/catala_surface/parser.mly @@ -63,6 +63,7 @@ %token BEGIN_METADATA END_METADATA MONEY DECIMAL %token UNDER_CONDITION CONSEQUENCE LBRACKET RBRACKET %token LABEL EXCEPTION LSQUARE RSQUARE SEMICOLON +%token INT_TO_DEC MAXIMUM MINIMUM %type source_file_or_master @@ -140,6 +141,9 @@ primitive_expression: | CARDINAL { (Builtin Cardinal, $sloc) } +| INT_TO_DEC { + (Builtin IntToDec, $sloc) +} | e = struct_or_enum_inject { e } @@ -209,6 +213,8 @@ compare_op: | NOT_EQUAL { (Neq, $sloc) } aggregate_func: +| MAXIMUM t = typ_base { (Aggregate (AggregateExtremum (true, Pos.unmark t)), $sloc) } +| MINIMUM t = typ_base { (Aggregate (AggregateExtremum (false, Pos.unmark t)), $sloc) } | SUM t = typ_base { (Aggregate (AggregateSum (Pos.unmark t)), $sloc) } | CARDINAL { (Aggregate AggregateCount, $sloc) } diff --git a/src/catala/catala_surface/parser_errors.ml b/src/catala/catala_surface/parser_errors.ml index 31f89845..f4fabc4c 100644 --- a/src/catala/catala_surface/parser_errors.ml +++ b/src/catala/catala_surface/parser_errors.ml @@ -13,11 +13,11 @@ let message s = "expected another inclusion of a Catala file, since this file is a master file which can \ only contain inclusions of other Catala files\n" | 8 -> "expected some text, another heading or a law article\n" - | 345 -> "expected a heading, an article title or some text\n" - | 330 -> "expected an article title, another heading or some text\n" - | 335 -> "expected a code block, a metadata block, more law text or a heading\n" - | 341 -> "expected a code block, a metadata block, more law text or a heading\n" - | 336 -> "expected a declaration or a scope use\n" + | 350 -> "expected a heading, an article title or some text\n" + | 335 -> "expected an article title, another heading or some text\n" + | 340 -> "expected a code block, a metadata block, more law text or a heading\n" + | 346 -> "expected a code block, a metadata block, more law text or a heading\n" + | 341 -> "expected a declaration or a scope use\n" | 22 -> "expected the name of the scope you want to use\n" | 24 -> "expected a scope use precondition or a colon\n" | 25 -> "expected an expression which will act as the condition\n" @@ -27,138 +27,138 @@ let message s = | 30 -> "expected a \"/\"\n" | 31 -> "expected the third component of the date literal\n" | 32 -> "expected a delimiter to finish the date literal\n" - | 66 -> "expected an operator to compose the expression on the left with\n" - | 72 -> "expected an enum constructor to test if the expression on the left\n" | 71 -> "expected an operator to compose the expression on the left with\n" - | 127 -> "expected an expression on the right side of the sum or minus operator\n" - | 155 -> "expected an expression on the right side of the logical operator\n" - | 74 -> "expected an expression for the argument of this function call\n" - | 115 -> "expected an expression on the right side of the comparison operator\n" - | 136 -> "expected an expression on the right side of the multiplication or division operator\n" - | 129 -> "expected an operator to compose the expression on the left\n" - | 165 -> "expected an expression standing for the set you want to test for membership\n" - | 67 -> "expected an identifier standing for a struct field or a subscope name\n" - | 213 -> "expected a colon after the scope use precondition\n" - | 69 -> "expected a constructor, to get the payload of this enum case\n" + | 77 -> "expected an enum constructor to test if the expression on the left\n" + | 76 -> "expected an operator to compose the expression on the left with\n" + | 132 -> "expected an expression on the right side of the sum or minus operator\n" + | 160 -> "expected an expression on the right side of the logical operator\n" + | 79 -> "expected an expression for the argument of this function call\n" + | 120 -> "expected an expression on the right side of the comparison operator\n" + | 141 -> "expected an expression on the right side of the multiplication or division operator\n" + | 134 -> "expected an operator to compose the expression on the left\n" + | 170 -> "expected an expression standing for the set you want to test for membership\n" + | 72 -> "expected an identifier standing for a struct field or a subscope name\n" + | 218 -> "expected a colon after the scope use precondition\n" + | 74 -> "expected a constructor, to get the payload of this enum case\n" | 35 -> "expected the \"for\" keyword to spell the aggregation\n" - | 149 -> "expected an expression to take the negation of\n" - | 63 -> "expected an expression to take the opposite of\n" - | 51 -> "expected an expression to match with\n" - | 197 -> "expected a pattern matching case\n" - | 198 -> "expected the name of the constructor for the enum case in the pattern matching\n" - | 204 -> + | 154 -> "expected an expression to take the negation of\n" + | 68 -> "expected an expression to take the opposite of\n" + | 55 -> "expected an expression to match with\n" + | 202 -> "expected a pattern matching case\n" + | 203 -> "expected the name of the constructor for the enum case in the pattern matching\n" + | 209 -> "expected a binding for the constructor payload, or a colon and the matching case expression\n" - | 205 -> "expected an identifier for this enum case binding\n" - | 201 -> "expected a colon and then the expression for this matching case\n" - | 207 -> "expected a colon or a binding for the enum constructor payload\n" - | 202 -> "expected an expression for this pattern matching case\n" - | 199 -> + | 210 -> "expected an identifier for this enum case binding\n" + | 206 -> "expected a colon and then the expression for this matching case\n" + | 212 -> "expected a colon or a binding for the enum constructor payload\n" + | 207 -> "expected an expression for this pattern matching case\n" + | 204 -> "expected another match case or the rest of the expression since the previous match case is \ complete\n" - | 196 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" - | 53 -> "expected an expression inside the parenthesis\n" - | 188 -> "unmatched parenthesis that should have been closed by here\n" - | 75 -> "expected a unit for this literal, or a valid operator to complete the expression \n" - | 55 -> "expected an expression for the test of the conditional\n" - | 184 -> "expected an expression the for the \"then\" branch of the conditiona\n" - | 185 -> + | 201 -> "expected the \"with patter\" keyword to complete the pattern matching expression\n" + | 57 -> "expected an expression inside the parenthesis\n" + | 193 -> "unmatched parenthesis that should have been closed by here\n" + | 80 -> "expected a unit for this literal, or a valid operator to complete the expression \n" + | 60 -> "expected an expression for the test of the conditional\n" + | 189 -> "expected an expression the for the \"then\" branch of the conditiona\n" + | 190 -> "expected the \"else\" branch of this conditional expression as the \"then\" branch is \ complete\n" - | 186 -> "expected an expression for the \"else\" branch of this conditional construction\n" - | 183 -> "expected the \"then\" keyword as the conditional expression is complete\n" - | 57 -> + | 191 -> "expected an expression for the \"else\" branch of this conditional construction\n" + | 188 -> "expected the \"then\" keyword as the conditional expression is complete\n" + | 62 -> "expected the \"all\" keyword to mean the \"for all\" construction of the universal test\n" - | 169 -> "expected an identifier for the bound variable of the universal test\n" - | 170 -> "expected the \"in\" keyword for the rest of the universal test\n" - | 171 -> "expected the expression designating the set on which to perform the universal test\n" - | 172 -> "expected the \"we have\" keyword for this universal test\n" - | 168 -> "expected an expression for the universal test\n" - | 177 -> "expected an identifier that will designate the existential witness for the test\n" - | 178 -> "expected the \"in\" keyword to continue this existential test\n" - | 179 -> "expected an expression that designates the set subject to the existential test\n" - | 180 -> "expected a keyword to form the \"such that\" expression for the existential test\n" - | 181 -> "expected a keyword to complete the \"such that\" construction\n" - | 175 -> "expected an expression for the existential test\n" - | 84 -> + | 174 -> "expected an identifier for the bound variable of the universal test\n" + | 175 -> "expected the \"in\" keyword for the rest of the universal test\n" + | 176 -> "expected the expression designating the set on which to perform the universal test\n" + | 177 -> "expected the \"we have\" keyword for this universal test\n" + | 173 -> "expected an expression for the universal test\n" + | 182 -> "expected an identifier that will designate the existential witness for the test\n" + | 183 -> "expected the \"in\" keyword to continue this existential test\n" + | 184 -> "expected an expression that designates the set subject to the existential test\n" + | 185 -> "expected a keyword to form the \"such that\" expression for the existential test\n" + | 186 -> "expected a keyword to complete the \"such that\" construction\n" + | 180 -> "expected an expression for the existential test\n" + | 89 -> "expected a payload for the enum case constructor, or the rest of the expression (with an \ operator ?)\n" - | 85 -> "expected structure fields introduced by --\n" - | 86 -> "expected the name of the structure field\n" - | 90 -> "expected a colon\n" - | 91 -> "expected the expression for this struct field\n" - | 87 -> "expected another structure field or the closing bracket\n" - | 88 -> "expected the name of the structure field\n" - | 159 -> "expected an expression for the content of this enum case\n" - | 160 -> + | 90 -> "expected structure fields introduced by --\n" + | 91 -> "expected the name of the structure field\n" + | 95 -> "expected a colon\n" + | 96 -> "expected the expression for this struct field\n" + | 92 -> "expected another structure field or the closing bracket\n" + | 93 -> "expected the name of the structure field\n" + | 164 -> "expected an expression for the content of this enum case\n" + | 165 -> "the expression for the content of the enum case is already well-formed, expected an \ operator to form a bigger expression\n" - | 62 -> "expected the keyword following cardinal to compute the number of elements in a set\n" - | 214 -> "expected a scope use item: a rule, definition or assertion\n" - | 249 -> "expected the name of the variable subject to the rule\n" - | 227 -> + | 67 -> "expected the keyword following cardinal to compute the number of elements in a set\n" + | 219 -> "expected a scope use item: a rule, definition or assertion\n" + | 254 -> "expected the name of the variable subject to the rule\n" + | 232 -> "expected a condition or a consequence for this rule, or the rest of the variable qualified \ name\n" - | 256 -> "expected a condition or a consequence for this rule\n" - | 251 -> "expected filled or not filled for a rule consequence\n" - | 257 -> "expected the name of the parameter for this dependent variable \n" - | 250 -> "expected the expression of the rule\n" - | 254 -> "expected the filled keyword the this rule \n" - | 228 -> "expected a struct field or a sub-scope context item after the dot\n" - | 215 -> "expected the name of the label\n" - | 245 -> "expected a rule or a definition after the label declaration\n" - | 246 -> "expected the label to which the exception is referring back\n" - | 248 -> "expected a rule or a definition after the exception declaration\n" - | 261 -> "expected the name of the variable you want to define\n" - | 262 -> "expected the defined as keyword to introduce the definition of this variable\n" - | 264 -> "expected an expression for the consequence of this definition under condition\n" - | 263 -> + | 261 -> "expected a condition or a consequence for this rule\n" + | 256 -> "expected filled or not filled for a rule consequence\n" + | 262 -> "expected the name of the parameter for this dependent variable \n" + | 255 -> "expected the expression of the rule\n" + | 259 -> "expected the filled keyword the this rule \n" + | 233 -> "expected a struct field or a sub-scope context item after the dot\n" + | 220 -> "expected the name of the label\n" + | 250 -> "expected a rule or a definition after the label declaration\n" + | 251 -> "expected the label to which the exception is referring back\n" + | 253 -> "expected a rule or a definition after the exception declaration\n" + | 266 -> "expected the name of the variable you want to define\n" + | 267 -> "expected the defined as keyword to introduce the definition of this variable\n" + | 269 -> "expected an expression for the consequence of this definition under condition\n" + | 268 -> "expected a expression for defining this function, introduced by the defined as keyword\n" - | 265 -> "expected an expression for the definition\n" - | 217 -> "expected an expression that shoud be asserted during execution\n" - | 218 -> "expecting the name of the varying variable\n" - | 221 -> "the variable varies with an expression that was expected here\n" - | 222 -> "expected an indication about the variation sense of the variable, or a new scope item\n" - | 220 -> "expected an indication about what this variable varies with\n" - | 230 -> "expected an expression for this condition\n" - | 240 -> "expected a consequence for this definition under condition\n" - | 236 -> "expected an expression for this definition under condition\n" - | 232 -> "expected the name of the variable that should be fixed\n" - | 233 -> "expected the legislative text by which the value of the variable is fixed\n" - | 234 -> "expected the legislative text by which the value of the variable is fixed\n" - | 243 -> "expected a new scope use item \n" - | 272 -> "expected the kind of the declaration (struct, scope or enum)\n" - | 273 -> "expected the struct name\n" - | 274 -> "expected a colon\n" - | 275 -> "expected struct data or condition\n" - | 276 -> "expected the name of this struct data \n" - | 277 -> "expected the type of this struct data, introduced by the content keyword\n" - | 278 -> "expected the type of this struct data\n" - | 292 -> "expected the name of this struct condition\n" - | 285 -> "expected a new struct data, or another declaration or scope use\n" - | 286 -> "expected the type of the parameter of this struct data function\n" + | 270 -> "expected an expression for the definition\n" + | 222 -> "expected an expression that shoud be asserted during execution\n" + | 223 -> "expecting the name of the varying variable\n" + | 226 -> "the variable varies with an expression that was expected here\n" + | 227 -> "expected an indication about the variation sense of the variable, or a new scope item\n" + | 225 -> "expected an indication about what this variable varies with\n" + | 235 -> "expected an expression for this condition\n" + | 245 -> "expected a consequence for this definition under condition\n" + | 241 -> "expected an expression for this definition under condition\n" + | 237 -> "expected the name of the variable that should be fixed\n" + | 238 -> "expected the legislative text by which the value of the variable is fixed\n" + | 239 -> "expected the legislative text by which the value of the variable is fixed\n" + | 248 -> "expected a new scope use item \n" + | 277 -> "expected the kind of the declaration (struct, scope or enum)\n" + | 278 -> "expected the struct name\n" + | 279 -> "expected a colon\n" + | 280 -> "expected struct data or condition\n" + | 281 -> "expected the name of this struct data \n" + | 282 -> "expected the type of this struct data, introduced by the content keyword\n" + | 283 -> "expected the type of this struct data\n" + | 297 -> "expected the name of this struct condition\n" | 290 -> "expected a new struct data, or another declaration or scope use\n" - | 282 -> "expected a new struct data, or another declaration or scope use\n" - | 295 -> "expected the name of the scope you are declaring\n" - | 296 -> "expected a colon followed by the list of context items of this scope\n" - | 297 -> "expected a context item introduced by \"context\"\n" - | 298 -> "expected the name of this new context item\n" - | 299 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" - | 300 -> "expected the name of the subscope for this context item\n" - | 307 -> "expected another scope context item or the end of the scope declaration\n" - | 302 -> "expected the type of this context item\n" - | 303 -> "expected the next context item or a dependency declaration for this item\n" - | 305 -> "expected the next context item or a dependency declaration for this item\n" - | 310 -> "expected the name of your enum\n" - | 311 -> "expected a colon\n" - | 312 -> "expected an enum case\n" - | 313 -> "expected the name of an enum case \n" - | 314 -> "expected a payload for your enum case, or another case or declaration \n" - | 315 -> "expected a content type\n" - | 320 -> "expected another enum case, or a new declaration or scope use\n" + | 291 -> "expected the type of the parameter of this struct data function\n" + | 295 -> "expected a new struct data, or another declaration or scope use\n" + | 287 -> "expected a new struct data, or another declaration or scope use\n" + | 300 -> "expected the name of the scope you are declaring\n" + | 301 -> "expected a colon followed by the list of context items of this scope\n" + | 302 -> "expected a context item introduced by \"context\"\n" + | 303 -> "expected the name of this new context item\n" + | 304 -> "expected the kind of this context item: is it a condition, a sub-scope or a data?\n" + | 305 -> "expected the name of the subscope for this context item\n" + | 312 -> "expected another scope context item or the end of the scope declaration\n" + | 307 -> "expected the type of this context item\n" + | 308 -> "expected the next context item or a dependency declaration for this item\n" + | 310 -> "expected the next context item or a dependency declaration for this item\n" + | 315 -> "expected the name of your enum\n" + | 316 -> "expected a colon\n" + | 317 -> "expected an enum case\n" + | 318 -> "expected the name of an enum case \n" + | 319 -> "expected a payload for your enum case, or another case or declaration \n" + | 320 -> "expected a content type\n" + | 325 -> "expected another enum case, or a new declaration or scope use\n" | 18 -> "expected a declaration or a scope use\n" | 19 -> "expected some text or the beginning of a code section\n" | 20 -> "expected a declaration or a scope use\n" | 21 -> "should not happen\n" - | 326 -> "expected a metadata-closing tag\n" - | 327 -> "expected a metadata-closing tag\n" + | 331 -> "expected a metadata-closing tag\n" + | 332 -> "expected a metadata-closing tag\n" | _ -> raise Not_found diff --git a/src/catala/default_calculus/ast.ml b/src/catala/default_calculus/ast.ml index 2e4a77a7..ba487c79 100644 --- a/src/catala/default_calculus/ast.ml +++ b/src/catala/default_calculus/ast.ml @@ -75,6 +75,7 @@ type unop = | ErrorOnEmpty | Log of log_entry * Utils.Uid.MarkedString.info list | Length + | IntToRat type operator = Ternop of ternop | Binop of binop | Unop of unop diff --git a/src/catala/default_calculus/interpreter.ml b/src/catala/default_calculus/interpreter.ml index b42b908f..38b4c80d 100644 --- a/src/catala/default_calculus/interpreter.ml +++ b/src/catala/default_calculus/interpreter.ml @@ -193,6 +193,7 @@ let rec evaluate_operator (op : A.operator Pos.marked) (args : A.expr Pos.marked | A.Unop (A.Minus KRat), [ ELit (LRat i) ] -> A.ELit (LRat (Q.sub Q.zero i)) | A.Unop A.Not, [ ELit (LBool b) ] -> A.ELit (LBool (not b)) | A.Unop A.Length, [ EArray es ] -> A.ELit (LInt (Z.of_int (List.length es))) + | A.Unop A.IntToRat, [ ELit (LInt i) ] -> A.ELit (LRat (Q.of_bigint i)) | A.Unop A.ErrorOnEmpty, [ e' ] -> if e' = A.ELit LEmptyError then Errors.raise_spanned_error diff --git a/src/catala/default_calculus/print.ml b/src/catala/default_calculus/print.ml index d76180a3..f8aa8b9b 100644 --- a/src/catala/default_calculus/print.ml +++ b/src/catala/default_calculus/print.ml @@ -137,13 +137,14 @@ let format_unop (fmt : Format.formatter) (op : unop Pos.marked) : unit = ~pp_sep:(fun fmt () -> Format.fprintf fmt ".") (fun fmt info -> Utils.Uid.MarkedString.format_info fmt info)) infos - | Length -> "length" ) + | Length -> "length" + | IntToRat -> "int_to_rat" ) let needs_parens (e : expr Pos.marked) : bool = match Pos.unmark e with EAbs _ | EApp _ -> true | _ -> false let format_var (fmt : Format.formatter) (v : Var.t) : unit = - Format.fprintf fmt "%s_%d" (Bindlib.name_of v) (Bindlib.uid_of v) + Format.fprintf fmt "%s" (Bindlib.name_of v) let rec format_expr (fmt : Format.formatter) (e : expr Pos.marked) : unit = let format_with_parens (fmt : Format.formatter) (e : expr Pos.marked) = diff --git a/src/catala/default_calculus/typing.ml b/src/catala/default_calculus/typing.ml index e16bb869..65389630 100644 --- a/src/catala/default_calculus/typing.ml +++ b/src/catala/default_calculus/typing.ml @@ -145,6 +145,7 @@ let op_type (op : A.operator Pos.marked) : typ Pos.marked UnionFind.elem = | A.Unop A.ErrorOnEmpty -> arr any any | A.Unop (A.Log _) -> arr any any | A.Unop A.Length -> arr array_any it + | A.Unop A.IntToRat -> arr it rt | Binop (Mult (KDate | KDuration)) | Binop (Div (KDate | KDuration)) | Unop (Minus KDate) -> Errors.raise_spanned_error "This operator is not available!" pos diff --git a/src/catala/driver.ml b/src/catala/driver.ml index 501bac7c..6b9ebc2a 100644 --- a/src/catala/driver.ml +++ b/src/catala/driver.ml @@ -138,9 +138,12 @@ let driver (source_file : Pos.input_file) (debug : bool) (unstyled : bool) let prgm = Desugared.Desugared_to_scope.translate_program prgm in Cli.debug_print "Translating to default calculus..."; let prgm = Scopelang.Scope_to_dcalc.translate_program prgm scope_uid in - Cli.debug_print (Format.asprintf "Output program:@\n%a" Dcalc.Print.format_expr prgm); - let typ = Dcalc.Typing.infer_type prgm in - Cli.debug_print (Format.asprintf "Typechecking results :@\n%a" Dcalc.Print.format_typ typ); + (* Cli.debug_print (Format.asprintf "Output program:@\n%a" Dcalc.Print.format_expr prgm); *) + Cli.debug_print "Typechecking..."; + let _typ = Dcalc.Typing.infer_type prgm in + (* Cli.debug_print (Format.asprintf "Typechecking results :@\n%a" Dcalc.Print.format_typ + typ); *) + Cli.debug_print "Starting interpretation..."; let results = Dcalc.Interpreter.interpret_program prgm in let results = List.sort From 4a5e8192b69c900f653b1cae50938aae2415924d Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Wed, 23 Dec 2020 15:37:29 +0100 Subject: [PATCH 140/142] Opam file: fix license format --- .gitignore | 1 + catala.opam | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index df7b8325..dd3d79d4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ _build/ +_opam/ *.install src/**/.merlin legifrance_oauth* diff --git a/catala.opam b/catala.opam index 72e77e69..b32e1b46 100644 --- a/catala.opam +++ b/catala.opam @@ -8,7 +8,7 @@ higher-level specification languages for fiscal legislation. """ maintainer: ["contact@catala-lang.org"] authors: ["Denis Merigoux"] -license: "Apache2" +license: "Apache-2.0" homepage: "https://github.com/CatalaLang/catala" bug-reports: "https://github.com/CatalaLang/catala/issues" depends: [ From 3b93fc5b437a529f4434255bab4c5d9812e64531 Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Wed, 23 Dec 2020 15:38:36 +0100 Subject: [PATCH 141/142] Tutorial: a few typos --- examples/tutorial_en/tutorial_en.catala_en | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/tutorial_en/tutorial_en.catala_en b/examples/tutorial_en/tutorial_en.catala_en index 43850bb1..94de8d58 100644 --- a/examples/tutorial_en/tutorial_en.catala_en +++ b/examples/tutorial_en/tutorial_en.catala_en @@ -41,7 +41,7 @@ individual's income over a year. To do that, we will intertwine short snippets of code between the sentences of the legislative text. Each snippet of code should be as short as possible and as close as possible to the actual sentence that justifies the code. This style -is called litterate programming, a programming paradigm invented by the famous +is called literate programming, a programming paradigm invented by the famous computer scientist Donald Knuth in the 70s. @@Defining a fictional income tax@@+ @@ -72,7 +72,7 @@ declaration structure Individual: */ @@End metadata@@ -This structre contains two data fields, "income" and "number_of_children". Structures are +This structure contains two data fields, "income" and "number_of_children". Structures are useful to group together data that goes together. Usually, you get one structure per concrete object on which the law applies (like the individual). It is up to you to decide how to group the data together, @@ -381,4 +381,4 @@ with their algorithmic translation. There is no single way to write Catala programs, as the program style should be adapted to the legislation it annotates. However, Catala is a functional language at heart, so following standard functional programming design patterns -should help achieve concise and readable code. \ No newline at end of file +should help achieve concise and readable code. From 06803e41704c494389f90bfe5ad0f804c28bb6ee Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Tue, 5 Jan 2021 14:35:04 +0100 Subject: [PATCH 142/142] Fixed makefile and dune_porject --- Makefile | 7 +++++-- dune-project | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index c1c2bf7f..d458d92e 100644 --- a/Makefile +++ b/Makefile @@ -45,12 +45,15 @@ build: @$(MAKE) --no-print-directory format dune build +release_build: + dune build --profile release + doc: dune build @doc ln -sf $(PWD)/_build/default/_doc/_html/index.html doc/odoc.html install: - dune build --profile release @install + dune build @install ########################################## # Syntax highlighting rules @@ -161,7 +164,7 @@ catala.html: src/catala/utils/cli.ml dune exec src/catala.exe -- --help=groff | man2html | sed -e '1,8d' \ | tac | sed "1,20d" | tac > $@ -website-assets: doc literate_examples grammar.html catala.html install +website-assets: doc literate_examples grammar.html catala.html release_build ########################################## # Misceallenous diff --git a/dune-project b/dune-project index 7193583b..dec43a9b 100644 --- a/dune-project +++ b/dune-project @@ -10,7 +10,7 @@ (bug_reports https://github.com/CatalaLang/catala/issues) (authors "Denis Merigoux") (maintainers "contact@catala-lang.org") -(license Apache2) +(license Apache-2.0) (package

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®D7~Hrz~oa=6B0_kKUN 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 E0!x23+W-In diff --git a/examples/us_tax_code/section_1015.catala_en b/examples/us_tax_code/section_1015.catala_en index 8ff4bbfa..4a5e3e7a 100644 --- a/examples/us_tax_code/section_1015.catala_en +++ b/examples/us_tax_code/section_1015.catala_en @@ -49,7 +49,7 @@ scope BasisOfGift: transferor.basis definition basis under condition - acquisition.moment > |01/31/1920| and + acquisition.moment > |12/31/1920| and acquisition.method = Gift consequence equals basis_subsection_a From d71d50ea4431059bec4ae741ccfae37597abacf1 Mon Sep 17 00:00:00 2001 From: Denis Merigoux Date: Sun, 3 Jan 2021 18:56:03 +0100 Subject: [PATCH 137/142] Fixed screenshot mangling --- doc/images/CatalaScreenShot.png | Bin 117623 -> 171148 bytes doc/images/ScreenShotVSCode.png | Bin 130918 -> 117623 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/images/CatalaScreenShot.png b/doc/images/CatalaScreenShot.png index cb52a2de960f52d581663756878c50797301d00e..294e97ccda4b316c0f10b8ea0faddf662abed740 100644 GIT binary patch literal 171148 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®D7~Hrz~oa=6B0_kKUN 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 E0!x23+W-In literal 117623 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�lT9sqYN`AF59Vs=gk^O^a(}Td**&)8 z6yONcND@;x4-%_c8hUP%dBUI_^OJq4R1GWC0e!5h1ba*ZH$aX3dTTWy_5C9I3wx6B zf3X|)wWNzrU2gV|jZ!C1cx{<3Ui$3@>i?&pO7z_OeXn&W|2;?Rn>W2x9N5h>a@1*f z|0#WQE5_%^8-(KRQ%7L^IK7%`uv^tlKd^J#(Ii#xS7}Ti_sy+_ystJa{*wmTZXvS~{JWh$B%EcpXO#V!X^8tOoAt z@{Z5aE!I-ArnFEIfpP&1I~PTQcZtQP*zMMj3Hc)$NWoZs4Vig9r*94M7e48I4=J8G zZ7Jk$c`iB_CtNxjSz50vnVgBB>;}W zca9?SkH3ntdh(yOXsUD%Z&;P;JJ~yGj6Aq(lR2CL5EOrTAYYrEEUxPyR*8T$fYhh_ zrLbg6lkb||iogdgPLSX#vvTouHY&2#jV-LrD)TTOrX))v_u z97KQ>W&75kcwnmaoBQaXfc7**B^y!1dgat>O%KtK1hB+kY-$-5Q>^^jD3yBh!oB)! z*=rDrT8!(@mKBtk-X5gljw9MGXV?N0&&ULv?Q&-Oklas3R5LF$dc#EXq%&e*QXsv2 z>yiUHj3DPYs2j&J&eb zW@~xx98zvt9ZB!t-qc)fq|w^l_{}&7zMYyocS)4Ps4Bw zjXqGTHb$MTHpVtV%inBf_csPG;f=aRBZ~DGJ84F83IT*AF|Q$vs*IG{kj-q_6Mn9t zSvj&cRxWf~-Jll&m|29C$CJjf+(%}QkNEnt85g!eczn%|ULQ4(oxX;1S~hHNOW2or zUs+#w+HN0Se2c#hN4mUf2LqFGq}G$tY1L>2PczN4Lo8d&)~i}cu&)YuUY;?!V{G$05MOgzHAl>N*0e?<`i5wJH*V4-iMux zs?tCxG7_&}I@PZ)WyX$w6dL@&YXui~4QxB@lXHqZ-}4TsKjg($9AsDjjA3<=tNxow z+1xj9yXz78oW`KtAVV-s*JPCx4tvL=>?JP%({j_C_F&R2BKnyoPSz|C}N$llu<>XND02G z5oCJuTlZw~G)rSvE3Z)(K0C9*pnRXbs*X+m#d{FA;O3nppodjXfF^RF7x6Gdd59ok7>7CsWF}}P8Jmk>9hC=g( zM4d}(Bl3+H=tpFX9@DiO>-3F&hxZ&7D~+cNrf9<*BF_Ol&Qc$*d0nD)9i1cJ>;EH*Ne0^zRE(VJJS1iP}g^_^N)`e;J>q6KIs za8#i`J4r+-A&|rJ#MWzcrl<_ELp5Ye{7s>VPJn$dhOeRvJdC>VY(HrpxBc%oaFES6u;&l#G(y z@8|qoOIBE6tfm>B;UFnU2eaT$E>SKp=5;f==@l-0$1>9=55sbjTYM9}i0NHf+2+?b ze^E}ffjrCzgkw{;-_`$z(-Ak*X%XoH&FZ&tbz+RBcUnfh>&IJuJ6n)B-<156n^1!d^ngtkF!2pI?#|-J1HAK+<{mVeOyd{If)fX~uB1|8fX? zEg3$mY}89uZ1j=$qU^-rbo`TSd{HNmP@A>p5{4cPz?Ve zKkAy7Rl;IL58neKz@h$NauN!oF^1c$=i;w%FWA)YlR~C1I7S>^is5XQjchO=R5^5% z>T$KKp5&;X?#h`i$9bgWOR6E6Rp%GA4e!^Jg^;&_p=AUOv(PRWpQ9D*Ao3K^X~}9; z25}o>%p!O*>gF7g4^&7d2yHfMO?PORB5e9lKNdn>uqfMgs54|YRp71`mKHUBRV&Yu zQJwtlk_sQ@KL1Z0^dbHAbAMI_Nc=%H>Iy2!6aFen+G5QACFHH92cJ3`jsud2&c{yD z($pC(*#)Yeg&91xA3lbH_E+Cz#4Xa%OfJ1-D=*k=x}5@^yd^=K_CrdUV;*tpj3#=eB@dk(0l z2t}xPf-M1=DVh>6vEA7xf?-@xUob!`kcc4ogQBaE$ve%eXW8ffozBji-FyZ8hD?qt z&GV;y-ev$0_c%3Pq79p?MnIbh#!f+J$@G?`cFl8~7hcQX-1k%=W{AcGQRACKqW)`f zi-TS>Lu|boHFh`9jLYRe4BYx!9ngay{DXnk1^;fpMnU)htS)Dnfc_+ml?Es9`C)r7 zO~JV@TyIN_Xw0wYP2XsEQ%4*%QnM73>oJ-1;dVZBy}W;+GG6Z~995MSGMQY?mSV{S za&#5JZ{9^m>tR$ke5esB5 zwMv7c3bg%C6`4}#bR~GULU~~f@^6X*ld?qQ`=1!+He7G%kx^m$cOkc`oDsuDOt{dJ zmZ)TXg6xf=#Hj!p^pZuh{R1-R+Wq$m#BkAKSRryyKL#kQe%_?R4MqoIwS?@P-mWBA z-0wg^Mx9gHYHuva2;-nk2&f(ITp`q=c|Ha-mIDgd?R z&^-t712?{BQf!^XTD~NSWS=jlU4E+Ql6!fK@qz!mUG`*iz6Y5s-T^X7W3bz|$s$Pp z3o0131tvi08v`->OBZqjxLQCciG^N6nD!aHlu24+dco#aEfxZznL|>( z{xSPaXo)RgWCrQPCTqrUt#Q*w4qof%G7XsVjuTAS7z%$#6}Rgk8W5ESZqLq)#XZ6i zDsn&`Ilir!K8kS@^Q;LH2M>6p!@>se_{ZbkngBqBcq_97I`V5h% zsccTI09=<@_bm$eTu~XVa;4b5L5*kQZB+j4HES6O9jdKlSoz;YQ8k`&b;2lfg5^(~`1ZtDeI=0f_ekyWj2Rw-6dIYQ_Zg01OWq|Ytd zOL>=3k7IK#?wVKr2@gUcCrJH`VJjT2lew+Tny`3gP2eMamxF@2-}r6_TsV_ic>Qsn zUkq}emcTb&^IGdQE^-ESN+Cj6!3B-sZDKW2hT+N~eoB4WV)mjvwL4~3g}Py)Xh=cK zzhVk&gU7_Uh1w#_d)bH&>1@~^Jy|)^+nW>c0D1QCq;? zH$?P`%!i$?J1pufDRgSj`RS@(M;@qJPo^O~4vsVa{hag_&>kmQVtZh}grxg&+*QE3 zfd>9c#Y*GHUf8OZ_#I^cvHl**pq^KH!`Up)>ZfJF^%6N3j;z({Zy_YSNOH+&HrDvX z^`nA${6lf>zi)h{*S|o(THSG>qJ@|}!L=@Rlzy!XXnA09X3BX!X1NPna$ovUFVOa~ z6MxSq$cKFWVb3v1R*bbUp~*N9QEI$fNhu(@+;m;xup$j&UwL+WgPK|sZy9bEMqZp6 ze!~SOsLS*9t$rSv?hW3rUEZa{s`$zf_+B}&7*M=A+NY==5^G`_$JZifSB&$#O} zuB!nTd-Z}DzV3=AAOWaRc=D5_6DR7)UMh7>RJFDHCZ}9_giKr!J(y5SiQnl8He4h{ znOGn&7nzUr;WVRPl4(H?@A?jMa4xGbkK!W5|GOvh$sx1=Y~pIIa!=2Dr^x``Z@h8?n{mHM)u zj#-44%%AzSeyb1)=vY7ZLPKH#B|p+dO>*e_aUSQotqB$2;QucRpc^yFmx^jl)5i+6 z79_dBbMFmEqEAv*9mS-53Tqzo zdZ@tX>1Rh=2-0JVUF`?wk)zqD-n?{MGA+oL`c7vJG|SCFNcwWV?x6| zf!fKRywPu4=Qaq;avTeH#eEExqV3WaP8^3mfgtPVWIyaffNT^5#n9JN4b}S}tV%pA z`9KC9?BY?suqy|DXxLYl)c5qI0?)A?MzbNK==-2&pmXWcZdfHVc)RdWn`5MiZ3Az# z)qz)1&K8Nen=Lw76Wco}m^bhM(H}!{wA*nBqVvez30yV)u9f~?TF$JyCForUVp<6H zbGIz9AF7|NX3ykHWF4nYAAtb8oNvJGqR5;QWfX9u;0e=UB9}S}XkSl;MpE0b% zgJr%}4$6f?*~u0l!PzdB<#>YQEv#d=>*Q;O%o*?P7|W9*Y>4)K!As$ZZ6I-#9thag!7YJmzpB-AT|Q$ErgqKo5# zRR(b(fn{&^hl$J3S^Cm{imuIdajMMw=UOd?sKx(EjWr5%nw>t0fz4zY_o~@<3~3oou{&Wttg9J7 z6j|*n$*|RoyyFK6U12aw@n!qOkSC9}$g|nH(j<8Es_nxTeG1|Khp=;uuIzal^~9NI zV%v5m*2K1L+nyvdv2EL!Sd-+$wr$%v$vwaStNUKoI_rGdYwhmcsP3+Qs>&`Yo59Ks zz+;WZNbOx^VY@%OApRHX<_iz};Ak=bZWND--z`5fG8Fan>n%cE1{x`Q?}7m3@*;AkDR>M^>&859kADYCB}Ujj^Wa269nY zrz46K<2V*{!tIKvYBI-fOfk4sW5s|DvjeNGSj(eMe<-3Qfqha@Du(?>aC8ctt zM4{4~w}UYrSYXQF!S7xLV6FBAbq#A}G1Wm;yLe?}M|JtMFdJ&u*DAYe2_xQm0k~b1 z2x`cM>R=kv>N5=-?!ho5*2o3|OIAa25KyTc;}JRim1^9_Ou-tzLdYk$s=^e@lA{)I zv@ty*2jg!q=>W<<7USX3Gw8Q@a3990=Xddrc_(}brAMD^USu1Sv?>#VcJfa|+46s#YL{}pv$Bp5!fZ```DDq^0JREbOYU0ZI& z;|x_fo|*QGno`D=_)%i-=vRK1MN7s8Na@x_8y-9!$WAgAte*${C>KQ|DRg`ojL}Q3 z$syZ2XWxtnGntddVuhpkltUo3Hdr44{q$iUGdeBMNP%O>5X@O{6sH(KZMbAaWyrba3-J0YH&qC%JmPN)g$k_ zv&Pz?B-Tpy3kS~|A4h0$sMrb1X#o}t_va`I#&hN{)nQZK{QcDb5 z8vSY&Of@th4!owEIGh~BwFdB!MqUzzo-}3|vJCYwzO0JM=3!^CT)Vi)j>hr z&e*1_@%(F{@Yg(B`5u;6;r^Zs|&=A1)zSl? zLe_WbGzXNy=W%zF6*DuJDzECtO4DworlJhb)*&|oo=E;^8JGYN)kGm#{3&PsH=Inz ziqCuEI5^X_WYDxM1)`cO4&J+x(w(=FCj49N4Tm;sziMHQfs(wMn&Q>BzM=7I^n1FX z)Lvb6(iEbZ_;o5hw-Q71`3|zQ<)^ogo`O|FUHlCaSQ<_+vsN#ezmpOsn{UMBGLfW~?i3RT3f0_XlJ94rIbGuuS~B3GSrBew zmsNJ~_x^mNsEhNb*FF*|mxu6~(VSf?O3(Ln&z}*pyD2&6DOm8UZfo&1VPsC1_@o2h zt(i1bo~!Xt>49m|vr+YJ564d@E@j@+^zHO@u1L0B`02pr>$JZrlfU?DjHg&-3!{Y4<42kI}gf> zJ+0C081;ZjgJJq`#4$56t$=lr)fs_i@RsBTMl&Kgx*Vg$hVZcJhj}%e5oeD;|8ckP zgqtE2wn!s0PMsJl-p?=b{Pfdpb*2-xs%Uz7bHlEBy~6%)ryk@?i+M3JhAGS97cJs& zPlTotPD=!74V?Bvb3CEH^XD`%j0#K0bMM`tbJoz8>_R)u8(PkVo2-#;@IHi;Z8k3S z(|h+HB2T*e{-SiKPUy`$+3oWQg#B`8C-}QLx!_XNy*!*yJQo%oL&l0kpDKrapI&6) zz6SPm&8UwuwKLEPb)Nn;WlY>za8t_rp00>X8LZ2Q!Dy(xR*50Pthxt}J&hTEMQ+un z%R@+0CSp31EbRc^jCTsLuSTc%d^u%kSu9b~o2GTFhdo_px!#+qW33d>ijteKezI-% z({a(>TFX<9Ely+&Ou|okC!W;WnB6m-ZaVosBhO^n3eC8uREygnkivt?>J^k5MLt)` zdlPbTQkI;;!>`nZa>BI8zR3NCFYS@EA2Zcq%H*P z;Xzf86^$n5<&1eEJ$zIAh1!b5s?R-@D?y z22*$Do3S7rq|chF?L>xE`;I9j3eI7_D`F0m`l6}?vf>umtmr1%-xE)rkUKY;7bPE4vL%lsP-5A zsyWNLbffJpD6a^Q3zdvg6|71em(=}rFl3yAA^@qRj?IfLtJhA>ydHULw3Q&l>KVSyb8q5>O!)$0$ePx-T2R5=^)%3_MZ;Zj_=vdpvm2 zz`^@*pGuegn31duq8S4H^V5K=pIzAQ@2}bU+==4*AkQN4(F(44M7?jEJ*n4e^;u+0 z{6FLl*WR7ivIRY^?DtqqxO02<2fMKrTXIvWh>4lk<54;e%@(24Jvq&IJFa$LrDEem zA8lbvtv=T_kOnc4u{WPzVlKMH6@-L@wh4s?y_fzjpl~Q`r94+vHgQ6}6p<=MjKD)Aw(i{8rb#J+fjU{Gh{7T98i4&ay(<^yOrFw6<)ar#Neucr+j_m7>5P{0 z$j3phZMWq|vh-*4%EJ&A?qd?Z^1|(5d;Jx!%SnfE3SvhXWL$4>aEJlzXvQaS{p6>` z6`Fq35w3y-)>GFv%^tRZ>1IYoUkBdGYA5mv6D=Ih1~<-@#U|u{_3@a(U`NLFILG*h zsaiwe#^j)0(THpOx-NBRB+M6hSXcxMOxG0%K8QZyDlQWHGGdc4BUdjB?9g7!7jST( zm}ViUBmPqyiAbtuK<)LP()tbMpPK!bJmLHh`KLGjL$(D(ERVm!{<|Q!6j_>=!6I*5 z_`<@j^THzXgZ;Y%?nHM4Ew{lx8_vzix_7Omqae3(wjSYmn-pTj`?*4NSi};xXSRmc zKkOyjMx;EjfjMB7RPRehz}@7TSJ9#NFfSHWlfNBfMhGbE?GG_ET7^8tZQkVw6AqTx z(XF5}bgglpjQqT?NZaFy`Asv%?aUQjFxBGt`d8Y$RQ3nU{8Lw|-LCsH-@s+Rm1*r) zlXE*J_aFJ`6N`2Zj<=xK#@KHUH;a)gpvw=nEuGZ*hcATVuRMUm1EIM^f=?<%_dMO! zpydOy!o*=KE)HV=?4MP-9B~=W$icptnM(p3!(={;mdfhRuh%x6w9lIX*5s$$?@u*Y zn#V3JF2+PpolVjkW|9MBH@9xW2%4e$jEs_l!#HPiTf2_JJ7h!sJii7`2nThn?$UhQ z!lD?oN2?e;UumwH(?iQ-FNtdkXMT;=qvKI`t`2b+bHfF2r}(huVV42_kcbsOT2z%M zog2AOZdqd5OCE~lS_`aoeCzsJbQ=l_ke&FVoc#P;_!#W02Q}Eu*j{S4yBMZt<|!@e zIa(|kDAUraUXauORvA=(n7zLNAzo!n16K@VrZ%xrgCFzg5-{fgMD5tw;l&-uTYEHo zq5Zd{3w;u$O2s!g?3l8Aoq!-6^a+W;Dd+ryML1mA zn6zbEI@f*gTp&ZpfD3*`u1lm8>Y zxoxWE6yC{k2UmGV%lt@s*iT?{Vubll`^~C9xf`$H3l|CwL6k*spvI!rOjEL$J5wr> z#9P}`TkXS`Iq}2NnWACIdJOa=Frx64!`Ai(d&aWaon(5skZo5J8m2JZtp?9bD}dy}giU>E zrfiVixJ@htSGuW+yTDjs-8Kb(Ww=DTBli_klPjqmvmcxJ@z@mYIN7LFiq%+yo^m8b zs+R%RyFc2eJ0E5On{J||=UhO7)(H%^{v8dz;%`@|=6(>HqDRw*y~V+%@IF8@J?n4Y zSHLg!#QG2N5Pil&R;;dQu`#|AbC( z@hV&Uk&-I1h3<YNhs6RQf8iSUd)In6D)9BFUkb^b21|&MhE#Wy>sRXvy$CBqZvF3qm6L>sDIgrp1Iu^=*K zRE=>GmR%CQ0ma0Z?@rl1hUe85Fln8;hyrORGauaM{g}qupEcYK>8%V{K3?LSlpxnw zZh0|78ypL}F~hEIkUc9uBF0SW2Xh4rV_3EM=f&PmOpsG(ez}_80rO4xVICh+HrhH4Tm@1{ZyX(eM5K*Z zt(AQvJP$N*2ns8{L{WOJ(Iy=0P9mMAo^hdS0OGMvqf?g$IR{?O8N0>2WEB%THG{Qj zM5M_$2B2Bp&78{`j#M}Er+IFEt(cbBTw8yZ)OyT?A9Fa|q>v}J`H(nuLpL>4Upi~{ zT$2BWIPQ#l{vF?NT%N*CF>U%?McsCLIuQTQMrk;Ak%2t*{G4PCZ#c4Gth%5l%7zgG zZ$sr8uLb^GElGrxuQB)i4mm>k+6;^wnG_q?0E1s%moACT5g~#a!<^F4WcNVvr8K)V zN>iJ~bkm_6>McTe4P|$|fM}R_xTb?8Q)J(GaA%I*25a&Z(_>1Tr|}{AASe3GXuSXN zsv3kA#dmcmC^S;qi^ol#pO)ZwNQ@LEbFLHJduT8hvnb~aIHAUNj-pthtR?kJwfyzF zh#%~85M_Ib`ejU7F_Q=`hlD znMfG%`6m&)^=!)msY@o`aTKk35dUU!cwYZIF4J|DR}HOw>)nbTLAs(OdX*x z(NOH|IqUu)Iy}VU#(%G<=O=PsYJ|{?!Z>!Bic{N@Qmuo3xhlQ`g+jHA%@wcg8BQkR z(R&vn{yHTP)iMRiE`aF@6O$0H7tKzcg`<=+kIyaPMI})vt=aoF0;bvXOh@EbAfX`; zlsgDu{**#FY8-33H;Fx84m5crdw@5-4Wo@Anj({V!U!;-SCG#grT_i4`jXYI*k?{x z%t#+)NS*@)yZCQLN36#8qd!Ug1~N3|SC7tXc7icGVL(~^S7-@NKt0zW7R@#XMa2SR z=}p%9Fqj_$C&8pJnHrY#^g&k1d!U5UoBnR0hTwh|S?LVnXHXRr1G{TYi%&15=$_`w zWe=L*EqkSkfZ;?9egiE9A0a~Nrg!L;JyTw1BEeQ!`R+QF82;E~sc3=dh0V_V2e@=Q z3`qg==F}^J!+7iue(1PoRvZ1bj@qJ=VXQ0%xh11Fr(ZCHl(c!_cPlTJ3g}MV>c0X2 zXybm$eV}v)H+rS4cZz~jp$@-@tKWkNh(41|sJaXG+u^0%AY&IX9jh7w+)u(Nxeu4l z7m(;U3PPpAe6dTJ6r2i5=0x6PcLWo_%U64HH;U~}cnS;(r8e*3J_#Ys0zTNT%yae% zA`^-XsGW#rB()x;TuWjqDbOtLcGg&)mvD!Nhe_VX1+lqlf{I#&K+dXJ4n&$nwAI0x zTL$@6!$Rur0#p^ImO&e3v)RNQLy|)Z*K?vM82bvcb&&mmz<2*hOuGq9^C=)_p9D6S zXHBh}R!c8`RCPc`sJAFosQc${h?Rk?@7nP&p(tdZ&6$+kB?e$@{$ru#JDv-;&!z!L zLzDUiJ77>OGn=Z}TuUDUyhR2g7;}8cl6{S_H^)gsFDFkHo=4dbMOSn~X42>`r4RRk zG1G?aeZ`9wakROH`o{`fpBDTt87$j^0#cZgedD3^{x=!|!1j&+Y`H!M6WA)Ak=}st?F$a6&U#yDc#DcO z_FXuOZdR8wa}_pu0g`bfx8g(5Dc`k;*rjq>Mv^B{fuZ~8X9-$IM!|_dwymdmuF&&Y zF#MT+wB(ShQ<*XD8xU8Q4VQ-6zEAKLCCeH&O#6dgAerh#atWXitVjKMCndkYquKqP z&CG%+&aD$6h=^)BYv}Cr(&v+{1Fy~97#Z3?5TslP{YcJ{FN3`1Er;* z)_X$x1&5@?lMR4Y;K?!@?ZCQa?xmwpy(yIcV)o&)!bY!jIh~1V7^2^(hD# zjr}20t6<(fSU-Cf9Rhk~+RSEUvYxTYdFWTmT}l@9T8As{EWUv6ETHm$-n^mOblf@? zf76;X)TSizX9?^Hf;bbK{Mn#2t~0n}n^>+_+WjnD)P#V%K6%Ggop%;^Yz~Dd9AVw z=ov!vHjo+hs(M9r_umCs59;{TwrKT>(Iu104DQ4aU{>L)ms%^Oa%%G^UD)88n;zP6 zhAV!J%PGX8r;8Z53wkf&{~BN4R1QE zet-AE2Y6K==P9Z{wzw4az0JjZv-+nGsb#8+ydDla(ea^3|u z?{Nr?%nGmR!ae*0AEyJFgv{MKfy{pb<)Um3L#b7E#57uPH)!^;0Z|c#ZPS{(dTlto z>y=^#fLe>L)EvM&=Amab6}P_pRb0t$Q8KDGn|f5aK@u z+7j6DSPJ=Qu9*a*h2D?xM%+ z%_(M3IBnvG3}=TBp>XMV%C_@*b~HLt!)$<#!^8}m9~@|LQa7z`a9v~xdlV3rToH1S zxHDHgJ3<->}ib7?ZWb?q?A*!#gs0*J?m~Ll;b4f;`G4N9_ymcd(!E! zcCfm1<|O^j30n>nxAu#7^QD1B93Kp1_VAV;L?l8*SIato)rDU(BIJA6^12*@MTjPU z5M0>ZdeQs`3oub)x4^Ib{oFhBV5K_SP~&bIa|ji6ojN6gzl*VGDjUGQpGs>BV5O*=ocl7(K#~TF zvL|Pew8$W9N-wT>U+0FktF-GOXO65cz6PyC`8L=Qb*!Da8b0tX`zBf(&x%+zt$tBT zC8OkhZX69``>V6n?X6)s{0l z5kp932+S!SUA9ieV$tntgkQKSk)wW>*puZSWE2)<)%V@>X&CBIyMNM*Yd|)IkVzDRuM4@+lozMBv)-4Rs&+v&BeYLd@e*sp+%b z&IQX74dGwSJBbKA`_#O@Va?MY6Rq9A_{2tpWKtsJQ9svEWlq0nj?BB^@BMDZminc< zQikckW+!uWl8qpv+|Ke3(}qBuLG(nlCNhbe!wNd&`gKAqq!w4eD_`eQ?tELs&&{B2 z>jpOh{=5UI7oh$$zd9pS1&e#_Iy9S`dK#Db;%4IR0a<^#w>9Hdxt;!5Im?<5&43EH zZgE%YsMq+9kEgreUGImye5*BXzgSrL0CvKf8rC(75XznVenoH9f#;8U<@8yTmz|kM zLZ>g6dDqE1Q80JS4o3P+pPS?-WXzq2NNcfgTsfJQB<{Ohou-Ujk;3$ZUl9!V5`1R- zL%>AL(A-iPej@z-Hocj7^((alk6pLOz13ljA|XE=N6fcK5UvegxgIS{g0$FT-iEI; zbe;uXG972=aF~leH5&bR>RPHKXAWo!yOBWnA7cgrcVwc5*ep3AjhM<6YJylJ|FOmB zxiCNXEUDOYL_DY|2bVWRIsD+;4wPgnFtEU^OV_cD%(C@P`v^98+PH#G{*(txoe|Mw zp#)YLS2ih|BX44SN73rY!dpY9@ znpmO4B~E}^x6(&jf!FVA?cOMM4joEcZdtI3f?~Vl;bp$2p3+%gP?TFuvh5!^?|JON zXQ5nB&eV_YR}~voAIz4cJuU~%pw0;H>8C^hP=tO>la+G8ex;348>(kk6_vBs4~0dPF(tS6j7Bg1z22q0h@t9I z4$5q8Hf2+xU(=Ge){L<#heXOG)%86JXXb+@7n!r77S~!9Re}M ze^SU2U~ISM)JdoA!nPgs{9PnP-(>x#_vxi3OmVQg6%}v^$H&-?*UgFA1Q-9##!j<# z>kYh8TJjJ$P{?9#wNl>_bXz$=obz||8=B&JKHu`jG+Jyt$$)rUdG&$5Li7prbGwk5 zTW+W^5=Ux{_7_fclb@3o#lza-)YeQMQHt|=HKku2_)HnP_(Wpy;M!nu>F57+*)C1Y zr;z{%PNgf~y72VBF}B=4((JPWTnR#+oIN09vELRd{T=2T$*_Ak=6-Qbs+wQ}wr5e^ za4N$|mED8a7kF3Zt@wY>Z|2o7g=7QQ@eq>b9655AmR=IuNFoFYq6$W=K@**E|B}pY z8tJr4=2`4ocUsaq#+K?qC{!+Nq6I}G^Y@Rg9MF#dCdYj0Q428j&3tI|U6>&@Cu1Kw z#uDaBGwL4;2V@-FLDTs3zpxJU7EkdD4!O&c)i2PHQa9)>Yk`b53m)^RQL46u=ihCZ zuR0eu7(iD|%!ZwY#3n~v>h=M@pI_z_iB{&?#|lhd)$XdHu%lCB(e9TA?kBhF^ft|^ z)Wo9}VZrwf^Yg;yo14UH;09yCWOC{Qc+5I}Xkh@JsTB>6XC7&!IWH@o@RL-RSQL|?I-3~`@9I$)jo;!3F6nYl7-vVRig)vVoL9oH`4J^YDyu4I# ziG`@`^2gUf{liun-+fP{ANpAo_Swx@(DhT~^WBCt-9o}|V|KQBclYSGOAelVS~~nqQi02{n)3~mdF5;3T7=Fm`VzB%OV&a6sf0E& z{`|Wyi&%dQV=1{q$W~{5u)W$sG_g{!#3xQauTW3pKu>$x4Jzu&p>39lbS$R#DXcbj zR!GkT!0TsF8@E@FpmelPzo_9@S9hHK164{j?vE z5%qfx7hYrxMAEs7K>TuC~Ny z0qu9xHpLUy)d19D^O#s0ZRr^9YsG~K(UV*Sks_FLT-!?_IfE&8)_NPzLkbaDaS>oT zOB_qPEDaxait`HIg8D`gSReVcstuW~!@gnO0)Z4N>um{lTUBqJCO*sJCLD`-%;sXh zZ;HNgbwrUG?xNA_#}AL8L?5@~4{ZPV3+VtZB9eZ(CaX3>QFTdHxA^_Bp}jA>-v3+S zZTt=yk(?x8?>V-0a4Ra>bJ%RS{Al(eh2Ov-qkCW%tM5DwnJ|?-5Re#G8X!NqF5yV~ z`s?$(RfX`>rvCLeGZ`sz?rP5+CtK9Fn4M@06l!v^I)rP_-=GB0IS3%6Dy%*>I z?8}@rHJ`X;gIS&AcQ!sZ*PmXK!gd=O)GhAN`Idl!aveMwfXu0ak@Dzlu*M9y=O)hg{Wp#ZVegeW z+T`XYD6&)<;|p);YOL&WE^wU?=AtwiB_}q4c>^m_0ME{>XR_)z*#@!DlZQ6Vu^67y ziNtWXkQ~4tbr9*m)9llYWeZMZKJ|_2IuM0RE1<88#TgtZzPI;Ewj{gc^ZY&B7e5h5 z2#{dx7v#cjV$!8)`_b5eKolNLr%}CeDi2Tq6;I1j!0(&MMt9Lb^w##`#|EYl%0^*G zpYZDK_(0Cbn8TSv5SlplX|z8<>#U$>Wpx}jctfU>EP(fJl#TTb z!m;KiG}ah|;h%Jox~bAD*w=OkqY!kRh}L`M_(u^7Obe3>e3TL4$^D$td=DlxtLR}{ z>SpN=X7ybUC~Ec_dr`j#g9Dre<~sJ%_6hppe%3#;Wc7@jKGa0&mD;!a6n=fA{5ymu zC`b{X@BI9sQ^Nu$NTgw}>bGT&<|fVt7ag*q;uo)(8Rz|$SVte|xfS4OxFH;~^jOR- zFDvhzg9TpWM10Yhb0o<7E9qx=H{`I{^YbekhjQRO(U!8g`=A7)nQ8yi{K{XY4p#(; zf1NqO^zhsNb>@`Z-zdFOC_n^O8P8N1`9TM&hQW8JhqJcZ@-uZS@| zpxb%gbRE=NALiDh*;>JuT>>-xCi!N4%yGBkV}X6MKP4HK9VP8f&>s&hvVX(VXkXvw z3DJe%VEk5)f!bG9rr4LPY_FbUGF0;!`##xm)fQ53bmfqCc7_mTY&?!O9+9B*BG_f- zi!OB*FjQd>!bW!J^iK4J&@*f}&Cwk23$0JXS9#h!Bs}@H)41E|=0HjgveAT+ZRJdY z)-5-#y}m9JR)=PaZiw_7IW1!b)}a`(z#)&8j)HM?+Hl!zAjf?Xm4LYfu#kLWf!U`5 zJar7(z54;>%7X~?bBDEEMO@sI1~wMfLVUikjBlrdZKdey6K@MReTUTIaNIkw>MZZO z5|&CEmS*)i8bz}gx0rG}Gss_LaGX)b#U4N2QhIX?@fV_7R4yP$3(O7wQq7Z~?C9g# zgu!AmEnX0FoNaEwGN>#5bIi?JT6%=DspKLq4>(-xax~1@hRh`;rYg&&)Vmqg?vHX& zQ;7fZ_Tc}>yy_sxS(}pR;JQD z{_Z}&#B%9&dOL`%f^bMuBQ@&ywfdvd z9Ot_yf8q&7+uqo)QR?n3&qQwEVj;2LpEnWtyv)eGRIHkF70;xGySM zAmcq2)NrzW%H>vEjm)i+=n0`M!RZUhp|#=;&}L088#XL? zmH8PTm5VB?YD&%G|6oc0Ea?LCXl%|>F<8CU2#sR~8h9zwlpF>$z55sDFm<@)g$M6F zJ6_P6i-w?L&{~jhUw(2a#pjEPc{|fI&h4x9c(E%fRw1!X#F?#RQ zB+~Z}0MVL$T-{i&<-$^OMhWKj>13t;r&oY$c{L%two`c>i zV@hlU8(@mwBV&!khoTOAKN9fX^fkAfzQ_OkNBqKc6{-6rwJ<{4NkX9_{{Xp` z6!Q>;6CoiX&&AHs1`q#ul~o{JXFlGkU5P+uqtrnNZq@r${~O!X%Astm(LH#Hf!1C_ zR>xu78K59nHgL`n|SafN2V~16By`pB;Sq+!lGJh>l9r! zeuvMvc#dU=s5_0h&l#s9s7Z1){t%nTAHnk0f&$gy5>kV1`f{~DMz`N@b{Im~0uov} zwmdT-PIFN_*gX?-gP9*+>z|@xh;il4cezj(_7tOVR@!CE_}$dR@3pwkxxDLhEhNAG zA+b#O`SY(JN6;kfJsRj6`0@T5js@P2WfYzBuO|7ozrTKA)6@Tr;F|guTlW7WxR!r| zC=XHB78jELgu#dnzd`UwD1hJ~m`GF8>XpgMir&##p|}F6Fq4t-uhfH4|GHtnmD=L^ zYuDzNWBk-n?}MNhA7j!T%nE23oD>-z0`J)Bf zv5m=Sll3d@BM{^zV-g;#xJ`jFWBOgm{gKONcG3uc^zCDA`4<|T96ilfTGejCf4@Gq zTN8QxeaM@%(`)8wGmAU`@QA0v?2?sMggP^rSN3dSW0O5@%%{4!k+^_4Xpaye$ZLGF z1ozvZM*b#uh~E#oy-i#}J_;gH8GAK`Zyi&7`L4_+6pYz1dYu$@og@?A2c+_E83-q- zHeQ;s{BfWefr!4@I9ZzBr+4!1Qv&Pwqsx=#Zr_7fLFAVYwnOoR$?X9tYqKRyWBc|= z>EC`+LPau%=NI%q%q&G&#e#&iVTRTp{Tq`p1j{Biz&=6)ij>0ZR1+tHal9ui8rmj7 z6S-njjqjU}r*ArE;*E|XtW2+}cPpEI$8yBUf}$Xe2AyzT*Z6hF5kLvT&^mi)v28Y` zHu((!v?&FO-iqoAUGW|c&q;4Oi6M-Xgt+H7YVwkPoj6RKh<38xxic0b3K*%wI&8Id zJhkA37xL!iJ=9?f!#n2!`YS10mt22>;~JXonc@ADL;viIPCvc^6G@RG%=&4e+EpQb zKV63z=`D!KYk+a>tQZEr{mJK4CkWA29-`8DjMHCzEoKb(dx9jGOFA7CwTuxd)nKN~ zEQ{+cVrJ7npwYBfLF#1(PMGdcxaR&g^ZcfL_Wob=)kL*H4xVE}|0E?oz(3QGl$8g2 z3L2ueYOcV>=c>V{<8kwv=Bb4eQBRhSoa?v}^4vm5h4YF=lu>fP(5{RK6`~x(D%r!% zVj#CJ#YyY_6sLbOt<42ZFh%Dc>+JuDb0X~f8r~5lR4j-)A%g8eupd``r1rS-3$|Vq z67fOvvO|21*)+_=IB-X#B_ty>X*5U2Echy8k6aFuvvqtG{MR%&IZkLz67=5^P zz~ES3b3quv**E91)E#d%S9%%LAf;$0VOtKBlvIh==0tRTqUB&$guRH>&&!Eci2tH% z$k@|Cyf=4IPiky_ri(Ipr|hAz7|1tD^Xcva|1^GS1_aYADBB~7bqZK~J3wjFdhx}k z-HPW@>1#h(z{f~R>9T|Z!a}dnML<+9V534q zj6LHwp8la22&O;VBvIS4+6a^szkgpLw|Z9^7S)_sK*#5nUk#jPoD-m|^$h-I?)@hq zW~J_T+G3AQj4h@8*nmG5HBGoxrPK}0ZnA-y>pdtt#sk0tz`#GV%1cA$ZABkWvWG1= zh**wIpISL%VV>ary!!>5Fklg1lCs2^Q=yt~=?4E&q5jPfe-?P=X}^@r*mIqhN9k1$ z-J~3nByJsnXnH=nuXylx@w+5tnUq!)i83gLGNN@)wNS?yF)tiF|ELB6@yWAerN@Xs zNWQ{N_`!5&B6HPdurPs)@-J|v`sh^$nUQ7ZxQ*iMlH}G3ug^KiA73J#ZW@zNRU;4M z@T*NbWg#ij0bQOADhjP=U>TaqIp4$&&O#cSKp?q~kA%*-L~^!#26qsJ6B;Z&S)X@X z#(L~iy}+AvEKmKCe~#u2bU?-l*!+#uZDywpJek=5o9L?-F~$}#9S6v|P-BCA6~I$_ zu<|8r@A$}xApmrH$ywTu6+tyl$)*=cls^$I5#1g_L@>e-d`O7W8NK#4xQxg z&lle1|mBh2#6!S~Eai;PhW3(I>$ihH9rr+$l+V1Akhyw3$; zJ3~8%^S&AbA?uh zW70e=1VR|ySlFFv3cD*1Er>8`8NEZ&6uEQQZzopp7i)Q?j9T8lrGMgxM|m11y=BD2 zMyu*k3#Ynd+`I37RVzR`2-r*a%|4d(-3@wmB^rZ<7pw;FXg5$}I3=i*U zIs8MAXyw%D!=STxC#DiDCa4R4fmtqfGW?kufS=5iTW== zLW)qYhY1xfn-Y}IJ0WrWmHyj_VrqYuNNg;KTy)LWuh)P3MWNW81bB%q!bvBWBCcaS zgW43NTOIf5y3brcGY_pNbAh~*qeD0SzwVFj!cvnGZk)Io^S`;=MS{}(E-2%Y`36Zv z;Qzi6Wu&tHV#@aviqVO=E_$h>^RiKX#e1MV=n~)=%}Mq*4u~Zn;7r*6&Dq$WB^pOx zTwrdgxkne%1nPC2&2+&N732KJhtEl8+Y|fhUg^v!lk)-0&}b#p|CMR!k*T}H!u>Vx ziF6Uq#N|{1Hp zaUNfe#d5`dMJI$M-&q+-L&yCoVTIJQ<(ZcKsT1ii-^1eYs%agQRoFQJvs`0D{}CY_ zj@tCjqcJ!|EM|8w-;GbpM}_((u1ap{yb_R!h#R+|OlN2rwh-;e9( zv$!O@Iwo3{r^t&VkZ-))yBl-m-elVHeS=u+@{Ith~j+)ueHTzew(Z5#Z@TbMsAqcX@LUe;PSuySZPG_pf8)S4R@>gE8Bvy4#z~tAy7}md8_BYD${c$0NP> z*QcR&*Y7I?pJ9ETf@dC`EP`+k*h0HwRbF{UP$n}1f4U4-1eUyyRY9NQar{LaQ#P zhs704zscH#luLogZgpU=O zR&Nex1c`&A<^<&pekho=`o`Sb6=OT)pVJyH)PG!yF|yzm;>K z4R_H~+)-dO1|d1O-@OK&X;61gN3FuKpf~~kshD$ub3ELFGAK}EC8H^zMt8D85w8ue zC86SM^^9C;=+@YhOsiZ+iow!$N+R%u<8eG!{C%kS-2URij#*8`61=_&#d1*DExu0~ zS~j~Ttj|oE(&ilnE2)`x@rxVtUbXma`+X8eLYJLJsu|?!x;21^l8sJzV7Z^_>Td{S zp_Ddmphj^D6b%)P!lEnxd$Ep~JEQDo@B}X=`-FKSAZ>eL){Z{q$=vykQ zO?*aF5L)#U+y5C(G9jPv56M)pDwI#{y|u$&@M1n_w9iC+(8ib&lbIp3M?-@TfyV^I ze-8^I)>7_!#d6Q@I_-0bN1mIeaYT_b9Py>tO^{8gwZ%KI8Mz85wb5h^z}MOk2g_nQ zx*i>E=4q(&Da3sEucZ7$38?PKQ4H;Kb)D(YAv6Ud(GxV zz+1Hv{FKsDo!};AIMC8o>s5FQaq)Z6CS)|^en z16-k_tSYr0e9>t)j1Xc32_n+#0k7W^k~1bVf-tv|s+sb|8xqvmOv1N%lA{*ik}tLf z9GtWNGDRRV$rafL@K|{NK&uS zMINhav-X*F|2r0iy&6^3HfIDpt&=9U>Q$R5hSp(PD7Eg^PYBZzTay5Ow^j!fS!;7F zh$c!H>qbm*nq&k$(w%s)RKsa!3xFYrq6>=~*6zopRr;!qVAG*3jf-O;9MBLJ6riEs74T4 z;%2%RGJ~M}rD8iYXB`o)wag@y3}O)-7(USfzlLj&)7boJ0DWE6tLMN@g7%a48ElS) z0?n&~08!M2Lc)V+S4hbMBOK1|kadxQcKY*?zu|U6!{}Zjkq$l26bWGn>^q4qqkQCY*Kpj+chp6$a`Ntq2OPc!qSXx$ZBx zJKc(4-^!Hz560dCD3YaV*hP17SaflBcO3?IcV}^T_r(`j92R$XTU-}+cXxMp{yFb? z&-uQ4)QZA4ZPLiJuKdkU;qb#R_mVypVYuIEs5WDD zea@tE{_KUd(P=vnh(WJU^sG;<@mP>q#CKQg@Cj#18*TjTs74hNK_gu5lO~i1rXa>C zC<$td7{9QgVEmxLq{bO*y7w%+a%Jx;P-j+IT!Gv#9d6(V*mC_~cml?F2!-RwL8)1m z>V$^QZg3b;q)#yeD$>sWXlnzAITbvPeAf&-h4#H%i{y?qUy2Izm-kppJJ$mG=;hse z139h^gSbeTawpsn%W2@pmBomzQV$uXrxwn1kW*-eoSuGaR}X&QZ4+v19L^e$@1*ZX z1qemPG3}o%{b`f)wS`4G%nAyMGTzsrw=fb%%|Q~N_9uge@L?BRk#gwBIg41)Fxb=( zCDeU3K)3u|A~`DclbnYSEO8fEiHL^aI(aYE|FwZF^~uWDjF#>>Pbzbuu-AUH$n9oi zf>+xT81&;(KtX=bjk3t~S?x{`jt@}{u+V+<>d3M%5X&;26+nU;G>{ioZ}?b|(=*ev znS4c;;pAs)1SW+p@u!QOk#a^5j!+IN+jCELymNX8wjN+TilmB0v4(uFJGW{JrXmsq z8GV#X`=(boNS}-=Sb!v$Tla)Cx66BHug}19qI4yxNQ_X39XRDfNFV?9N9bp&0UXaL zhU=V=EE*GA5Yx+Ts@`5!i<8-k*Rrj?=)w`4#~P`6`ra)&eI4pHwyVwr;_H;Tkz$I} zqh{5YdbECo#4RR)-Zz}w#j=K zFb(am^O-n=tSSehU-7UBzgNUsks>>|5nR(Klwt)?SFiHp{B3ZZ1y6jqGY- zL#mAQyOiGhM9>jjhUnxU)qWgnOfhciqQ)DNctugAyCrvu3cDb-G+!!dp%KUYh&8z18JwsaA|4v(wJW=t-6MQPcx9Z(9U? zaE3R(EFyjg5&XlQQ_6K0-&DXJ_(>2gp~C9AAI)mUEzKJ8Ey>5AtWPta9{ZE1*nWYW z09xsRh7sHH5b5BCj$dM5yrz}`e&@diZuuoVTJNNzrk@KKj>jKMM)>fBiRdUf=fTv=zy zt~g(htGEmV>j1QplOeKZRs-@=jEv7>OnlkUQgzm0#z=C#FSd)-x=HIuyLEQ|A_6Hy zcImQBU!kuly`WoVO7D9UZv+!k1#_-POU|zp&)P^c zNUIr@i5Am*$JShWzBecjf7kf^=Y=5HbIK}JW;Xeo64h*y+QU|dH^ocH#MYJwl|42b zHKJ->_pr&%PHS+$!*#DLk~LRvJ~C!p^8vluuv!AhN{E2AUM%$LJ)nU`smci8C{E4G zN_uz!rJnZ)0%^DNP6IX!u_x8$Drr$e^rzCYGwa=Xqi(CciJhVmZqLYC#KSTVD+PV$ zOcrhwo96^1d4rySXUcUIsrT<=XObddJwk*#Tg*st-TZ2+(}&AoaPY`SEA9m)>GUT^ z4lNE`Hyrc^rU^I5Ht1LhM!yVG*cW^V1i=ghb#;_&Js$alqL(HQaEp}(V&k|7Yye}2%&K2XR15C8wU)`0 zR{MWS3xeN1(wftY>l=z+j-=lW!CCBS;p4zN4 z8*c*?U|{}c9yA3?lRHftnG#?MHH)5cp@2;-JSWnW#fyF{CAAEiqbK?;b5SgP4t5@G zJ*OGZ?kptI!;PjeK=@K$uzOcnB(N1N1yN3~k&YxSJQw70hx5!|Re!WoJA87NyBa{Z za=>!mDK((8X+f91d;cB|_A!^K_qYiW5VhQQxPE!_&-!cvhf+Sa*?xCK=jnp2ZC3n3hvB0wcU%3&`h6H~ zq=Xnx*3me$#g+{b9ZTh2KYQW8B=J8lnxq1;B@0M(rFe}d-%q>hhOkO#gr8e%{LYt{ z@OCs^_b4vcS3%34vAq4_nbo?@%h=w~6{j9himhzJ+a`^U4H!0T>dGcy&0Lm&VyuYx(m{8S zXr!@WUgUH5@jV7ayG$jMf=Zc*=e6~`N`{a={1;d)Obc<6JR&W$foh1NCksK#?K~3L zc(85{+fj+`R9l`92L7Nc2+b2AcOY-Zoi+HSp7rnp^dxa$?fJXFR(Eql;GznJ6B44z}@>c(o|#O}7{ZD9!+ zgS-%V()EbY!*FNtcDEGW&bCIATHs!A4x0*4Y3S8a$^CBwcOKGU`%u)A=T9IvnlpPz<>3ddc!sU?x*`|DNaE>6)&@b|KXK znU0wExd(#myGV3~fK+a3E~56b+OM0RDS0m)#{2hV^CpZ$&oeg(Iby6kqDldgcxyU~ zRr1XQjV$COKG>gy<#T9Rgh!!Rl=8Ngsrj9;39!4Ij6zWGOTi$1MBxsJEXkOdMWC=@ zFTPAI$as=RJ~RZy#OsG~v;F$rtR9nZ3iwOqRE1RQJ2WZf5OLfBH;O(c(0K1EV={m@3R@gUPt^BBaHJ+bLgF z#`V|Eow5$tL-`rY+H@JUMuu7!e^NMbXqU+;+T(T`ZvUVfGKrXBx<6lV$*jIwcxz72 zY>PQc(-U^d1@j3*G?Bp@8oDaJ-q_oF1DyDGcxw!pE$_+bccPAnLm%4FeyxxsF{%xy z_2H>%Bu@wMdvs_0xI{@f)-WxU`!i__Sw0v^fq+%zs$oCE>#@x*Ka9@nMU*R0aNhd4 z+ecUKHvf$^W>;Fjx{)bU_GrXCnsGAmcQz>Mo|q@wb+hoPi-ntebH>V8ZRty!`a7R( z%WMB&0nfbkz1i9}Y`IQZaK9&wG()yJB*638D9`=F>ou1qGSO*!$ekU$U{yd?lv~`* z`_GXtRq|f={RXv@6$Bd&H7y;{$-$loqkdPe18HnJMEjHz78eI*2V;myHeb^1 z-b0dvI;+*%i4Cs3oadek#Z;G>mG4;pJI;eGJ*C$UvBn$8j5?zkK~!WiE3zW11woq9 z&JVS(%OPHpJEoT%Mm^3Fn-#jS3fI&?y@HGRYMAD2>3M6UgEv`N>t(}2-^6i6rgbvP z6Wvki>A^{g*p#n73TiTkBg}^0AB7Hr)9Vw)QbMcCePfTReu~E77FU&$F|vVqvKFps z$z^tA9+em*%V#;P@U2x|KMK~))@i1sk86kB%eqC#;Ta1Gf=P3Z6Zu+$sW{Ua+j{%P zlz+Ja?W6C1Mt?bxODdjJT>~zNy+;N1R%MNqSJ>4KIslQ%M+~-qkvC1GTGR1#2hfqG z+@MKlvP5gfCAL^4qWd`qLAGlQ3Ng%GMU;PHNs=*|KZd;@E2NcLN=Y2?mww|_Idz~_ zX4oSbKuPTFp4&nw^ryv=kFA$ISO$Z^k>6(+2ssL3vU@ohjc2UcqI}V9ux!4#z59==p0PBAE3P=9q6=Jf`5E_p=jrI!`u3<4LKeEiUxFZ z@M`|W6%8coPV7lbY2I+jb6Rk|*m1GoD4U)clmTy^m(ZMASZvgF#t!#9KN*ePyRKOpNO)y zjCm%$X&by|T51$7sK79am|ReCzzcU0=3BeKH4=J_9jStFIJ zdTh0+QcJa#oOfk25^0?=M}O2t>l1h1?unMN9-Ma0YKG7_uI~?W$GpQ5)c2Xzp2TZo zXF4~;=MOl&Cf|>+<%bjcyM=BejU*8`av2X>(yvuElF$I=9|%++fi4U+S<(uYojD3< zPjL$m2#H=E&X4X~c^kb<62;q8-}y|vb92Sla1TXb0*Lrna;LfO1yT1mKEi_syspV= z7<+54W)kyN@V+g#z(;EaqYEtee;6w#WI{&}-ZcXQE~`efs*5!+D|Nftk}YffmODN+ zNy(2x@m{|1d?9acYb$jFFC==U4Z~(GXS|<6gAzo6YOR*Epp*Tcy9)7T7q**pyBRy; ziR>j*#+lm^7hd!H}r?&p_=8bd$G#1PCRaxczmR7U}okSStdR9MXf z@J|Rbr{e4SHSxKWQw0Ueja>})%Z{Gmni!XweSE4It&%;=7l*5Sa&aT-k5LQYns^xS zYDX-$yuB-DydnAv)Rwz98n zdJ}?!6TksIrS49cn)YrZGA>iNl#%$!-e6XZTEohU!o$liwft3L=Xnp0@7ML^(X=Kv zH28jJc~<-kA>@qvo5vcK_w6IyJ3dY2KC^5{r!u75+g~uP`9>l;S{<`sU#{TfI-bjC zVo$suZ){FWajMA>(=Vy5HTj1BG~Oy`azCOB@F9$E)LTY~DGuz-+PH>TXgFqI;aSIJ)sQvxWO zGV^$mYRhIFsy9!+7aj?2&wvEJqre53m)|@Nq#~S~J z)8ttB{S@EN*6Vn~^}LK2PpcvL4C8E|KBaRjqgTrJDgJGD<6;bU`tsdx!T`0aPq-~c zQ|NVjsaz(?C_xLHyg9$>dHOwwlqS-M@aI7F7SShJoCwt1u$b~$U0QOpfiFl2Eu4mP z=2#QoEF9_b=KM8e#1Nj9PnX>=g+qzOEPp#qYb4{19DX6D+B3DR)GeU;K=+bQaO$ae zptk-Qk|_P#e0#RoJZC@GKmDy4udMoRbH^5oPfU0pl|Ia2tJu8oT#LKqO?*+?`1~?K z9s7CmP=_l{M_zM_8mh{AMbZw>+;mDX>7D)E)pnX(hxN9!Dan()KSq1kH}T>DLHYe#n*TM z-boB4pq1hACY>Wv)oDA75GQ~}1N^(Ft(dL#medXk*_-MGkRBn zU_Z|1)iN}jYqG;(L=~G~zaqelZzfo4Ekowg0j#I1E_VLFqa*2V>hul(2Ao{?D zm0X+fbJRG06$-_;gpr9SUtTCpj1}$BN=6T6yBBFinn#m3`p@}s)4lDhUfyZ@=SzoL zV3n(f)|<|?wOT>{wN8Rhvb{F;<4fIFp4(#Hy{s<=#dtS9h@!#Xk5igS#1+%Y*t_S` zs8g=_pxBpY3wH?v9wbz8DP=Q*lf5ibh%S2vORak_1EuLBHta(qGlR)&af-si3X;g< zJ<(C;d$5;kZ*yxer}EeRjqbGPd>>YFQ8Vcm67#2ifgX*(yo-|5Go zTPaY;NVEA>l+9sFq*z#CN@lFy@%o<7KwXh>-%Gr};WUtJwDSW4KDtp~e41frK=uIOsf3rJJ)6Gn_e0;BH3#Pb^<-Y|Amfg{ExqJo>9URjvUPry zjNb=5MKLzNT+Z-_49$ZO|4$50^pPXH3j-qzsmU2c?v0BvJ+FkWIbPZPgz21`-?3i{ zp{};6YHZs%`?^$6t`0sfLu%}HVKtQx!9^d`C1F{IvnSlyMDN^)J0&~FQej-I-3Ste zBQ{)xG98o6t3A|B3S0YQWOn&J52ZqGHngND1Q4Dal`!fDW2X*KlQY9aWnZr-Jv zWHP_8sf`n=7JLD3M^tGvA)b<{+0oVCzwR6;XQ#TD z9GpjZ4+Fp5u96#5BtP2AGI(NliOB}PxDfk}ORej(1P!+-pT0g)IGW?J9u(f_$-vO6 z9Z_}YbGyg+ z=)0YRUxD~uDU#1%SqSs zO~@w@*ZM|UGa!l-y!0YCGbqg-vZ$<}Ox)R)cd6+zuGouKuA@T_JhM+PecwqZ2rYDQ zF6hGYA0NCPt9##B>uPSY-Bq3q8#wetAFc$E*h1nPxFR*J%)Z%E`|%C-0J48d8+o~t zdxSc1E$34>$l=WB>xNw4W7ej7+L*l7sC?zJ-{vvZ6kN;)P3aG=^okR2Be8UFs0>m) z+8X%@o>r4iUw@<4ola~vamCeJ(9uxmELwo$fF^Dn<;+Cj!%bLAEo8MLzdapwqutXf zRr1SqLz=hgxOw52LZeKk;-FX-)RfwWo8K+LUrT2F!YaFi=t{!mGsTu^X|ek;F$w(G zymVXADBD#1JkI#@NNm=utfde(hb;iD{2fu`Y&emw5Yh+gxfhf7hvz=$9bqFM@xc5> zAWFFV9sT=#>Dz^iN2}x*g9{BU-w=>smX)9}u|@jN;jBdhXijr{&eh--GhTSNg}405 zP~wRCxv{9mJUx?cAm;u&iJBtH^rD;TNVI`Lk(I{-yzG~VlE*ezD~%qRlOsIx=$D); z>)}js5^`fR0%zE3m`JmkadLC&t-}uCuc;6}7A#ZheaS%iuOUL4n~i{rN2^` zp9xIWSVN>u^F?UM$f{YIg6K!?^IGw{MnxnntdAxaOBn|Z`pzA_$Zh#X_SYQDIr>;x zHG{{mRD}PRqjD{3j`Hq*dn$3>-ozZamTR``&(N1z@6N!#{n11^wU@s@!K9Zb$`u+2 z7`^|dsP2w-6i9A7iY*)^owK0}o=@)^HsuJ5%YvNi#P>D|G!uFH<5=% zxN?mYLi9r-W1tZI(fWqixgLz;*z0Qc`o&4#SjircRk75ADUK3b#hBwb!ZRQ31mM(& z?=Kyq-!*9$pMN9zy$K;&SdW+ffm+AUu=jn+_fc$4)fQ~phIUfOWN5AuK2ZUY_CQ=Y z{sjqs83Gd010$x@2W0WcE2jH(Zf$G6Gvo1h*Mwt|1;=`dDcw6TJgIWz!=YhH$_Ax2 zK$9Pr4L@07d{32JYs!(D(NrtvS-|!DO8&)g-vMIRdO$K$HgDxg^;dt&1JB$k4cVG6WG?XEdURY8x2Hqf2HnFk zG#|3;la$c$LQQSRu9&l1KW=C9_*UbClB!KqUucq^$kjr8m_FM)yN4Xz*|Z-eK5>^1 zxq0gT@vsc=>(P#<%vRK~*IYa2mZb|UA@fR$GJ5dRzr`9{+8BD#mPOaE<()*UoQXFImmqT+J-u zx~OZ;n^5hPkBimBwfw^g_QVP(GAI87Wdr)Eh+1)pT~KO(jw?n=jBu5*IE2C0JvGUu zWQyUAm?-z%mZ>plB}-Iv{nHEN$-%x%paXq!YYUd3kw#Mc_k>L;SJQLSfeKkxhj#>} z0O`fo8-NWc?_rmK$^EDK54y0&fSs>k=398fd{)d{9x#@VZ9oZ@Z_t=KzV);M?W`hKp&I>4VCMZq0+)>`J3ksEsLnnA|r+OjBK z6`V@5@bep&8wRVT*Z|b+5N^_69%)Cd|9Yg6g4Ng9^G4#A`yGpeG_DPaPd9L-z^Gtj0)2qBhEq`&qSqCRPfo%iJY{Q#X~V-)^}Cc83wb zndVL1QCn2RdZLRA1V8k=i_oyaPEpB{@9H{_0X?47Yb2)3`|A&2n~y2jsU}Ay&Gt1C zrJq;rLP4s(k|-1?eNjxO4IV6=>KPx}+M}czu>Ry_OIMH$k-$8GTID`TYqQFfDhMaA z_lwa^W?Yi53I%ghM-R#EsJ%Q*{r=WGgxeLm+xJ7<>R(p84V)xcRMbyc3@m9nq4 zZaaTUv99IamZjGAZv}^KK59VFME+-nl}VSBX*qB#ms7{z7?$Dhz58py853uS1VgE( zEndq=4Vh&hNSN>rF!WV|HCX}p|m=t+K8amb|xsB~ph zAb)+=&3fPA7t4eoX1fWbeV1z|X?t~K49{f0OejalyGRs5f+)Bm4{B`4ha@7kA!RsHip2#r++jAG#4+?^>bbwWj1*P-dO@T_iVcrrPwr)IC%<@W%a8j& z-SQzns6et)(Ds&m#gp;k{=yTN;#8j>i7y$%16BYPhYsVcBa{2rB5w!-5i5I!8|n-* z$j-K++x5mt#2H#aV!LVt{P#(;7EBz>$zl|4wlT(Lw=}#^>*T#KZk`{zCM8lWvNG zT>{!Cqr}R!NT`qr99Iu588@s~%NIn7?{HCJ4DbK_{Vi8Y;@u+IM zg*En*bq{fr%b_HcEp97}mS?OVf!n-e)IRQ1Vdr4Wt`x^=R$ik!T;6Wg5I^%J?xpK% z_;QnueNZqoPwqf}u4J-6tt-w68hifhyRI6ZTdK;%RC9EA=I&PJ$)xrdoQZpYv_yh5 z*Kc6x83x5Di^zoTAKr}fQ1ilX4_@e}%FGUqd^lrJN=gTpt-DZ2Cha5l)0s%H5A!bV z@st4rH1CmH>iS6yB(YB^6qjO|fvKPXUW*s$emGvuL+j^y)_wO6h;Wvo0`9CR5 z9Kl*3CM}I}L_)`HGOb=#x$wP!GzZrMSYXQ3PKPH0KM2Az$p{ZvONA!8f&Mn9HTEQ_@1@&vSYH_0a_lI zRYv!=^z)=p*DZ>IEheKiDL6N}@yeNBpZSVkDb`(Y1^AC+ekrYJW6i)OdmRd@<4S~i}iu^CQgldS3p=+`9Rt&fEj zfMfDxW^BSs|0)0QDSbHe&>Z~%0-eZ? ze87%I`F&(!B7>9YtO&wcTIJTCD1)R2Kv9MO+n5f6C34LFxTKxLX9OJlPu%Yfwn~vq z?AvSpFk=l+~KG)DkMnyF6sI_cFO zS5{b@3);_MqSSQbpi22LF6JP}ZA$%1(`jwM^)t$RAK!r3(kDK1I^Zl;Mv)AXNE&}Z z&rD@CQB9wbdH_3P4OL-k22i&L*|#NZHmlrpdHe13*!t;;z&tHt-o&Wy=liyc!e0#3 z6aN|`YkQ|MaN8kwXXKi@Dgys;Ocuff%tvc1@4>&zeTGofqqKI8VSOYB# z2x|~;e(k#TyzcOcwaaj(ly|Rq?~Z@5u1g}1>#mPP;R#Z-d?;I<#7g)^k(%Np-cm4; zwfT8m93Q5A6d27VKa!9cN84dMwl8!XN>Ocbg1okmug)`1pWNRqX?sxyLsUM)x25q& zP8IaWCw02)@K!8ghk{9$H!)151)-$AXoxToN<$luwD2@P=lH(a2l+bNQOH*8Q$pMc zBY;P2jyUVCTrS*rY#b49^_{2L%k<_={QQODRt(Dx5R_0~l{3t^=?pDm{@YjvDWBp3 zp5N)1*_`evm1TP}f8b^{%5hZKD5c*0Q{6UCt0~w-B({)qF$4?|k1ZLR32S0OA%j-} z$#jwf(=B=n32Uzm5h*)PWyZE}Q4ZC00pp_f*NMVglePh@Ln$qVJ{fXS0M64Y@jWIt zhKeF^Hv_=rTORM>dn{G*DwNJ z{{#_sQQU^#6ytl|$oL!)PsqX7h~%DYb1AG8(GB zHru};3|94`=2P$^Ij_90cEA-~(X~3Fx!axNt#5GS>8>xRpbB{lK~OV`)%u;c{cJyY zD)M^8#zZ?amni)a1J)fzh&#e0z@esOeY&JP`ZrhsoKVbx6X-j1sPXRnV$PzZbG508 z(8|K46Dg&XCoA7|x+pC33%9sUW4#?3k|4L^cM$Ehvy$3G;d}2wa$pFW0iAKu%)3Jp z^2wu2Yx>cNy5UnX*qaS>9=oKmjG97&{DI>}+(JjccD(i^R{GX$U)o??_yL=iX`kTQ zkx-GUCV;!qY&YUyDy=YAx9vN-;6bxB;#PA_?CK+1C}=*?vy*F4fEe4C~#iV?G7SBhpY5bcif-`OyXCO%-!LHyarT8j_{( z>QhFdUd!p^E}DmA6Pqi=PfCm(X6!G3p|AyoG2e4f4O3yD!l@`4J-%z;PIm1{bDkY| zd9K;ssAZbxG*zRHG;v{8&VA!{K-0vR98M>r_@pfuE{eMoozt_LV|hzHCX@AwnubYB zReVj!^Xc~GHY2|$-U%=n$+uPiJks-`<646wZAe!aN6L(z3=@&oJ-sI>bDA%zt#7}o zH<8b{^X*a7`QRs$Ggmy@PMFx;H|RrRzo^O>zn3-jtvN5x0~qX7y*P0LJcwsF+e3~;z@JfZhm*PD z;&&AHI!8uc*1XEb{x8VI+1!EIAg4XK4~}#a7`gZ=<`3|4b?T-?8ABn|lY?Y#mFWN) zQwVIQoiKAKRT)0CK+v>0^f?=MFQ_KHR!d?^PFVYr5}|l1|1Y-#7v=+ZJfI|ANF0^$ z#QX&je<(kPOYH|nCX_Cerx^c=+b7jyY2(6BfxIum=ll()PAgT#$I=b2u3RVkjGLE! zyd3a=*q(4FMo0Uw74pFT_~wxsSSsStm3N+-U1{sbA>X8e&J5jQKol`eSa2DBT7y2H z=sd>*Kw$Kcqcg%}$oiM%%u>Sn;v(w@*ivWbCeC*iAIbSo8a!?^)Hjq&j2ixbAqa60 z92X1C=Nk}gnD_>QzhXz9VDsrx2Iz*Q*6O9gfjr&*5db@dkpdpy*g1jyIEzs&z@Ls1 zQ&DQ(I!A8%62B0p;Q}5t>+g3Ui}x;&j0u|={cthnh2$c?HOnVHz1)qNQIb?RO~lkN z`^~A<{nu$Uqccu2=$iizs>22u9%Lr?MeC~+)HurVVOLRPC*T&BP#qjbF>;;N8npb? zp@otYo2M<}-M*JtgD6(_LW&3cX}1UKn=263aoMVJVCF$Qy8Js%6Ktb0BxtdA^k`Ikh=1sVCL?ftZ}2^pRC_rCX!Xolkm!LLe`;7L6S0MD}dsqfn`# zd|CGGm~DEW(b%&Z!^wu+qZ1%;e=weC2mi!-pOc!^ODBt(QsNKtA01nkQ7dTLx5nEBGu_7C2f`}1)>7pjBU!Uc(5$L;S_7v8&g4qUQ;JqpGhQky z4(A~9xE|?x1s6ClUX2&RGSI@vY1OV?0i2g%mU>QHvmUNR_O1erOU&w6xHB42&+gQx z!UE~2V7?voWA{cQeusN-Zj9-)LC#wkr=a&C2xC)rt4P49&)i1pDFh8jFD>zuUD9_+ zp$|{}2i(?Sx?R)cphPAZFZ)wP4;O~g*SOZllNIJ9lvcPdH)homyuk&q{!yMgbi6>% zTg=sKx(|1S3HOT16aMI7^x09Z2hWuYj-$kd6cNa*il_P&ign$x(G796S*i6j-n6qa z+{ZqofrsaN=vuYF+P(XhW%7pH z(h{QX{fzqcnF8=H1R=zDM>DA$l`OLS6=P$b)2XpaiR^ET0`z$+H38Ya8Jqt`6j1o_ zMElV=zZ@!w`fnYcd7=J#OlW8Wpj8IHY})7f0#12s6bXs%$5(_KC%M zTE+J=A?(Ae1uy<4`nB7`U|;&xIZkVI>0cqg5)pj%9M0L1cxe>$eoLx*mCsv2&hktp zmP$!2qhL1sm-aCD?v8l~jj$8k8@t%S--ESKzWIRuac|cX2G^i3hF!Q%ofcMQr40@( zFCJy6W1Ni@NB@sBM9zJkFGZiO?SRR>b@Y3$3n@J35X46P@vj#Kj~}h0jhvRnS6*;_ zPugN{0@6apU*(^Km4}ja%5CqL8ULY30*IQ9U9*b_c!PI~I`pOJgX@h*2US>&K%uvsvfavE{#)1#kjD@wCw89Jg5?{gi{wt)vICJ|k1! zi7R8zxySajpjyHhO+SLR<-}uh%MYdLL&TNfCK>VobqLT!qd#&M>UnLu*}$%Jxf;i2G_LJ zA4e)WWODy)$<46wP}}E{C&BF-K2;xZ-I7I||B>8bS~9zcNQ*W2;z{*tpi@UY$m5?{ zV4{Zua0suqc*}GNYLIs zT7BK>%l-k5j-x&kQp(Tv)-{9+(HyKNDks9@_gle93FXr?Kd?_B$0~HHVwM`z37RHE z{}~8~NhVLiI|*Ai;7K$cKDq!n9X5MqEVSI>Cj6irkGGE~+>4(Jx|1ZJC$Yd~e~_BL zR07PcnjDhiDK9SXlPYFio*@W-bzlzS_MAJOe*C_41q1~>UANUIp4giC%I6s;&Szbb zzQSw~G}`*dn!Nr{ zt8De70PkpH>Q4%R!!^Tc`KbACf9u{E|7(bD_m}G>9r|)8+iJR{uD@8lDJ+pp$m*AG z+}7Q1$HC#0ofQb6?hXBVt~iY)DE)(wcm8u6j(ZXsv>L;#;HVq9sodq>^N^`2LB|R+ z5iU(^rw7U}`O*B0W15x6m=3ldHp<>jwlUleIf>eEgqeg@L@qy(DK~74?|?jhd#u7f z=Edy`qA?y>gm#^1BFFWnh41t87L)E-Z2aFlt1i7Zz5c7c-SHHry-ZVi51@rxIi04H zLxWm}Q(UfQy`fwz?;-Bh=dR464hqiIy!`0OyY6x@rL2~b%&{@+GDp1E>EWR)=&LRG zK=-`rFn#sr4l%e}!6ASxyW5-fW=cNTdir)xaGosPb9c$ZdBSLB4*zQD8ISD7tm{Qe zpcMG8UtSt5E)Dj&5YEJWdnIMd9=Y zpP0T^!WnD+2-xC(Xfla?x)fveqQi#_xCn--<&iOL+l{ELPplfHZ}XYyP6?HLxQ_8Y zW57^*d|)C>+Ht@kx2k{V1CAyY;X5rb=u}sqq2c;9y0poyx|3V!J0jSqtmfsMGhi`j zEWP-Zr#s*TPyzCGcRk5_R-#r(KXh3~S`TxM=Uv|3BndAf3T}}ITcDl%p7KW3m%;QV zpRdxQFI=$)r5=FD2Z8UtbT6^MVO%%&n}{f3HeUE$Jzv$nv@5x+y?WlZYRPlQj;!4T zqr{8?@MIp&xk=s(1<<*VpV3R(6S1gch+hhPIqF zrMa=%?{Mos5cVU#fS$O02ZJ{wTabLnv!X+5aHHK?-*y$z&e1m{sK@H+Yb3L0NBiS% z`k887cgtQ3e*&Nh=~UJ3(SJ{W3oaUvpqu`5Z6LwQ_&UCidWl2;{DG`aRsEH&t^ENB z@$vFj!B44P>X%-fgV;vqx2M!mT)Pzoh+(sY)8xGcm+2M{U5g;X9mt$*!gGHv1;3=u z1;Kt+-(LG9)NjYDM2>pqej8g6!c>~pA1@W%6uy`K0HOr3N7g&)Cg1sf^|e>$Q zXLv9|(|5XRdLk!EA2$>;y?B^rzi(0~ep%a(FNpB0ekNNNQGUL61EwtF0gkss_oLT4 zc3Et754bNE>k131jOB!R13>9rBEPRsbRPtoz4caWujKzVD7L=L5KqQKB>V)?k4fyZ z)>dtPv%@uh>qkuzAyvIqJ>&`Wvia)k7Ra+5?LBs@NMZ3>h|4$c6I$@sbE_&txFHYn z^1ib%%NhYx`oSaIn{X*Wc;5|RvW!CrC!T7QZ_X2@x!(l5)ngWQNpjC76*Uil;?WI| z`6X2{&H)&$6;Ky8+Gd?A}48Ma0CRTUtce*c4Ags_IO$R>Y$nECy`73 z%{&CVn`_Jg#b;#wc+|g5NslSdu z*qfI3>B=fCvI>VDk5zNfAq^Lcbr6}nLd7|+9-wmsU%}DgfXr~-;CRCDQ~fb__s_`j z%(7Gu0Osn!f|pb5S~!dl7!A8~kkQt=eKIpNbzYaSZg6K7HKaw{A(KH;xTgM0+kFtAo24`>^iIs?yA9j3lP6eB!J-@Tfd$KB+9>=?=iM( zDAu(u)N7o@`CIX@ft2hY4i&$+G)?r$)EkY4Sjsy) z&3)kVXiA9}_esXNm_Y8Qm6-cVI`oY$>pGa|0_ zb!~cxkg+^nL&=IT?&d-htj^c@Vge&BNYGu(ij z>S3^h-=Xvv&%8#cYKQh1b27Yeew~P6*l{xO?O`G0>8kyY{YhG@iu+^3H9M}prokht zugLwq+do!l&H&FRPkw&B9pBq^-BN9E{j3I2cCgYkIvw*nlT8p{SP7Q`zeAX~=2N-_m;*r)+ z4d1;IzDjI+oIB=be+J~xbMQA$hCBX@>8NuY4-w+Fa?bDO3}J_*5fN(KWp| z7$xV~8B!)Z=#n0xG(=Jlan4p#G-c7WrCY@I^K$2~k)z{J=tT*H1bp=sZezt)KFs}z z(INhOZkrFF*98H-Y9hrc@IYmbyF{v#q#1@8oY}<5NL^y0R5FCm7s1ih5aZ*Z& z%0&#FKpJ9INtkBGleh9d64m+%?U&PKvx~R$H$6HQ>Jqq=oi4@v*bUP-4X4S79e)@W z0yWK;i#;+_iy75gihz*OpJAwJ_YKhX%s3iP0l{=@(tijT3tYgfhel=8Q!K8PYbp6K zAWg%5D++#yx)@*jtw=z!I)4XC41N1^?UT^z<3yWcM8C_>7^73JJP&ps2B)cPj3>%) z&9k>~LNA)OhE66P*US~(>q8KZ2VOlWlWa~xn#xer5Jrl)NDqc8NdcBJWQ0ftt`!(v z3l3F!g*UylmL0>qF$xzUSHQq*knW#~U(vQe?$GLALp`*LXAsnTVXwaJTPo@a?Jq!t z0s{r{$0eN2@z!Pww8rIss=>OXhUUti?A^A$Q*axQ#(vQ5jOEe+(0o!M|C(MPHbZS~ zAG@$hZP7p$kBudhY|ANS13RNz&XcD+$8FF8Ks6Ia+bd1+h!xwu+A(*iD{M&2wH;-q zT%n@_1>X*XnQ!htGg#5&Jkf5UI6ub_gS6|!9y*QbB1s*Qm#v7dHH>8U>e-_xDlQ*p ziH#!)91%BZ4z1VrCSzoZj}Y4riIRw)|04E_Kby&@+&|wO)){y=;DdfG@MU-Z)4DHdT*+r`i52@NW$_aj zQd&^K)wl{Sz`J^Wxa+lYz^d%hebA8^^3@5lXt(n}O?wySqawr^zFsfTnyc;=RSv(P zcLxRW-?RRkT7CR9IS1e9{{2OOsOcRgJoE1d^Vi>2zd5IgUzG0LC@wD!52+b6Q2+JF z{w~004@dRZSuGQFsUG^@60(6XGqV3w04na!|EstlYER}V#jlY<4`}}u6mWu_GY9)m zu@HX{LlkcR{pP>bj4rSol|_&INtD;xs-kk; zi6*>64;L1AH787u1xag*E2ipb{P5ru`As$~`_fNagJaurflOk1%~WbZyvAgnebwB@ zSnOAD9G0r7&RIADGj_C?(vuh&ZCsVBEL0LH!?M)f<6?~86di5?v+jR%RnV{b`3Qq7 z#eGiTny9>IX8ZrJ^_Ed_G+Wd#1Sd#>JHg%E3GNO-g2UkM?hxEv1Hs+hb7SRF5%`bu?_$!004=9!dM3G@Q6W!(5aIYajI3pKKz z^m0O{D3epZ{DjJ@)c^UlkAFZ^&6OwjnP8N_#z=}?!*9FjxuKY9$HZLYBc+sK&^Qu& zXk&ZW=-Uo_9}Y3FBct*=*?+ozDX@^o5)asb|Fb<(@-B~iSeE7;qgbe#`GCY~_}~sb zD`|=Op`W{5hy`HYU|$bPsm+|*UERm-4xGjq^*T$+r{5~jd%>l|4m3?Z^)&OE?9A%LzWT^YAaY1y$<9eGRyRFT;@g@7Vj= z+tv`3XZyv%laf!1LRJkbLf+KxrZ`%;MMs;UGNEv+%wHr`(S9*!miBZStI-ce=R@=P zOrDaX*oJfmi-lS2hSYeNRN67UyeW1GJv`zgt;pJBQsXA8IkQ(rtUiU<8TKoQ)=PV& zV(uwDgY9!%YB{c=X3^vPW0|}`Q5lXqRkrNOCxva$&0dRZfT5PA`Mx7Z;}pE@WBHP6 zOO6%U47PtEHm;rd)(@zO3cbkq#sp$>N+4dr<~iA=#>Z@U?-y)4qm@^Bon(|D%s$m^ z<8uU(sGOf+lm`IGgk+OG5*lNUpvL~u3-VaaPG9|0^Tr^_j~Wfs1Ts-+efy;cZRv&j z1g8@)#&Y1`d~F>ex;>3;PX>IE8`psGRfKjwadOkR@xo&%YRa)P@4zfw7IPoLz4Pm^ z97;m%8(qpwG~DE^Yxfr=ZcIG`9@DkC$+KL2fo`r9iOoTJ{35g8ekqr;+E0nC6GCyy zsyf`GGUK!`-0DykA@SGFxu~S4DeZ$3^xQCfkT%f}{NM>{T$Jx8)zwkoe2uicmIyO{ zU{D~YGNlmpt4=Q@kL~I{&nCv0Flb5=sCY%rY$jBwg8L%6eX1zv#;Q>m)Wt&%Y;x^V zSO23hBK;;WSc-wK^O-Tz-b}11bn&RD>$~YWfCWKJ8C9AVtEbBGuNy9vsiw1f?DDRt z&6Vm^Vs`5O>jnzMUB7^&Mi{@|1^}|mZG)h=>|jaNg$spl6pT-JghFyvbD>e)VsHxM^hT>F3)at$HU5|f9HT)#D#;sXeYy&8T zpy2j9hs}5B9j4EW-8x^3E17oojJdhvS^x500u;N^r!2_@grgoNG2)5simUAOOC+Qk z95i5C?mrgU`EFdy7qxrUtquo$YVXz>gG!KzYOe1uO7y5mH1CiYpVH!9CmMEsfJ^J- zms{k`_L?OAvw6m*rKQUvl!djp zNiaPA*+4Gdru(X>1B+cJKD(T+tR4^&o>kRw+k<#rNOp>?JXUT7rJ$l;lNcZv2uPBV z)dcDqk*PWW{AIr=95n3XIPd!I1)NdWGDC4^meV2Y=pc78aE^=N+)I+S^R{D(lAo%6 z%oO_5%;F3dTOGt%w2(=`v8oz-D8i>o8p#~%QKq^nh(?9st8T#4>0TDKQe~KM9|*Og z=fekZ?~w0OY)KZ=GE)V|Mk`uk6WDM!?MRUOhbB(Crb>=>r<|i&nPvwyvq&TbO_wm) zkLzPV+^Cgk3R#1#fnCGUhkOtRldY~LY(#|OrB68<@E?!HrAO}RE010-6g0P;C7@N( z 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