Skip to content

Commit

Permalink
Fix #47
Browse files Browse the repository at this point in the history
  • Loading branch information
denismerigoux committed Mar 12, 2021
1 parent f70f58e commit d26bef4
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 51 deletions.
120 changes: 71 additions & 49 deletions src/catala/surface/name_resolution.ml
Original file line number Diff line number Diff line change
Expand Up @@ -264,49 +264,15 @@ let add_def_local_var (ctxt : context) (name : ident Pos.marked) : context * Sco

(** Process a scope declaration *)
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 Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with
| Some use ->
Errors.raise_multispanned_error
(Format.asprintf "scope name \"%s\" already used"
(Utils.Cli.print_with_style [ ANSITerminal.yellow ] "%s" name))
[
(Some "first use", Pos.get_position (Scopelang.Ast.ScopeName.get_info use));
(Some "second use", pos);
]
| None ->
let scope_uid = Scopelang.Ast.ScopeName.fresh (name, pos) in
let ctxt =
{
ctxt with
scope_idmap = Desugared.Ast.IdentMap.add name scope_uid ctxt.scope_idmap;
scopes =
Scopelang.Ast.ScopeMap.add scope_uid
{
var_idmap = Desugared.Ast.IdentMap.empty;
label_idmap = Desugared.Ast.IdentMap.empty;
default_rulemap = Desugared.Ast.ScopeDefMap.empty;
sub_scopes_idmap = Desugared.Ast.IdentMap.empty;
sub_scopes = Scopelang.Ast.SubScopeMap.empty;
}
ctxt.scopes;
}
in
List.fold_left
(fun ctxt item -> process_item_decl scope_uid ctxt (Pos.unmark item))
ctxt decl.scope_decl_context
let name, _ = decl.scope_decl_name in
let scope_uid = Desugared.Ast.IdentMap.find name ctxt.scope_idmap in
List.fold_left
(fun ctxt item -> process_item_decl scope_uid ctxt (Pos.unmark item))
ctxt decl.scope_decl_context

