Toplevel defs: tests & fixes

This commit is contained in:
Louis Gesbert 2023-02-08 16:55:07 +01:00
parent 9b0c7583ec
commit d66cd1e29c
9 changed files with 151 additions and 13 deletions

View File

@ -989,6 +989,8 @@ let translate_scope_decl
(input_destructurings rules_with_return_expr)),
new_struct_ctx )
(* TODO: rename "scope" here to avoid confusion, since it now includes toplevel
defs and scopes *)
let translate_program (prgm : 'm Scopelang.Ast.program) : 'm Ast.program =
let scope_dependencies = Scopelang.Dependency.build_program_dep_graph prgm in
Scopelang.Dependency.check_for_cycle_in_scope scope_dependencies;

View File

@ -314,7 +314,7 @@ and evaluate_expr (ctx : decl_ctx) (e : 'm Ast.expr) : 'm Ast.expr =
| EVar _ ->
Errors.raise_spanned_error (Expr.pos e)
"free variable found at evaluation (should not happen if term was \
well-typed"
well-typed)"
| EApp { f = e1; args } -> (
let e1 = evaluate_expr ctx e1 in
let args = List.map (evaluate_expr ctx) args in

View File

@ -58,6 +58,16 @@ let scope ctx env scope =
{ scope with scope_defs; scope_assertions }
let program prg =
let env =
TopdefName.Map.fold
(fun name (_e, ty) env -> Typing.Env.add_global_var name ty env)
prg.program_globals Typing.Env.empty
in
let program_globals =
TopdefName.Map.map
(fun (e, ty) -> Expr.unbox (expr prg.program_ctx env (Expr.box e)), ty)
prg.program_globals
in
let env =
ScopeName.Map.fold
(fun scope_name scope env ->
@ -70,9 +80,9 @@ let program prg =
scope.scope_defs ScopeVar.Map.empty
in
Typing.Env.add_scope scope_name ~vars env)
prg.program_scopes Typing.Env.empty
prg.program_scopes env
in
let program_scopes =
ScopeName.Map.map (scope prg.program_ctx env) prg.program_scopes
in
{ prg with program_scopes }
{ prg with program_globals; program_scopes }

View File

@ -98,6 +98,24 @@ let scope ?(debug = false) ctx fmt (name, decl) =
SubScopeName.format_t subscope_name Print.punctuation "]"))
decl.scope_decl_rules
let print_topdef ctx ppf name (e, ty) =
Format.pp_open_vbox ppf 2;
let () =
Format.pp_open_hovbox ppf 2;
Print.keyword ppf "let";
Format.pp_print_space ppf ();
TopdefName.format_t ppf name;
Print.punctuation ppf ":";
Format.pp_print_space ppf ();
Print.typ ctx ppf ty;
Format.pp_print_space ppf ();
Print.punctuation ppf "=";
Format.pp_close_box ppf ()
in
Format.pp_print_cut ppf ();
Print.expr ctx ppf e;
Format.pp_close_box ppf ()
let program ?(debug : bool = false) (fmt : Format.formatter) (p : 'm program) :
unit =
let ctx = p.program_ctx in
@ -116,6 +134,11 @@ let program ?(debug : bool = false) (fmt : Format.formatter) (p : 'm program) :
enum ctx fmt n e;
pp_sep fmt ())
ctx.ctx_enums;
TopdefName.Map.iter
(fun name def ->
print_topdef ctx fmt name def;
pp_sep fmt ())
p.program_globals;
Format.pp_print_list ~pp_sep (scope ~debug ctx) fmt
(ScopeName.Map.bindings p.program_scopes);
Format.pp_close_box fmt ()

View File

@ -211,7 +211,7 @@ let rec unfold
typ, expr, pos, is_main
| Topdef (name, typ, expr) ->
let pos = Marked.get_mark (TopdefName.get_info name) in
typ, Expr.box expr, pos, false
typ, Expr.rebox expr, pos, false
in
let main_scope = if is_main then ScopeVar var else main_scope in
let next = unfold ctx next mark main_scope in

View File

@ -259,6 +259,7 @@ source_file: BEGIN_CODE DECLARATION YEAR
## code_item -> DECLARATION . ENUM UIDENT COLON list(addpos(enum_decl_line)) [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION . lident CONTENT typ DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION . lident CONTENT typ DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION . lident CONTENT typ DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
##
## The known suffix of the stack is as follows:
## DECLARATION
@ -973,7 +974,7 @@ expected the name of the scope being used
source_file: BEGIN_CODE YEAR
##
## Ends in an error in state: 368.
## Ends in an error in state: 370.
##
## source_file_item -> BEGIN_CODE . code END_CODE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
##
@ -1034,8 +1035,8 @@ source_file: BEGIN_METADATA LAW_TEXT LAW_HEADING
## 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 1, spurious reduction of production nonempty_list(LAW_TEXT) -> LAW_TEXT
## In state 357, spurious reduction of production law_text -> nonempty_list(LAW_TEXT)
## In state 358, spurious reduction of production option(law_text) -> law_text
## In state 359, spurious reduction of production law_text -> nonempty_list(LAW_TEXT)
## In state 360, spurious reduction of production option(law_text) -> law_text
##
expected some law text or code block
@ -3902,6 +3903,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT YEAR
##
## code_item -> DECLARATION lident . CONTENT typ DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident . CONTENT typ DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident . CONTENT typ DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
##
## The known suffix of the stack is as follows:
## DECLARATION lident
@ -3915,6 +3917,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT YEAR
##
## code_item -> DECLARATION lident CONTENT . typ DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident CONTENT . typ DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident CONTENT . typ DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
##
## The known suffix of the stack is as follows:
## DECLARATION lident CONTENT
@ -3928,6 +3931,7 @@ source_file: BEGIN_CODE DECLARATION LIDENT CONTENT BOOLEAN YEAR
##
## code_item -> DECLARATION lident CONTENT typ . DEPENDS separated_nonempty_list(COMMA,var_content) DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident CONTENT typ . DEPENDS LPAREN separated_nonempty_list(COMMA,var_content) RPAREN DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
## code_item -> DECLARATION lident CONTENT typ . DEFINED_AS expression [ SCOPE END_CODE DECLARATION ]
##
## The known suffix of the stack is as follows:
## DECLARATION lident CONTENT typ
@ -4157,7 +4161,7 @@ expected a binary operator continuing the expression, or a keyword ending the ex
source_file: BEGIN_DIRECTIVE YEAR
##
## Ends in an error in state: 359.
## Ends in an error in state: 361.
##
## source_file_item -> BEGIN_DIRECTIVE . LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
##
@ -4169,7 +4173,7 @@ expected a directive, e.g. 'Include: <filename>'
source_file: BEGIN_DIRECTIVE LAW_INCLUDE YEAR
##
## Ends in an error in state: 360.
## Ends in an error in state: 362.
##
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE . COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
##
@ -4181,7 +4185,7 @@ expected ':', then a file name or 'JORFTEXTNNNNNNNNNNNN'
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON YEAR
##
## Ends in an error in state: 361.
## Ends in an error in state: 363.
##
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON . nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
##
@ -4193,7 +4197,7 @@ expected a file name or 'JORFTEXTNNNNNNNNNNNN'
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG YEAR
##
## Ends in an error in state: 362.
## Ends in an error in state: 364.
##
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . [ END_DIRECTIVE AT_PAGE ]
## nonempty_list(DIRECTIVE_ARG) -> DIRECTIVE_ARG . nonempty_list(DIRECTIVE_ARG) [ END_DIRECTIVE AT_PAGE ]
@ -4206,7 +4210,7 @@ expected a page specification in the form '@p.<number>', or a newline
source_file: BEGIN_DIRECTIVE LAW_INCLUDE COLON DIRECTIVE_ARG AT_PAGE YEAR
##
## Ends in an error in state: 366.
## Ends in an error in state: 368.
##
## source_file_item -> BEGIN_DIRECTIVE LAW_INCLUDE COLON nonempty_list(DIRECTIVE_ARG) option(AT_PAGE) . END_DIRECTIVE [ LAW_TEXT LAW_HEADING EOF BEGIN_METADATA BEGIN_DIRECTIVE BEGIN_CODE ]
##
@ -4218,7 +4222,7 @@ expected a newline
source_file: LAW_HEADING YEAR
##
## Ends in an error in state: 371.
## Ends in an error in state: 373.
##
## source_file -> source_file_item . source_file [ # ]
##

View File

@ -604,6 +604,7 @@ let var_content ==
let depends_stance ==
| DEPENDS ; args = separated_nonempty_list(COMMA,var_content) ; <>
| DEPENDS ; LPAREN ; args = separated_nonempty_list(COMMA,var_content) ; RPAREN ; <>
| { [] }
let code_item :=
| SCOPE ; c = uident ;

View File

@ -0,0 +1,24 @@
## Scope calls are not allowed outside of scopes
```catala
declaration scope S1:
output a content decimal
scope S1:
definition a equals 44.2
declaration glob5 content decimal
equals (output of S1).a
```
```catala-test-inline
$ catala typecheck
[ERROR] Scope calls are not allowed outside of a scope
┌─⯈ tests/test_name_resolution/bad/toplevel_defs.catala_en:11.10-22:
└──┐
11 │ equals (output of S1).a
│ ‾‾‾‾‾‾‾‾‾‾‾‾
└─ Scope calls are not allowed outside of scopes
#return code 255#
```

View File

@ -0,0 +1,74 @@
## Test basic toplevel values defs
```catala
declaration glob1 content decimal equals 44.12
declaration scope S:
output a content decimal
output b content A
declaration structure A:
data y content boolean
data z content decimal
declaration glob2 content A equals
A { --y: glob1 >= 30. --z: 123. * 17. }
scope S:
definition a equals glob1 * glob1
definition b equals glob2
```
```catala-test-inline
$ catala Interpret -s S
[RESULT] Computation successful! Results:
[RESULT] a = 1946.5744
[RESULT] b = A { "y"= true; "z"= 2091. }
```
## Test toplevel function defs
```catala
declaration glob3 content decimal
depends on x content money
equals decimal of x + 10.
declaration scope S2:
output a content decimal
scope S2:
definition a equals glob3 of $44 + 100.
```
```catala-test-inline
$ catala Interpret -s S2
[RESULT] Computation successful! Results:
[RESULT] a = 154.
```
## Test function def with two args
```catala
declaration glob4 content decimal
depends on x content money, y content decimal
equals decimal of x * y + 10.
declaration scope S3:
output a content decimal
#scope S3:
# definition a equals 50 + glob3 of ($44, 55.)
# TODO: no syntax yet
```
```catala-test-inline
$ catala Interpret -s S3
[ERROR] This variable evaluated to an empty term (no rule that defined it applied in this situation)
┌─⯈ tests/test_name_resolution/good/toplevel_defs.catala_en:57.9-10:
└──┐
57 │ output a content decimal
│ ‾
└─ Test function def with two args
#return code 255#
```