2020-06-22 17:16:55 +03:00
|
|
|
(* 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
|
2020-09-12 21:22:47 +03:00
|
|
|
<nicolas.chataing@ens.fr> Denis Merigoux <denis.merigoux@inria.fr>
|
2020-06-22 17:16:55 +03:00
|
|
|
|
|
|
|
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. *)
|
|
|
|
|
2020-09-12 21:22:47 +03:00
|
|
|
(** Builds a context that allows for mapping each name to a precise uid, taking lexical scopes into
|
|
|
|
account *)
|
2020-06-22 17:16:55 +03:00
|
|
|
|
2021-01-21 23:33:04 +03:00
|
|
|
open Utils
|
2020-11-23 11:22:47 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** {1 Name resolution context} *)
|
|
|
|
|
2020-06-22 17:16:55 +03:00
|
|
|
type ident = string
|
|
|
|
|
2020-12-04 20:48:16 +03:00
|
|
|
type typ = Scopelang.Ast.typ
|
2020-07-15 17:14:11 +03:00
|
|
|
|
2022-01-05 17:57:18 +03:00
|
|
|
type unique_rulename = Ambiguous of Pos.t list | Unique of Desugared.Ast.RuleName.t Pos.marked
|
2021-01-22 07:47:48 +03:00
|
|
|
|
2022-01-03 20:39:59 +03:00
|
|
|
type scope_def_context = {
|
|
|
|
default_exception_rulename : unique_rulename option;
|
2022-01-04 20:19:15 +03:00
|
|
|
label_idmap : Desugared.Ast.LabelName.t Desugared.Ast.IdentMap.t;
|
|
|
|
label_groups : Desugared.Ast.RuleSet.t Desugared.Ast.LabelMap.t;
|
2022-01-03 20:39:59 +03:00
|
|
|
}
|
|
|
|
|
2020-09-12 21:22:47 +03:00
|
|
|
type scope_context = {
|
2022-02-28 19:19:06 +03:00
|
|
|
var_idmap : Desugared.Ast.ScopeVar.t Desugared.Ast.IdentMap.t; (** Scope variables *)
|
2022-01-03 20:39:59 +03:00
|
|
|
scope_defs_contexts : scope_def_context Desugared.Ast.ScopeDefMap.t;
|
2021-01-21 08:07:09 +03:00
|
|
|
(** What is the default rule to refer to for unnamed exceptions, if any *)
|
2020-11-25 12:49:53 +03:00
|
|
|
sub_scopes_idmap : Scopelang.Ast.SubScopeName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Sub-scopes variables *)
|
2020-11-23 14:20:38 +03:00
|
|
|
sub_scopes : Scopelang.Ast.ScopeName.t Scopelang.Ast.SubScopeMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** To what scope sub-scopes refer to? *)
|
2020-09-12 21:22:47 +03:00
|
|
|
}
|
|
|
|
(** Inside a scope, we distinguish between the variables and the subscopes. *)
|
2020-07-15 17:14:11 +03:00
|
|
|
|
2020-12-04 18:40:17 +03:00
|
|
|
type struct_context = typ Pos.marked Scopelang.Ast.StructFieldMap.t
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Types of the fields of a struct *)
|
2020-12-04 18:40:17 +03:00
|
|
|
|
|
|
|
type enum_context = typ Pos.marked Scopelang.Ast.EnumConstructorMap.t
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Types of the payloads of the cases of an enum *)
|
2020-12-04 18:40:17 +03:00
|
|
|
|
2022-02-05 02:04:19 +03:00
|
|
|
type var_sig = {
|
|
|
|
var_sig_typ : typ Pos.marked;
|
|
|
|
var_sig_is_condition : bool;
|
2022-02-07 12:30:36 +03:00
|
|
|
var_sig_io : Ast.scope_decl_context_io;
|
2022-02-28 17:40:19 +03:00
|
|
|
var_sig_states_idmap : Desugared.Ast.StateName.t Desugared.Ast.IdentMap.t;
|
|
|
|
var_sig_states_list : Desugared.Ast.StateName.t list;
|
2022-02-05 02:04:19 +03:00
|
|
|
}
|
|
|
|
|
2020-07-15 18:47:16 +03:00
|
|
|
type context = {
|
2022-02-28 20:34:32 +03:00
|
|
|
local_var_idmap : Desugared.Ast.Var.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** 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 *)
|
2020-12-04 18:40:17 +03:00
|
|
|
struct_idmap : Scopelang.Ast.StructName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** The names of the structs *)
|
2020-12-04 18:40:17 +03:00
|
|
|
field_idmap : Scopelang.Ast.StructFieldName.t Scopelang.Ast.StructMap.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** 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 *)
|
2020-12-04 18:40:17 +03:00
|
|
|
constructor_idmap :
|
|
|
|
Scopelang.Ast.EnumConstructor.t Scopelang.Ast.EnumMap.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** 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 *)
|
2022-02-28 19:19:06 +03:00
|
|
|
var_typs : var_sig Desugared.Ast.ScopeVarMap.t;
|
2022-02-05 02:04:19 +03:00
|
|
|
(** The signatures of each scope variable declared *)
|
2020-07-15 18:47:16 +03:00
|
|
|
}
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Main context used throughout {!module: Surface.Desugaring} *)
|
|
|
|
|
|
|
|
(** {1 Helpers} *)
|
2020-07-15 18:47:16 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Temporary function raising an error message saying that a feature is not supported yet *)
|
2020-08-07 13:51:51 +03:00
|
|
|
let raise_unsupported_feature (msg : string) (pos : Pos.t) =
|
2020-12-05 19:27:08 +03:00
|
|
|
Errors.raise_spanned_error (Printf.sprintf "Unsupported feature: %s" msg) pos
|
2020-08-07 13:51:51 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Function to call whenever an identifier used somewhere has not been declared in the program
|
|
|
|
previously *)
|
2020-09-12 21:22:47 +03:00
|
|
|
let raise_unknown_identifier (msg : string) (ident : ident Pos.marked) =
|
|
|
|
Errors.raise_spanned_error
|
2021-01-20 21:19:17 +03:00
|
|
|
(Printf.sprintf "\"%s\": unknown identifier %s"
|
|
|
|
(Utils.Cli.print_with_style [ ANSITerminal.yellow ] "%s" (Pos.unmark ident))
|
|
|
|
msg)
|
2020-09-12 21:22:47 +03:00
|
|
|
(Pos.get_position ident)
|
2020-07-16 15:46:40 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Gets the type associated to an uid *)
|
2022-02-28 19:19:06 +03:00
|
|
|
let get_var_typ (ctxt : context) (uid : Desugared.Ast.ScopeVar.t) : typ Pos.marked =
|
|
|
|
(Desugared.Ast.ScopeVarMap.find uid ctxt.var_typs).var_sig_typ
|
2020-12-31 02:28:26 +03:00
|
|
|
|
2022-02-28 19:19:06 +03:00
|
|
|
let is_var_cond (ctxt : context) (uid : Desugared.Ast.ScopeVar.t) : bool =
|
|
|
|
(Desugared.Ast.ScopeVarMap.find uid ctxt.var_typs).var_sig_is_condition
|
2022-02-05 02:04:19 +03:00
|
|
|
|
2022-02-28 19:19:06 +03:00
|
|
|
let get_var_io (ctxt : context) (uid : Desugared.Ast.ScopeVar.t) : Ast.scope_decl_context_io =
|
|
|
|
(Desugared.Ast.ScopeVarMap.find uid ctxt.var_typs).var_sig_io
|
2020-08-03 23:03:05 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Get the variable uid inside the scope given in argument *)
|
|
|
|
let get_var_uid (scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context)
|
2022-02-28 19:19:06 +03:00
|
|
|
((x, pos) : ident Pos.marked) : Desugared.Ast.ScopeVar.t =
|
2020-12-14 17:23:04 +03:00
|
|
|
let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in
|
|
|
|
match Desugared.Ast.IdentMap.find_opt x scope.var_idmap with
|
2021-01-08 00:38:56 +03:00
|
|
|
| None ->
|
|
|
|
raise_unknown_identifier
|
|
|
|
(Format.asprintf "for a variable of scope %a" Scopelang.Ast.ScopeName.format_t scope_uid)
|
|
|
|
(x, pos)
|
2020-12-14 17:23:04 +03:00
|
|
|
| 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 *)
|
2022-02-28 19:19:06 +03:00
|
|
|
let belongs_to (ctxt : context) (uid : Desugared.Ast.ScopeVar.t)
|
2020-12-14 17:23:04 +03:00
|
|
|
(scope_uid : Scopelang.Ast.ScopeName.t) : bool =
|
|
|
|
let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in
|
|
|
|
Desugared.Ast.IdentMap.exists
|
2022-02-28 19:19:06 +03:00
|
|
|
(fun _ var_uid -> Desugared.Ast.ScopeVar.compare uid var_uid = 0)
|
2020-12-14 17:23:04 +03:00
|
|
|
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 *)
|
2022-02-28 19:19:06 +03:00
|
|
|
| Desugared.Ast.ScopeDef.Var (x, _) ->
|
2020-12-31 02:28:26 +03:00
|
|
|
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 *)
|
2022-02-28 19:19:06 +03:00
|
|
|
| Desugared.Ast.ScopeDef.Var (x, _) ->
|
2020-12-31 02:28:26 +03:00
|
|
|
is_var_cond ctxt x
|
2020-12-14 17:23:04 +03:00
|
|
|
|
2022-01-04 20:19:15 +03:00
|
|
|
let label_groups (ctxt : context) (s_uid : Scopelang.Ast.ScopeName.t)
|
|
|
|
(def : Desugared.Ast.ScopeDef.t) : Desugared.Ast.RuleSet.t Desugared.Ast.LabelMap.t =
|
2022-01-28 19:31:31 +03:00
|
|
|
try
|
|
|
|
(Desugared.Ast.ScopeDefMap.find def
|
|
|
|
(Scopelang.Ast.ScopeMap.find s_uid ctxt.scopes).scope_defs_contexts)
|
|
|
|
.label_groups
|
|
|
|
with Not_found -> Desugared.Ast.LabelMap.empty
|
2022-01-04 20:19:15 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** {1 Declarations pass} *)
|
|
|
|
|
2020-07-16 13:04:23 +03:00
|
|
|
(** Process a subscope declaration *)
|
2020-11-23 14:20:38 +03:00
|
|
|
let process_subscope_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context)
|
2020-11-25 12:49:53 +03:00
|
|
|
(decl : Ast.scope_decl_context_scope) : context =
|
2020-09-12 21:22:47 +03:00
|
|
|
let name, name_pos = decl.scope_decl_context_scope_name in
|
2020-07-16 15:46:40 +03:00
|
|
|
let subscope, s_pos = decl.scope_decl_context_scope_sub_scope in
|
2020-11-23 14:20:38 +03:00
|
|
|
let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in
|
2020-11-25 12:49:53 +03:00
|
|
|
match Desugared.Ast.IdentMap.find_opt subscope scope_ctxt.sub_scopes_idmap with
|
2020-09-12 21:22:47 +03:00
|
|
|
| Some use ->
|
2021-01-20 21:19:17 +03:00
|
|
|
Errors.raise_multispanned_error
|
2022-01-10 17:00:36 +03:00
|
|
|
(Format.asprintf "Subscope name \"%a\" already used"
|
2022-01-10 20:36:14 +03:00
|
|
|
(Utils.Cli.format_with_style [ ANSITerminal.yellow ])
|
|
|
|
subscope)
|
2020-09-13 01:33:56 +03:00
|
|
|
[
|
2020-11-23 14:20:38 +03:00
|
|
|
(Some "first use", Pos.get_position (Scopelang.Ast.SubScopeName.get_info use));
|
2020-09-13 01:33:56 +03:00
|
|
|
(Some "second use", s_pos);
|
|
|
|
]
|
2020-07-16 15:46:40 +03:00
|
|
|
| None ->
|
2020-11-23 14:20:38 +03:00
|
|
|
let sub_scope_uid = Scopelang.Ast.SubScopeName.fresh (name, name_pos) in
|
2020-09-12 21:22:47 +03:00
|
|
|
let original_subscope_uid =
|
2020-11-25 12:49:53 +03:00
|
|
|
match Desugared.Ast.IdentMap.find_opt subscope ctxt.scope_idmap with
|
2020-09-13 19:48:28 +03:00
|
|
|
| None -> raise_unknown_identifier "for a scope" (subscope, s_pos)
|
2020-09-12 21:22:47 +03:00
|
|
|
| Some id -> id
|
2020-08-03 12:03:25 +03:00
|
|
|
in
|
2020-09-12 21:22:47 +03:00
|
|
|
let scope_ctxt =
|
2020-07-16 15:46:40 +03:00
|
|
|
{
|
2020-09-12 21:22:47 +03:00
|
|
|
scope_ctxt with
|
2020-11-25 12:49:53 +03:00
|
|
|
sub_scopes_idmap =
|
|
|
|
Desugared.Ast.IdentMap.add name sub_scope_uid scope_ctxt.sub_scopes_idmap;
|
2020-11-23 14:20:38 +03:00
|
|
|
sub_scopes =
|
|
|
|
Scopelang.Ast.SubScopeMap.add sub_scope_uid original_subscope_uid scope_ctxt.sub_scopes;
|
2020-07-16 15:46:40 +03:00
|
|
|
}
|
|
|
|
in
|
2020-11-23 14:20:38 +03:00
|
|
|
{ ctxt with scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes }
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2020-12-31 02:28:26 +03:00
|
|
|
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
|
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a basic type (all types except function types) *)
|
2020-12-30 00:26:10 +03:00
|
|
|
let rec process_base_typ (ctxt : context) ((typ, typ_pos) : Ast.base_typ Pos.marked) :
|
2020-12-04 20:48:16 +03:00
|
|
|
Scopelang.Ast.typ Pos.marked =
|
2020-08-06 16:18:40 +03:00
|
|
|
match typ with
|
2020-12-09 16:51:22 +03:00
|
|
|
| Ast.Condition -> (Scopelang.Ast.TLit TBool, typ_pos)
|
2020-12-30 00:26:10 +03:00
|
|
|
| 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 )
|
2020-11-25 12:49:53 +03:00
|
|
|
| Ast.Data (Ast.Primitive prim) -> (
|
2020-08-06 16:18:40 +03:00
|
|
|
match prim with
|
2020-12-09 16:51:22 +03:00
|
|
|
| Ast.Integer -> (Scopelang.Ast.TLit TInt, typ_pos)
|
|
|
|
| Ast.Decimal -> (Scopelang.Ast.TLit TRat, typ_pos)
|
|
|
|
| Ast.Money -> (Scopelang.Ast.TLit TMoney, typ_pos)
|
2020-12-10 13:35:56 +03:00
|
|
|
| Ast.Duration -> (Scopelang.Ast.TLit TDuration, typ_pos)
|
|
|
|
| Ast.Date -> (Scopelang.Ast.TLit TDate, typ_pos)
|
2020-12-09 16:51:22 +03:00
|
|
|
| Ast.Boolean -> (Scopelang.Ast.TLit TBool, typ_pos)
|
2020-11-25 12:49:53 +03:00
|
|
|
| Ast.Text -> raise_unsupported_feature "text type" typ_pos
|
2020-12-04 20:48:16 +03:00
|
|
|
| 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
|
2022-01-10 17:00:36 +03:00
|
|
|
(Format.asprintf "Unknown type \"%a\", not a struct or enum previously declared"
|
2022-01-10 20:36:14 +03:00
|
|
|
(Utils.Cli.format_with_style [ ANSITerminal.yellow ])
|
|
|
|
ident)
|
2021-03-23 12:59:43 +03:00
|
|
|
typ_pos)))
|
2020-08-06 16:18:40 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a type (function or not) *)
|
2020-12-04 20:48:16 +03:00
|
|
|
let process_type (ctxt : context) ((typ, typ_pos) : Ast.typ Pos.marked) :
|
|
|
|
Scopelang.Ast.typ Pos.marked =
|
2020-08-06 16:18:40 +03:00
|
|
|
match typ with
|
2020-12-04 20:48:16 +03:00
|
|
|
| Ast.Base base_typ -> process_base_typ ctxt (base_typ, typ_pos)
|
2020-11-25 12:49:53 +03:00
|
|
|
| Ast.Func { arg_typ; return_typ } ->
|
2020-12-04 20:48:16 +03:00
|
|
|
( Scopelang.Ast.TArrow (process_base_typ ctxt arg_typ, process_base_typ ctxt return_typ),
|
|
|
|
typ_pos )
|
2020-08-06 16:18:40 +03:00
|
|
|
|
2020-07-16 13:04:23 +03:00
|
|
|
(** Process data declaration *)
|
2020-11-23 14:20:38 +03:00
|
|
|
let process_data_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context)
|
2020-11-25 12:49:53 +03:00
|
|
|
(decl : Ast.scope_decl_context_data) : context =
|
2020-07-16 15:46:40 +03:00
|
|
|
(* First check the type of the context data *)
|
2020-12-04 20:48:16 +03:00
|
|
|
let data_typ = process_type ctxt decl.scope_decl_context_item_typ in
|
2020-12-31 02:28:26 +03:00
|
|
|
let is_cond = is_type_cond decl.scope_decl_context_item_typ in
|
2020-08-04 13:44:56 +03:00
|
|
|
let name, pos = decl.scope_decl_context_item_name in
|
2020-11-23 14:20:38 +03:00
|
|
|
let scope_ctxt = Scopelang.Ast.ScopeMap.find scope ctxt.scopes in
|
2020-11-25 12:49:53 +03:00
|
|
|
match Desugared.Ast.IdentMap.find_opt name scope_ctxt.var_idmap with
|
2020-09-12 21:22:47 +03:00
|
|
|
| Some use ->
|
2021-01-20 21:19:17 +03:00
|
|
|
Errors.raise_multispanned_error
|
2022-01-10 17:00:36 +03:00
|
|
|
(Format.asprintf "var name \"%a\" already used"
|
2022-01-10 20:36:14 +03:00
|
|
|
(Utils.Cli.format_with_style [ ANSITerminal.yellow ])
|
|
|
|
name)
|
2020-11-23 18:12:45 +03:00
|
|
|
[
|
2022-02-28 19:19:06 +03:00
|
|
|
(Some "first use", Pos.get_position (Desugared.Ast.ScopeVar.get_info use));
|
2020-11-23 18:12:45 +03:00
|
|
|
(Some "second use", pos);
|
|
|
|
]
|
2020-09-12 21:22:47 +03:00
|
|
|
| None ->
|
2022-02-28 19:19:06 +03:00
|
|
|
let uid = Desugared.Ast.ScopeVar.fresh (name, pos) in
|
2020-09-13 01:33:56 +03:00
|
|
|
let scope_ctxt =
|
2020-11-25 12:49:53 +03:00
|
|
|
{ scope_ctxt with var_idmap = Desugared.Ast.IdentMap.add name uid scope_ctxt.var_idmap }
|
2020-09-13 01:33:56 +03:00
|
|
|
in
|
2022-02-28 17:40:19 +03:00
|
|
|
let states_idmap, states_list =
|
|
|
|
List.fold_right
|
|
|
|
(fun state_id (states_idmap, states_list) ->
|
|
|
|
let state_uid = Desugared.Ast.StateName.fresh state_id in
|
|
|
|
( Desugared.Ast.IdentMap.add (Pos.unmark state_id) state_uid states_idmap,
|
|
|
|
state_uid :: states_list ))
|
|
|
|
decl.scope_decl_context_item_states
|
|
|
|
(Desugared.Ast.IdentMap.empty, [])
|
|
|
|
in
|
2020-09-12 21:22:47 +03:00
|
|
|
{
|
|
|
|
ctxt with
|
2020-11-23 14:20:38 +03:00
|
|
|
scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes;
|
2022-02-05 02:04:19 +03:00
|
|
|
var_typs =
|
2022-02-28 19:19:06 +03:00
|
|
|
Desugared.Ast.ScopeVarMap.add uid
|
2022-02-05 02:04:19 +03:00
|
|
|
{
|
|
|
|
var_sig_typ = data_typ;
|
|
|
|
var_sig_is_condition = is_cond;
|
2022-02-07 12:30:36 +03:00
|
|
|
var_sig_io = decl.scope_decl_context_item_attribute;
|
2022-02-28 17:40:19 +03:00
|
|
|
var_sig_states_idmap = states_idmap;
|
|
|
|
var_sig_states_list = states_list;
|
2022-02-05 02:04:19 +03:00
|
|
|
}
|
|
|
|
ctxt.var_typs;
|
2020-09-12 21:22:47 +03:00
|
|
|
}
|
2020-07-16 13:04:23 +03:00
|
|
|
|
|
|
|
(** Process an item declaration *)
|
2020-11-23 14:20:38 +03:00
|
|
|
let process_item_decl (scope : Scopelang.Ast.ScopeName.t) (ctxt : context)
|
2020-11-25 12:49:53 +03:00
|
|
|
(decl : Ast.scope_decl_context_item) : context =
|
2020-07-16 13:04:23 +03:00
|
|
|
match decl with
|
2020-11-25 12:49:53 +03:00
|
|
|
| Ast.ContextData data_decl -> process_data_decl scope ctxt data_decl
|
|
|
|
| Ast.ContextScope sub_decl -> process_subscope_decl scope ctxt sub_decl
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2020-09-12 21:22:47 +03:00
|
|
|
(** Adds a binding to the context *)
|
2022-02-28 20:34:32 +03:00
|
|
|
let add_def_local_var (ctxt : context) (name : ident Pos.marked) : context * Desugared.Ast.Var.t =
|
|
|
|
let local_var_uid = Desugared.Ast.Var.make name in
|
2020-12-06 19:48:15 +03:00
|
|
|
let ctxt =
|
2020-11-25 12:49:53 +03:00
|
|
|
{
|
2020-12-06 19:48:15 +03:00
|
|
|
ctxt with
|
|
|
|
local_var_idmap =
|
|
|
|
Desugared.Ast.IdentMap.add (Pos.unmark name) local_var_uid ctxt.local_var_idmap;
|
2020-11-25 12:49:53 +03:00
|
|
|
}
|
2020-09-12 21:22:47 +03:00
|
|
|
in
|
2020-12-06 19:48:15 +03:00
|
|
|
(ctxt, local_var_uid)
|
2020-09-12 21:22:47 +03:00
|
|
|
|
2020-07-16 13:04:23 +03:00
|
|
|
(** Process a scope declaration *)
|
2020-11-25 12:49:53 +03:00
|
|
|
let process_scope_decl (ctxt : context) (decl : Ast.scope_decl) : context =
|
2021-03-12 19:07:25 +03:00
|
|
|
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
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a struct declaration *)
|
2020-12-04 20:02:49 +03:00
|
|
|
let process_struct_decl (ctxt : context) (sdecl : Ast.struct_decl) : context =
|
2021-03-12 19:07:25 +03:00
|
|
|
let s_uid = Desugared.Ast.IdentMap.find (fst sdecl.struct_decl_name) ctxt.struct_idmap in
|
2020-12-04 20:02:49 +03:00
|
|
|
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
|
2020-12-04 20:48:16 +03:00
|
|
|
(process_type ctxt fdecl.Ast.struct_decl_field_typ))
|
2020-12-04 20:02:49 +03:00
|
|
|
| Some fields ->
|
|
|
|
Some
|
|
|
|
(Scopelang.Ast.StructFieldMap.add f_uid
|
2020-12-04 20:48:16 +03:00
|
|
|
(process_type ctxt fdecl.Ast.struct_decl_field_typ)
|
2020-12-04 20:02:49 +03:00
|
|
|
fields))
|
|
|
|
ctxt.structs;
|
|
|
|
})
|
|
|
|
ctxt sdecl.struct_decl_fields
|
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process an enum declaration *)
|
2020-12-04 20:02:49 +03:00
|
|
|
let process_enum_decl (ctxt : context) (edecl : Ast.enum_decl) : context =
|
2021-03-12 19:07:25 +03:00
|
|
|
let e_uid = Desugared.Ast.IdentMap.find (fst edecl.enum_decl_name) ctxt.enum_idmap in
|
2020-12-04 20:02:49 +03:00
|
|
|
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
|
2020-12-09 16:51:22 +03:00
|
|
|
| None -> (Scopelang.Ast.TLit TUnit, cdecl_pos)
|
2020-12-04 20:48:16 +03:00
|
|
|
| Some typ -> process_type ctxt typ
|
2020-12-04 20:02:49 +03:00
|
|
|
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
|
|
|
|
|
2021-03-12 19:07:25 +03:00
|
|
|
(** Process the names of all declaration items *)
|
|
|
|
let process_name_item (ctxt : context) (item : Ast.code_item Pos.marked) : context =
|
2021-04-29 18:46:56 +03:00
|
|
|
let raise_already_defined_error (use : Uid.MarkedString.info) name pos msg =
|
2021-03-12 19:07:25 +03:00
|
|
|
Errors.raise_multispanned_error
|
2022-01-10 17:00:36 +03:00
|
|
|
(Format.asprintf "%s name \"%a\" already defined" msg
|
2022-01-10 20:36:14 +03:00
|
|
|
(Utils.Cli.format_with_style [ ANSITerminal.yellow ])
|
|
|
|
name)
|
2021-09-28 13:01:08 +03:00
|
|
|
[ (Some "First definition:", Pos.get_position use); (Some "Second definition:", pos) ]
|
2021-03-12 19:07:25 +03:00
|
|
|
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
|
2021-04-29 18:46:56 +03:00
|
|
|
| Some use ->
|
|
|
|
raise_already_defined_error (Scopelang.Ast.ScopeName.get_info use) name pos "scope"
|
2021-03-12 19:07:25 +03:00
|
|
|
| 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;
|
2022-01-03 20:39:59 +03:00
|
|
|
scope_defs_contexts = Desugared.Ast.ScopeDefMap.empty;
|
2021-03-12 19:07:25 +03:00
|
|
|
sub_scopes_idmap = Desugared.Ast.IdentMap.empty;
|
|
|
|
sub_scopes = Scopelang.Ast.SubScopeMap.empty;
|
|
|
|
}
|
|
|
|
ctxt.scopes;
|
2021-03-23 12:59:43 +03:00
|
|
|
})
|
2021-03-12 19:07:25 +03:00
|
|
|
| StructDecl sdecl -> (
|
|
|
|
let name, pos = sdecl.struct_decl_name in
|
2021-04-29 18:46:56 +03:00
|
|
|
match Desugared.Ast.IdentMap.find_opt name ctxt.struct_idmap with
|
|
|
|
| Some use ->
|
|
|
|
raise_already_defined_error (Scopelang.Ast.StructName.get_info use) name pos "struct"
|
2021-03-12 19:07:25 +03:00
|
|
|
| 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;
|
2021-03-23 12:59:43 +03:00
|
|
|
})
|
2021-03-12 19:07:25 +03:00
|
|
|
| EnumDecl edecl -> (
|
|
|
|
let name, pos = edecl.enum_decl_name in
|
2021-04-29 18:46:56 +03:00
|
|
|
match Desugared.Ast.IdentMap.find_opt name ctxt.enum_idmap with
|
|
|
|
| Some use ->
|
|
|
|
raise_already_defined_error (Scopelang.Ast.EnumName.get_info use) name pos "enum"
|
2021-03-12 19:07:25 +03:00
|
|
|
| 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;
|
2021-03-23 12:59:43 +03:00
|
|
|
})
|
2021-03-12 19:07:25 +03:00
|
|
|
| ScopeUse _ -> ctxt
|
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a code item that is a declaration *)
|
2020-11-25 12:49:53 +03:00
|
|
|
let process_decl_item (ctxt : context) (item : Ast.code_item Pos.marked) : context =
|
2020-12-04 20:02:49 +03:00
|
|
|
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
|
2020-07-16 13:04:23 +03:00
|
|
|
|
|
|
|
(** Process a code block *)
|
2020-11-25 12:49:53 +03:00
|
|
|
let process_code_block (ctxt : context) (block : Ast.code_block)
|
|
|
|
(process_item : context -> Ast.code_item Pos.marked -> context) : context =
|
2020-09-12 21:22:47 +03:00
|
|
|
List.fold_left (fun ctxt decl -> process_item ctxt decl) ctxt block
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a law structure, only considering the code blocks *)
|
2020-11-25 12:49:53 +03:00
|
|
|
let rec process_law_structure (ctxt : context) (s : Ast.law_structure)
|
|
|
|
(process_item : context -> Ast.code_item Pos.marked -> context) : context =
|
2020-10-04 02:25:37 +03:00
|
|
|
match s with
|
2020-11-25 12:49:53 +03:00
|
|
|
| Ast.LawHeading (_, children) ->
|
2020-10-04 02:25:37 +03:00
|
|
|
List.fold_left (fun ctxt child -> process_law_structure ctxt child process_item) ctxt children
|
2021-05-15 02:16:08 +03:00
|
|
|
| Ast.CodeBlock (block, _, _) -> process_code_block ctxt block process_item
|
|
|
|
| Ast.LawInclude _ | Ast.LawText _ -> ctxt
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2020-12-18 15:13:51 +03:00
|
|
|
(** {1 Scope uses pass} *)
|
|
|
|
|
2022-02-28 19:19:06 +03:00
|
|
|
let get_def_key (name : Ast.qident) (state : Ast.ident Pos.marked option)
|
|
|
|
(scope_uid : Scopelang.Ast.ScopeName.t) (ctxt : context) (default_pos : Pos.t) :
|
|
|
|
Desugared.Ast.ScopeDef.t =
|
2021-01-22 07:47:48 +03:00
|
|
|
let scope_ctxt = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in
|
|
|
|
match name with
|
|
|
|
| [ x ] ->
|
|
|
|
let x_uid = get_var_uid scope_uid ctxt x in
|
2022-03-07 13:55:26 +03:00
|
|
|
let var_sig = Desugared.Ast.ScopeVarMap.find x_uid ctxt.var_typs in
|
2022-02-28 19:19:06 +03:00
|
|
|
Desugared.Ast.ScopeDef.Var
|
|
|
|
( x_uid,
|
2022-03-07 13:55:26 +03:00
|
|
|
match state with
|
|
|
|
| Some state -> (
|
|
|
|
try Some (Desugared.Ast.IdentMap.find (Pos.unmark state) var_sig.var_sig_states_idmap)
|
2022-03-06 19:13:40 +03:00
|
|
|
with Not_found ->
|
|
|
|
Errors.raise_multispanned_error
|
|
|
|
(Format.asprintf "This identifier is not a state declared for variable %a."
|
|
|
|
Desugared.Ast.ScopeVar.format_t x_uid)
|
|
|
|
[
|
|
|
|
(None, Pos.get_position state);
|
|
|
|
( Some "Variable declaration:",
|
|
|
|
Pos.get_position (Desugared.Ast.ScopeVar.get_info x_uid) );
|
|
|
|
])
|
2022-03-07 13:55:26 +03:00
|
|
|
| None ->
|
|
|
|
if not (Desugared.Ast.IdentMap.is_empty var_sig.var_sig_states_idmap) then
|
|
|
|
Errors.raise_multispanned_error
|
|
|
|
(Format.asprintf
|
|
|
|
"This definition does not indicate which state has to be considered for \
|
|
|
|
variable %a."
|
|
|
|
Desugared.Ast.ScopeVar.format_t x_uid)
|
|
|
|
[
|
|
|
|
(None, Pos.get_position x);
|
|
|
|
( Some "Variable declaration:",
|
|
|
|
Pos.get_position (Desugared.Ast.ScopeVar.get_info x_uid) );
|
|
|
|
]
|
|
|
|
else None )
|
2021-01-22 07:47:48 +03:00
|
|
|
| [ y; x ] ->
|
2021-01-24 16:32:41 +03:00
|
|
|
let subscope_uid : Scopelang.Ast.SubScopeName.t = get_subscope_uid scope_uid ctxt y in
|
2021-01-22 07:47:48 +03:00
|
|
|
let subscope_real_uid : Scopelang.Ast.ScopeName.t =
|
|
|
|
Scopelang.Ast.SubScopeMap.find subscope_uid scope_ctxt.sub_scopes
|
|
|
|
in
|
|
|
|
let x_uid = get_var_uid subscope_real_uid ctxt x in
|
|
|
|
Desugared.Ast.ScopeDef.SubScopeVar (subscope_uid, x_uid)
|
2021-01-24 16:32:41 +03:00
|
|
|
| _ -> Errors.raise_spanned_error "Structs are not handled yet" default_pos
|
2021-01-22 07:47:48 +03:00
|
|
|
|
2020-12-18 15:13:51 +03:00
|
|
|
let process_definition (ctxt : context) (s_name : Scopelang.Ast.ScopeName.t) (d : Ast.definition) :
|
|
|
|
context =
|
2022-01-03 20:39:59 +03:00
|
|
|
(* We update the definition context inside the big context *)
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
scopes =
|
|
|
|
Scopelang.Ast.ScopeMap.update s_name
|
|
|
|
(fun (s_ctxt : scope_context option) ->
|
|
|
|
let def_key =
|
2022-02-28 19:19:06 +03:00
|
|
|
get_def_key (Pos.unmark d.definition_name) d.definition_state s_name ctxt
|
2022-01-03 20:39:59 +03:00
|
|
|
(Pos.get_position d.definition_expr)
|
|
|
|
in
|
|
|
|
match s_ctxt with
|
|
|
|
| None -> assert false (* should not happen *)
|
|
|
|
| Some s_ctxt ->
|
|
|
|
Some
|
|
|
|
{
|
|
|
|
s_ctxt with
|
|
|
|
scope_defs_contexts =
|
|
|
|
Desugared.Ast.ScopeDefMap.update def_key
|
|
|
|
(fun def_key_ctx ->
|
|
|
|
let def_key_ctx : scope_def_context =
|
|
|
|
Option.fold
|
|
|
|
~none:
|
|
|
|
{
|
|
|
|
(* Here, this is the first time we encounter a definition for this
|
|
|
|
definition key *)
|
|
|
|
default_exception_rulename = None;
|
|
|
|
label_idmap = Desugared.Ast.IdentMap.empty;
|
2022-01-04 20:19:15 +03:00
|
|
|
label_groups = Desugared.Ast.LabelMap.empty;
|
2022-01-03 20:39:59 +03:00
|
|
|
}
|
|
|
|
~some:(fun x -> x)
|
|
|
|
def_key_ctx
|
|
|
|
in
|
|
|
|
(* First, we update the def key context with information about the
|
|
|
|
definition's label*)
|
|
|
|
let def_key_ctx =
|
|
|
|
match d.Ast.definition_label with
|
|
|
|
| None -> def_key_ctx
|
2022-01-04 20:19:15 +03:00
|
|
|
| Some label ->
|
2022-01-05 17:37:34 +03:00
|
|
|
let new_label_idmap =
|
|
|
|
Desugared.Ast.IdentMap.update (Pos.unmark label)
|
|
|
|
(fun existing_label ->
|
|
|
|
match existing_label with
|
|
|
|
| Some existing_label -> Some existing_label
|
|
|
|
| None -> Some (Desugared.Ast.LabelName.fresh label))
|
|
|
|
def_key_ctx.label_idmap
|
|
|
|
in
|
|
|
|
let label_id =
|
|
|
|
Desugared.Ast.IdentMap.find (Pos.unmark label) new_label_idmap
|
|
|
|
in
|
2022-01-04 20:19:15 +03:00
|
|
|
{
|
|
|
|
def_key_ctx with
|
2022-01-05 17:37:34 +03:00
|
|
|
label_idmap = new_label_idmap;
|
|
|
|
label_groups =
|
|
|
|
Desugared.Ast.LabelMap.update label_id
|
|
|
|
(fun group ->
|
|
|
|
match group with
|
|
|
|
| None ->
|
|
|
|
Some (Desugared.Ast.RuleSet.singleton d.definition_id)
|
|
|
|
| Some existing_group ->
|
|
|
|
Some
|
|
|
|
(Desugared.Ast.RuleSet.add d.definition_id
|
|
|
|
existing_group))
|
|
|
|
def_key_ctx.label_groups;
|
2022-01-04 20:19:15 +03:00
|
|
|
}
|
2022-01-03 20:39:59 +03:00
|
|
|
in
|
|
|
|
(* And second, we update the map of default rulenames for unlabeled
|
|
|
|
exceptions *)
|
|
|
|
let def_key_ctx =
|
|
|
|
match d.Ast.definition_exception_to with
|
|
|
|
(* If this definition is an exception, it cannot be a default
|
|
|
|
definition *)
|
|
|
|
| UnlabeledException | ExceptionToLabel _ -> def_key_ctx
|
|
|
|
(* If it is not an exception, we need to distinguish between several
|
|
|
|
cases *)
|
|
|
|
| NotAnException -> (
|
|
|
|
match def_key_ctx.default_exception_rulename with
|
|
|
|
(* There was already a default definition for this key. If we need it,
|
|
|
|
it is ambiguous *)
|
|
|
|
| Some old ->
|
|
|
|
{
|
|
|
|
def_key_ctx with
|
|
|
|
default_exception_rulename =
|
|
|
|
Some
|
|
|
|
(Ambiguous
|
|
|
|
([ Pos.get_position d.definition_name ]
|
|
|
|
@
|
|
|
|
match old with
|
|
|
|
| Ambiguous old -> old
|
2022-01-05 17:57:18 +03:00
|
|
|
| Unique (_, pos) -> [ pos ]));
|
2022-01-03 20:39:59 +03:00
|
|
|
}
|
|
|
|
(* No definition has been set yet for this key *)
|
|
|
|
| None -> (
|
|
|
|
match d.Ast.definition_label with
|
|
|
|
(* This default definition has a label. This is not allowed for
|
|
|
|
unlabeled exceptions *)
|
|
|
|
| Some _ ->
|
|
|
|
{
|
|
|
|
def_key_ctx with
|
|
|
|
default_exception_rulename =
|
|
|
|
Some (Ambiguous [ Pos.get_position d.definition_name ]);
|
|
|
|
}
|
|
|
|
(* This is a possible default definition for this key. We create
|
|
|
|
and store a fresh rulename *)
|
|
|
|
| None ->
|
|
|
|
{
|
|
|
|
def_key_ctx with
|
2022-01-05 17:57:18 +03:00
|
|
|
default_exception_rulename =
|
|
|
|
Some
|
|
|
|
(Unique
|
|
|
|
(d.definition_id, Pos.get_position d.definition_name));
|
2022-01-03 20:39:59 +03:00
|
|
|
}))
|
|
|
|
in
|
|
|
|
Some def_key_ctx)
|
|
|
|
s_ctxt.scope_defs_contexts;
|
|
|
|
})
|
|
|
|
ctxt.scopes;
|
|
|
|
}
|
2020-12-18 15:13:51 +03:00
|
|
|
|
|
|
|
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
|
2021-11-28 15:09:44 +03:00
|
|
|
| Rule r -> process_definition ctxt s_name (Ast.rule_to_def r)
|
2020-12-18 15:13:51 +03:00
|
|
|
| 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
|
2022-01-10 17:00:36 +03:00
|
|
|
(Format.asprintf "\"%a\": this scope has not been declared anywhere, is it a typo?"
|
|
|
|
(Utils.Cli.format_with_style [ ANSITerminal.yellow ])
|
2022-01-10 20:36:14 +03:00
|
|
|
(Pos.unmark suse.Ast.scope_use_name))
|
2020-12-18 15:13:51 +03:00
|
|
|
(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
|
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** {1 API} *)
|
|
|
|
|
|
|
|
(** Derive the context from metadata, in one pass over the declarations *)
|
2020-11-25 12:49:53 +03:00
|
|
|
let form_context (prgm : Ast.program) : context =
|
2020-07-16 13:04:23 +03:00
|
|
|
let empty_ctxt =
|
2020-11-23 14:20:38 +03:00
|
|
|
{
|
2020-12-06 19:48:15 +03:00
|
|
|
local_var_idmap = Desugared.Ast.IdentMap.empty;
|
2020-11-25 12:49:53 +03:00
|
|
|
scope_idmap = Desugared.Ast.IdentMap.empty;
|
2020-11-23 14:20:38 +03:00
|
|
|
scopes = Scopelang.Ast.ScopeMap.empty;
|
2022-02-28 19:19:06 +03:00
|
|
|
var_typs = Desugared.Ast.ScopeVarMap.empty;
|
2020-12-04 18:40:17 +03:00
|
|
|
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;
|
2020-11-23 14:20:38 +03:00
|
|
|
}
|
2020-07-16 13:04:23 +03:00
|
|
|
in
|
2020-09-12 21:22:47 +03:00
|
|
|
let ctxt =
|
|
|
|
List.fold_left
|
2021-05-15 02:16:08 +03:00
|
|
|
(fun ctxt item -> process_law_structure ctxt item process_name_item)
|
2020-09-12 21:22:47 +03:00
|
|
|
empty_ctxt prgm.program_items
|
|
|
|
in
|
2021-03-12 19:07:25 +03:00
|
|
|
let ctxt =
|
|
|
|
List.fold_left
|
2021-05-15 02:16:08 +03:00
|
|
|
(fun ctxt item -> process_law_structure ctxt item process_decl_item)
|
2021-03-12 19:07:25 +03:00
|
|
|
ctxt prgm.program_items
|
|
|
|
in
|
2020-12-18 15:13:51 +03:00
|
|
|
let ctxt =
|
|
|
|
List.fold_left
|
2021-05-15 02:16:08 +03:00
|
|
|
(fun ctxt item -> process_law_structure ctxt item process_use_item)
|
2020-12-18 15:13:51 +03:00
|
|
|
ctxt prgm.program_items
|
|
|
|
in
|
2020-12-06 19:48:15 +03:00
|
|
|
ctxt
|