(** 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 =
{
ctxt with
struct_idmap =
Desugared.Ast.IdentMap.add (Pos.unmark sdecl.struct_decl_name) s_uid ctxt.struct_idmap;
}
in
let s_uid = Desugared.Ast.IdentMap.find (fst sdecl.struct_decl_name) ctxt.struct_idmap in
List.fold_left
(fun ctxt (fdecl, _) ->
let f_uid = Scopelang.Ast.StructFieldName.fresh fdecl.Ast.struct_decl_field_name in
Expand Down Expand Up @@ -344,14 +310,7 @@ let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context =

(** 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 =
{
ctxt with
enum_idmap =
Desugared.Ast.IdentMap.add (Pos.unmark edecl.enum_decl_name) e_uid ctxt.enum_idmap;
}
in
let e_uid = Desugared.Ast.IdentMap.find (fst edecl.enum_decl_name) 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
Expand Down Expand Up @@ -385,6 +344,64 @@ let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context =
})
ctxt edecl.enum_decl_cases

(** Process the names of all declaration items *)
let process_name_item (ctxt : context) (item : Ast.code_item Pos.marked) : context =
let raise_already_defined_error use name pos msg =
Errors.raise_multispanned_error
(Format.asprintf "%s name \"%s\" already defined" msg
(Utils.Cli.print_with_style [ ANSITerminal.yellow ] "%s" name))
[
(Some "first definition", Pos.get_position (Scopelang.Ast.ScopeName.get_info use));
(Some "second definition", pos);
]
in
match Pos.unmark item with
| ScopeDecl decl -> (
let name, pos = decl.scope_decl_name in
(* Checks if the name is already used *)
match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with
| Some use -> raise_already_defined_error use name pos "scope"
| None ->
let scope_uid = Scopelang.Ast.ScopeName.fresh (name, pos) in
{
ctxt with
scope_idmap = Desugared.Ast.IdentMap.add name scope_uid ctxt.scope_idmap;
scopes =
Scopelang.Ast.ScopeMap.add scope_uid
{
var_idmap = Desugared.Ast.IdentMap.empty;
label_idmap = Desugared.Ast.IdentMap.empty;
default_rulemap = Desugared.Ast.ScopeDefMap.empty;
sub_scopes_idmap = Desugared.Ast.IdentMap.empty;
sub_scopes = Scopelang.Ast.SubScopeMap.empty;
}
ctxt.scopes;
} )
| StructDecl sdecl -> (
let name, pos = sdecl.struct_decl_name in
match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with
| Some use -> raise_already_defined_error use name pos "struct"
| None ->
let s_uid = Scopelang.Ast.StructName.fresh sdecl.struct_decl_name in
{
ctxt with
struct_idmap =
Desugared.Ast.IdentMap.add (Pos.unmark sdecl.struct_decl_name) s_uid ctxt.struct_idmap;
} )
| EnumDecl edecl -> (
let name, pos = edecl.enum_decl_name in
match Desugared.Ast.IdentMap.find_opt name ctxt.scope_idmap with
| Some use -> raise_already_defined_error use name pos "enum"
| None ->
let e_uid = Scopelang.Ast.EnumName.fresh edecl.enum_decl_name in

{
ctxt with
enum_idmap =
Desugared.Ast.IdentMap.add (Pos.unmark edecl.enum_decl_name) e_uid ctxt.enum_idmap;
} )
| ScopeUse _ -> ctxt

(** 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
Expand Down Expand Up @@ -608,9 +625,14 @@ let form_context (prgm : Ast.program) : context =
in
let ctxt =
List.fold_left
(fun ctxt item -> process_program_item ctxt item process_decl_item)
(fun ctxt item -> process_program_item ctxt item process_name_item)
empty_ctxt prgm.program_items
in
let ctxt =
List.fold_left
(fun ctxt item -> process_program_item ctxt item process_decl_item)
ctxt prgm.program_items
in
let ctxt =
List.fold_left
(fun ctxt item -> process_program_item ctxt item process_use_item)
Expand Down
19 changes: 19 additions & 0 deletions tests/test_name_resolution/good/out_of_order.catala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## [Article]

```catala
new scope S:
param a content A
param b content B
new struct A:
data x content int
data y content B
new struct B:
data y content bool
data z content dec
scope S:
def b := B { -- y: true -- z: 0.0}
def a := A { -- x: 0 -- y : b }
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[RESULT] Computation successful! Results:
[RESULT] a = A {"x": 0, "y": B {"y": true, "z": 0.}}
[RESULT] b = B {"y": true, "z": 0.}
3 changes: 3 additions & 0 deletions tests/test_struct/bad/nested2.catala
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ new struct S:
new enum E:
-- Case1 content bool
-- Case2 content S
new scope A:
param x content E
```
26 changes: 24 additions & 2 deletions tests/test_struct/bad/output/nested2.catala.A.out
Original file line number Diff line number Diff line change
@@ -1,7 +1,29 @@
[ERROR] Unknown type "E", not a struct or enum previously declared
[ERROR] Cyclic dependency detected between types!
[ERROR]
[ERROR] Cycle type S, declared:
[ERROR] --> test_struct/bad/nested2.catala
[ERROR] |
[ERROR] 5 | data x content E
[ERROR] 4 | new struct S:
[ERROR] | ^
[ERROR] + Article
[ERROR]
[ERROR] Used here in the definition of another cycle type E:
[ERROR] --> test_struct/bad/nested2.catala
[ERROR] |
[ERROR] 10 | -- Case2 content S
[ERROR] | ^
[ERROR] + Article
[ERROR]
[ERROR] Cycle type E, declared:
[ERROR] --> test_struct/bad/nested2.catala
[ERROR] |
[ERROR] 8 | new enum E:
[ERROR] | ^
[ERROR] + Article
[ERROR]
[ERROR] Used here in the definition of another cycle type S:
[ERROR] --> test_struct/bad/nested2.catala
[ERROR] |
[ERROR] 5 | data x content E
[ERROR] | ^
[ERROR] + Article

0 comments on commit d26bef4

Please sign in to comment.