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:
|
2020-09-12 21:22:47 +03:00
|
|
|
Nicolas Chataing <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
|
2022-08-12 23:42:39 +03:00
|
|
|
open Shared_ast
|
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-07-15 17:14:11 +03:00
|
|
|
|
2022-01-05 17:57:18 +03:00
|
|
|
type unique_rulename =
|
|
|
|
| Ambiguous of Pos.t list
|
2022-05-30 12:20:48 +03:00
|
|
|
| Unique of Desugared.Ast.RuleName.t Marked.pos
|
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;
|
2022-01-03 20:39:59 +03:00
|
|
|
}
|
|
|
|
|
2020-09-12 21:22:47 +03:00
|
|
|
type scope_context = {
|
2022-08-25 13:09:51 +03:00
|
|
|
var_idmap : 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 *)
|
2022-08-17 18:14:29 +03:00
|
|
|
sub_scopes_idmap : SubScopeName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Sub-scopes variables *)
|
2022-08-12 23:42:39 +03:00
|
|
|
sub_scopes : 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
|
|
|
|
2022-08-17 18:14:29 +03:00
|
|
|
type struct_context = typ Marked.pos 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
|
|
|
|
2022-08-17 18:14:29 +03:00
|
|
|
type enum_context = typ Marked.pos 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 = {
|
2022-05-30 12:20:48 +03:00
|
|
|
var_sig_typ : typ Marked.pos;
|
2022-02-05 02:04:19 +03:00
|
|
|
var_sig_is_condition : bool;
|
2022-02-07 12:30:36 +03:00
|
|
|
var_sig_io : Ast.scope_decl_context_io;
|
2022-08-25 13:09:51 +03:00
|
|
|
var_sig_states_idmap : StateName.t Desugared.Ast.IdentMap.t;
|
|
|
|
var_sig_states_list : 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 *)
|
2022-08-12 23:42:39 +03:00
|
|
|
scope_idmap : ScopeName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** The names of the scopes *)
|
2022-08-12 23:42:39 +03:00
|
|
|
struct_idmap : StructName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** The names of the structs *)
|
2022-08-16 11:04:01 +03:00
|
|
|
field_idmap : StructFieldName.t 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 *)
|
2022-08-12 23:42:39 +03:00
|
|
|
enum_idmap : EnumName.t Desugared.Ast.IdentMap.t;
|
2020-12-14 17:23:04 +03:00
|
|
|
(** The names of the enums *)
|
2022-08-16 11:04:01 +03:00
|
|
|
constructor_idmap : EnumConstructor.t 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 *)
|
2022-08-16 11:04:01 +03:00
|
|
|
structs : struct_context StructMap.t; (** For each struct, its context *)
|
|
|
|
enums : enum_context 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) =
|
2022-03-08 15:04:27 +03:00
|
|
|
Errors.raise_spanned_error pos "Unsupported feature: %s" msg
|
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 *)
|
2022-05-30 12:20:48 +03:00
|
|
|
let raise_unknown_identifier (msg : string) (ident : ident Marked.pos) =
|
|
|
|
Errors.raise_spanned_error (Marked.get_mark ident)
|
2022-03-08 15:04:27 +03:00
|
|
|
"\"%s\": unknown identifier %s"
|
2022-05-30 12:20:48 +03:00
|
|
|
(Utils.Cli.with_style [ANSITerminal.yellow] "%s" (Marked.unmark ident))
|
2022-03-08 15:04:27 +03:00
|
|
|
msg
|
2020-07-16 15:46:40 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Gets the type associated to an uid *)
|
2022-08-25 13:09:51 +03:00
|
|
|
let get_var_typ (ctxt : context) (uid : ScopeVar.t) : typ Marked.pos =
|
2022-02-28 19:19:06 +03:00
|
|
|
(Desugared.Ast.ScopeVarMap.find uid ctxt.var_typs).var_sig_typ
|
2020-12-31 02:28:26 +03:00
|
|
|
|
2022-08-25 13:09:51 +03:00
|
|
|
let is_var_cond (ctxt : context) (uid : ScopeVar.t) : bool =
|
2022-02-28 19:19:06 +03:00
|
|
|
(Desugared.Ast.ScopeVarMap.find uid ctxt.var_typs).var_sig_is_condition
|
2022-02-05 02:04:19 +03:00
|
|
|
|
2022-08-25 13:09:51 +03:00
|
|
|
let get_var_io (ctxt : context) (uid : ScopeVar.t) : Ast.scope_decl_context_io =
|
2022-02-28 19:19:06 +03:00
|
|
|
(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
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope_uid : ScopeName.t)
|
2020-12-14 17:23:04 +03:00
|
|
|
(ctxt : context)
|
2022-08-25 13:09:51 +03:00
|
|
|
((x, pos) : ident Marked.pos) : 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
|
2022-08-16 11:04:01 +03:00
|
|
|
(Format.asprintf "for a variable of scope %a" ScopeName.format_t scope_uid)
|
2021-01-08 00:38:56 +03:00
|
|
|
(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
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope_uid : ScopeName.t)
|
2020-12-14 17:23:04 +03:00
|
|
|
(ctxt : context)
|
2022-08-17 18:14:29 +03:00
|
|
|
((y, pos) : ident Marked.pos) : SubScopeName.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 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]. *)
|
2022-08-16 11:04:01 +03:00
|
|
|
let is_subscope_uid (scope_uid : ScopeName.t) (ctxt : context) (y : ident) :
|
|
|
|
bool =
|
2020-12-14 17:23:04 +03:00
|
|
|
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-08-25 13:09:51 +03:00
|
|
|
let belongs_to (ctxt : context) (uid : ScopeVar.t) (scope_uid : ScopeName.t) :
|
|
|
|
bool =
|
2020-12-14 17:23:04 +03:00
|
|
|
let scope = Scopelang.Ast.ScopeMap.find scope_uid ctxt.scopes in
|
|
|
|
Desugared.Ast.IdentMap.exists
|
2022-08-25 13:09:51 +03:00
|
|
|
(fun _ var_uid -> 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) :
|
2022-05-30 12:20:48 +03:00
|
|
|
typ Marked.pos =
|
2020-12-14 17:23:04 +03:00
|
|
|
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
|
|
|
|
|
|
|
(** {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
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope : ScopeName.t)
|
2020-11-23 14:20:38 +03:00
|
|
|
(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
|
2020-09-13 01:33:56 +03:00
|
|
|
[
|
2022-08-17 18:14:29 +03:00
|
|
|
Some "first use", Marked.get_mark (SubScopeName.get_info use);
|
2020-09-13 01:33:56 +03:00
|
|
|
Some "second use", s_pos;
|
|
|
|
]
|
2022-03-08 15:04:27 +03:00
|
|
|
"Subscope name \"%a\" already used"
|
|
|
|
(Utils.Cli.format_with_style [ANSITerminal.yellow])
|
|
|
|
subscope
|
2020-07-16 15:46:40 +03:00
|
|
|
| None ->
|
2022-08-17 18:14:29 +03:00
|
|
|
let sub_scope_uid = 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-11-23 14:20:38 +03:00
|
|
|
{
|
|
|
|
scope_ctxt with
|
|
|
|
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;
|
|
|
|
}
|
2022-05-12 16:10:55 +03:00
|
|
|
in
|
|
|
|
{
|
2020-12-04 20:48:16 +03:00
|
|
|
ctxt with
|
2020-11-23 14:20:38 +03:00
|
|
|
scopes = Scopelang.Ast.ScopeMap.add scope scope_ctxt ctxt.scopes;
|
2022-05-12 16:10:55 +03:00
|
|
|
}
|
2020-07-16 13:04:23 +03:00
|
|
|
|
2022-05-30 12:20:48 +03:00
|
|
|
let is_type_cond ((typ, _) : Ast.typ Marked.pos) =
|
2020-12-31 02:28:26 +03:00
|
|
|
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)
|
2022-08-25 13:09:51 +03:00
|
|
|
((typ, typ_pos) : Ast.base_typ Marked.pos) : typ Marked.pos =
|
2020-08-06 16:18:40 +03:00
|
|
|
match typ with
|
2022-08-25 13:09:51 +03:00
|
|
|
| Ast.Condition -> TLit TBool, typ_pos
|
2020-12-30 00:26:10 +03:00
|
|
|
| Ast.Data (Ast.Collection t) ->
|
2022-08-25 13:09:51 +03:00
|
|
|
( TArray
|
|
|
|
(process_base_typ ctxt (Ast.Data (Marked.unmark t), Marked.get_mark t)),
|
2020-12-30 00:26:10 +03:00
|
|
|
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
|
2022-08-25 13:09:51 +03:00
|
|
|
| Ast.Integer -> TLit TInt, typ_pos
|
|
|
|
| Ast.Decimal -> TLit TRat, typ_pos
|
|
|
|
| Ast.Money -> TLit TMoney, typ_pos
|
|
|
|
| Ast.Duration -> TLit TDuration, typ_pos
|
|
|
|
| Ast.Date -> TLit TDate, typ_pos
|
|
|
|
| Ast.Boolean -> 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
|
2022-08-25 13:09:51 +03:00
|
|
|
| Some s_uid -> TStruct s_uid, typ_pos
|
2020-12-04 20:48:16 +03:00
|
|
|
| None -> (
|
|
|
|
match Desugared.Ast.IdentMap.find_opt ident ctxt.enum_idmap with
|
2022-08-25 13:09:51 +03:00
|
|
|
| Some e_uid -> TEnum e_uid, typ_pos
|
2020-12-04 20:48:16 +03:00
|
|
|
| None ->
|
2022-03-08 15:04:27 +03:00
|
|
|
Errors.raise_spanned_error typ_pos
|
|
|
|
"Unknown type \"%a\", not a struct or enum previously declared"
|
|
|
|
(Utils.Cli.format_with_style [ANSITerminal.yellow])
|
|
|
|
ident)))
|
2020-08-06 16:18:40 +03:00
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a type (function or not) *)
|
2022-05-30 12:20:48 +03:00
|
|
|
let process_type (ctxt : context) ((typ, typ_pos) : Ast.typ Marked.pos) :
|
2022-08-25 13:09:51 +03:00
|
|
|
typ Marked.pos =
|
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 } ->
|
2022-08-25 13:09:51 +03:00
|
|
|
( TArrow (process_base_typ ctxt arg_typ, process_base_typ ctxt return_typ),
|
2020-12-04 20:48:16 +03:00
|
|
|
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
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope : ScopeName.t)
|
2020-11-23 14:20:38 +03:00
|
|
|
(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
|
2020-11-23 18:12:45 +03:00
|
|
|
[
|
2022-08-25 13:09:51 +03:00
|
|
|
Some "First use:", Marked.get_mark (ScopeVar.get_info use);
|
2022-04-29 21:18:01 +03:00
|
|
|
Some "Second use:", pos;
|
2020-11-23 18:12:45 +03:00
|
|
|
]
|
2022-04-29 21:18:01 +03:00
|
|
|
"Variable name \"%a\" already used"
|
2022-03-08 15:04:27 +03:00
|
|
|
(Utils.Cli.format_with_style [ANSITerminal.yellow])
|
|
|
|
name
|
2020-09-12 21:22:47 +03:00
|
|
|
| None ->
|
2022-08-25 13:09:51 +03:00
|
|
|
let uid = ScopeVar.fresh (name, pos) in
|
2020-11-25 12:49:53 +03:00
|
|
|
let scope_ctxt =
|
2020-09-12 21:22:47 +03:00
|
|
|
{
|
2020-11-23 14:20:38 +03:00
|
|
|
scope_ctxt with
|
2022-02-28 19:19:06 +03:00
|
|
|
var_idmap = Desugared.Ast.IdentMap.add name uid scope_ctxt.var_idmap;
|
2020-09-12 21:22:47 +03:00
|
|
|
}
|
2022-05-12 16:10:55 +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) ->
|
2022-08-25 13:09:51 +03:00
|
|
|
let state_uid = StateName.fresh state_id in
|
2022-05-30 12:20:48 +03:00
|
|
|
( Desugared.Ast.IdentMap.add (Marked.unmark state_id) state_uid
|
2022-02-28 17:40:19 +03:00
|
|
|
states_idmap,
|
|
|
|
state_uid :: states_list ))
|
|
|
|
decl.scope_decl_context_item_states
|
|
|
|
(Desugared.Ast.IdentMap.empty, [])
|
2022-05-12 16:10:55 +03:00
|
|
|
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-05-12 16:10:55 +03:00
|
|
|
{
|
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-05-12 16:10:55 +03:00
|
|
|
}
|
2022-02-05 02:04:19 +03:00
|
|
|
ctxt.var_typs;
|
2022-05-12 16:10:55 +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
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope : ScopeName.t)
|
2020-11-23 14:20:38 +03:00
|
|
|
(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-06-03 17:40:03 +03:00
|
|
|
let add_def_local_var (ctxt : context) (name : ident) :
|
2022-02-28 20:34:32 +03:00
|
|
|
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 =
|
2022-06-03 17:40:03 +03:00
|
|
|
Desugared.Ast.IdentMap.add 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
|
2022-05-30 12:20:48 +03:00
|
|
|
(fun ctxt item -> process_item_decl scope_uid ctxt (Marked.unmark item))
|
2021-03-12 19:07:25 +03:00
|
|
|
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
|
2022-03-28 15:43:38 +03:00
|
|
|
if List.length sdecl.struct_decl_fields = 0 then
|
|
|
|
Errors.raise_spanned_error
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.get_mark sdecl.struct_decl_name)
|
2022-03-28 15:43:38 +03:00
|
|
|
"The struct %s does not have any fields; give it some for Catala to be \
|
|
|
|
able to accept it."
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark sdecl.struct_decl_name);
|
2020-12-04 20:02:49 +03:00
|
|
|
List.fold_left
|
|
|
|
(fun ctxt (fdecl, _) ->
|
2022-08-16 11:04:01 +03:00
|
|
|
let f_uid = StructFieldName.fresh fdecl.Ast.struct_decl_field_name in
|
2020-12-04 20:02:49 +03:00
|
|
|
let ctxt =
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
field_idmap =
|
|
|
|
Desugared.Ast.IdentMap.update
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark fdecl.Ast.struct_decl_field_name)
|
2020-12-04 20:02:49 +03:00
|
|
|
(fun uids ->
|
|
|
|
match uids with
|
2022-08-12 23:42:39 +03:00
|
|
|
| None -> Some (StructMap.singleton s_uid f_uid)
|
2022-08-16 11:04:01 +03:00
|
|
|
| Some uids -> Some (StructMap.add s_uid f_uid uids))
|
2020-12-04 20:02:49 +03:00
|
|
|
ctxt.field_idmap;
|
|
|
|
}
|
|
|
|
in
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
structs =
|
2022-08-12 23:42:39 +03:00
|
|
|
StructMap.update s_uid
|
2020-12-04 20:02:49 +03:00
|
|
|
(fun fields ->
|
|
|
|
match fields with
|
|
|
|
| None ->
|
|
|
|
Some
|
2022-08-17 18:14:29 +03:00
|
|
|
(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
|
2022-08-17 18:14:29 +03:00
|
|
|
(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
|
2022-03-28 15:43:38 +03:00
|
|
|
if List.length edecl.enum_decl_cases = 0 then
|
|
|
|
Errors.raise_spanned_error
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.get_mark edecl.enum_decl_name)
|
2022-03-28 15:43:38 +03:00
|
|
|
"The enum %s does not have any cases; give it some for Catala to be able \
|
|
|
|
to accept it."
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark edecl.enum_decl_name);
|
2020-12-04 20:02:49 +03:00
|
|
|
List.fold_left
|
|
|
|
(fun ctxt (cdecl, cdecl_pos) ->
|
2022-08-16 11:04:01 +03:00
|
|
|
let c_uid = EnumConstructor.fresh cdecl.Ast.enum_decl_case_name in
|
2020-12-04 20:02:49 +03:00
|
|
|
let ctxt =
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
constructor_idmap =
|
|
|
|
Desugared.Ast.IdentMap.update
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark cdecl.Ast.enum_decl_case_name)
|
2020-12-04 20:02:49 +03:00
|
|
|
(fun uids ->
|
|
|
|
match uids with
|
2022-08-12 23:42:39 +03:00
|
|
|
| None -> Some (EnumMap.singleton e_uid c_uid)
|
|
|
|
| Some uids -> Some (EnumMap.add e_uid c_uid uids))
|
2020-12-04 20:02:49 +03:00
|
|
|
ctxt.constructor_idmap;
|
|
|
|
}
|
|
|
|
in
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
enums =
|
2022-08-12 23:42:39 +03:00
|
|
|
EnumMap.update e_uid
|
2020-12-04 20:02:49 +03:00
|
|
|
(fun cases ->
|
|
|
|
let typ =
|
|
|
|
match cdecl.Ast.enum_decl_case_typ with
|
2022-08-25 13:09:51 +03:00
|
|
|
| None -> 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
|
2022-08-17 18:14:29 +03:00
|
|
|
| None -> Some (EnumConstructorMap.singleton c_uid typ)
|
|
|
|
| Some fields -> Some (EnumConstructorMap.add c_uid typ fields))
|
2020-12-04 20:02:49 +03:00
|
|
|
ctxt.enums;
|
|
|
|
})
|
|
|
|
ctxt edecl.enum_decl_cases
|
|
|
|
|
2021-03-12 19:07:25 +03:00
|
|
|
(** Process the names of all declaration items *)
|
2022-05-30 12:20:48 +03:00
|
|
|
let process_name_item (ctxt : context) (item : Ast.code_item Marked.pos) :
|
2021-03-12 19:07:25 +03:00
|
|
|
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
|
2021-09-28 13:01:08 +03:00
|
|
|
[
|
2022-05-30 12:20:48 +03:00
|
|
|
Some "First definition:", Marked.get_mark use;
|
2021-09-28 13:01:08 +03:00
|
|
|
Some "Second definition:", pos;
|
|
|
|
]
|
2022-03-08 15:04:27 +03:00
|
|
|
"%s name \"%a\" already defined" msg
|
|
|
|
(Utils.Cli.format_with_style [ANSITerminal.yellow])
|
|
|
|
name
|
2021-03-12 19:07:25 +03:00
|
|
|
in
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark item with
|
2021-03-12 19:07:25 +03:00
|
|
|
| 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 ->
|
2022-08-16 11:04:01 +03:00
|
|
|
raise_already_defined_error (ScopeName.get_info use) name pos "scope"
|
2021-03-12 19:07:25 +03:00
|
|
|
| None ->
|
2022-08-12 23:42:39 +03:00
|
|
|
let scope_uid = ScopeName.fresh (name, pos) in
|
2021-03-12 19:07:25 +03:00
|
|
|
{
|
|
|
|
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;
|
|
|
|
})
|
|
|
|
| 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 ->
|
2022-08-16 11:04:01 +03:00
|
|
|
raise_already_defined_error (StructName.get_info use) name pos "struct"
|
2021-03-12 19:07:25 +03:00
|
|
|
| None ->
|
2022-08-12 23:42:39 +03:00
|
|
|
let s_uid = StructName.fresh sdecl.struct_decl_name in
|
2021-03-12 19:07:25 +03:00
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
struct_idmap =
|
|
|
|
Desugared.Ast.IdentMap.add
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark sdecl.struct_decl_name)
|
2021-03-12 19:07:25 +03:00
|
|
|
s_uid ctxt.struct_idmap;
|
|
|
|
})
|
|
|
|
| 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 ->
|
2022-08-16 11:04:01 +03:00
|
|
|
raise_already_defined_error (EnumName.get_info use) name pos "enum"
|
2021-03-12 19:07:25 +03:00
|
|
|
| None ->
|
2022-08-12 23:42:39 +03:00
|
|
|
let e_uid = EnumName.fresh edecl.enum_decl_name in
|
2021-03-12 19:07:25 +03:00
|
|
|
|
|
|
|
{
|
|
|
|
ctxt with
|
|
|
|
enum_idmap =
|
|
|
|
Desugared.Ast.IdentMap.add
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark edecl.enum_decl_name)
|
2021-03-12 19:07:25 +03:00
|
|
|
e_uid ctxt.enum_idmap;
|
|
|
|
})
|
|
|
|
| ScopeUse _ -> ctxt
|
|
|
|
|
2020-12-14 17:23:04 +03:00
|
|
|
(** Process a code item that is a declaration *)
|
2022-05-30 12:20:48 +03:00
|
|
|
let process_decl_item (ctxt : context) (item : Ast.code_item Marked.pos) :
|
2020-11-25 12:49:53 +03:00
|
|
|
context =
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark item with
|
2020-12-04 20:02:49 +03:00
|
|
|
| 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)
|
2022-05-30 12:20:48 +03:00
|
|
|
(process_item : context -> Ast.code_item Marked.pos -> 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)
|
2022-05-30 12:20:48 +03:00
|
|
|
(process_item : context -> Ast.code_item Marked.pos -> 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)
|
2022-05-30 12:20:48 +03:00
|
|
|
(state : Ast.ident Marked.pos option)
|
2022-08-12 23:42:39 +03:00
|
|
|
(scope_uid : ScopeName.t)
|
2022-02-28 19:19:06 +03:00
|
|
|
(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
|
2022-05-30 12:20:48 +03:00
|
|
|
(Desugared.Ast.IdentMap.find (Marked.unmark state)
|
2022-03-07 13:55:26 +03:00
|
|
|
var_sig.var_sig_states_idmap)
|
2022-03-06 19:13:40 +03:00
|
|
|
with Not_found ->
|
|
|
|
Errors.raise_multispanned_error
|
|
|
|
[
|
2022-05-30 12:20:48 +03:00
|
|
|
None, Marked.get_mark state;
|
2022-03-06 19:13:40 +03:00
|
|
|
( Some "Variable declaration:",
|
2022-08-25 13:09:51 +03:00
|
|
|
Marked.get_mark (ScopeVar.get_info x_uid) );
|
2022-03-08 15:04:27 +03:00
|
|
|
]
|
|
|
|
"This identifier is not a state declared for variable %a."
|
2022-08-25 13:09:51 +03:00
|
|
|
ScopeVar.format_t 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
|
|
|
|
[
|
2022-05-30 12:20:48 +03:00
|
|
|
None, Marked.get_mark x;
|
2022-03-07 13:55:26 +03:00
|
|
|
( Some "Variable declaration:",
|
2022-08-25 13:09:51 +03:00
|
|
|
Marked.get_mark (ScopeVar.get_info x_uid) );
|
2022-03-07 13:55:26 +03:00
|
|
|
]
|
2022-03-08 15:04:27 +03:00
|
|
|
"This definition does not indicate which state has to be \
|
|
|
|
considered for variable %a."
|
2022-08-25 13:09:51 +03:00
|
|
|
ScopeVar.format_t x_uid
|
2022-03-07 13:55:26 +03:00
|
|
|
else None )
|
2021-01-22 07:47:48 +03:00
|
|
|
| [y; x] ->
|
2022-08-17 18:14:29 +03:00
|
|
|
let subscope_uid : SubScopeName.t = get_subscope_uid scope_uid ctxt y in
|
2022-08-12 23:42:39 +03:00
|
|
|
let subscope_real_uid : ScopeName.t =
|
2021-01-22 07:47:48 +03:00
|
|
|
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)
|
2022-06-01 12:13:14 +03:00
|
|
|
| _ ->
|
|
|
|
Errors.raise_spanned_error default_pos
|
|
|
|
"This line is defining a quantity that is neither a scope variable nor a \
|
|
|
|
subscope variable. In particular, it is not possible to define struct \
|
|
|
|
fields individually in Catala."
|
2021-01-22 07:47:48 +03:00
|
|
|
|
2020-12-18 15:13:51 +03:00
|
|
|
let process_definition
|
|
|
|
(ctxt : context)
|
2022-08-12 23:42:39 +03:00
|
|
|
(s_name : ScopeName.t)
|
2020-12-18 15:13:51 +03:00
|
|
|
(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
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark d.definition_name)
|
2022-02-28 19:19:06 +03:00
|
|
|
d.definition_state s_name ctxt
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.get_mark d.definition_expr)
|
2022-01-03 20:39:59 +03:00
|
|
|
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:
|
2022-05-12 16:10:55 +03:00
|
|
|
{
|
2022-01-03 20:39:59 +03:00
|
|
|
(* 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-05-12 16:10:55 +03:00
|
|
|
}
|
2022-01-03 20:39:59 +03:00
|
|
|
~some:(fun x -> x)
|
|
|
|
def_key_ctx
|
2022-05-12 16:10:55 +03:00
|
|
|
in
|
2022-01-03 20:39:59 +03:00
|
|
|
(* 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 =
|
2022-05-30 12:20:48 +03:00
|
|
|
Desugared.Ast.IdentMap.update (Marked.unmark label)
|
2022-01-05 17:37:34 +03:00
|
|
|
(fun existing_label ->
|
|
|
|
match existing_label with
|
|
|
|
| Some existing_label -> Some existing_label
|
2022-01-03 20:39:59 +03:00
|
|
|
| None ->
|
2022-01-05 17:37:34 +03:00
|
|
|
Some (Desugared.Ast.LabelName.fresh label))
|
|
|
|
def_key_ctx.label_idmap
|
2022-05-12 16:10:55 +03:00
|
|
|
in
|
2022-07-13 16:00:57 +03:00
|
|
|
{ def_key_ctx with label_idmap = new_label_idmap }
|
2022-05-12 16:10:55 +03:00
|
|
|
in
|
2022-01-03 20:39:59 +03:00
|
|
|
(* 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 ->
|
2022-05-12 16:10:55 +03:00
|
|
|
{
|
2022-01-03 20:39:59 +03:00
|
|
|
def_key_ctx with
|
|
|
|
default_exception_rulename =
|
2022-05-12 16:10:55 +03:00
|
|
|
Some
|
2022-01-03 20:39:59 +03:00
|
|
|
(Ambiguous
|
2022-05-30 12:20:48 +03:00
|
|
|
([Marked.get_mark d.definition_name]
|
2022-05-12 16:10:55 +03:00
|
|
|
@
|
2022-01-03 20:39:59 +03:00
|
|
|
match old with
|
|
|
|
| Ambiguous old -> old
|
2022-01-05 17:57:18 +03:00
|
|
|
| Unique (_, pos) -> [pos]));
|
2022-05-12 16:10:55 +03:00
|
|
|
}
|
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 =
|
2022-05-12 16:10:55 +03:00
|
|
|
Some
|
2022-01-04 20:19:15 +03:00
|
|
|
(Ambiguous
|
2022-05-30 12:20:48 +03:00
|
|
|
[Marked.get_mark d.definition_name]);
|
2022-01-03 20:39:59 +03:00
|
|
|
}
|
|
|
|
(* This is a possible default definition for this
|
|
|
|
key. We create and store a fresh rulename *)
|
2022-01-05 17:37:34 +03:00
|
|
|
| None ->
|
2022-01-04 20:19:15 +03:00
|
|
|
{
|
|
|
|
def_key_ctx with
|
2022-01-05 17:37:34 +03:00
|
|
|
default_exception_rulename =
|
2022-01-03 20:39:59 +03:00
|
|
|
Some
|
|
|
|
(Unique
|
|
|
|
( d.definition_id,
|
2022-05-30 12:20:48 +03:00
|
|
|
Marked.get_mark d.definition_name ));
|
2022-01-05 17:57:18 +03:00
|
|
|
}))
|
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
|
2022-08-12 23:42:39 +03:00
|
|
|
(s_name : ScopeName.t)
|
2020-12-18 15:13:51 +03:00
|
|
|
(ctxt : context)
|
2022-05-30 12:20:48 +03:00
|
|
|
(sitem : Ast.scope_use_item Marked.pos) : context =
|
|
|
|
match Marked.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
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark suse.Ast.scope_use_name)
|
2020-12-18 15:13:51 +03:00
|
|
|
ctxt.scope_idmap
|
|
|
|
with Not_found ->
|
|
|
|
Errors.raise_spanned_error
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.get_mark suse.Ast.scope_use_name)
|
2022-03-08 15:04:27 +03:00
|
|
|
"\"%a\": this scope has not been declared anywhere, is it a typo?"
|
|
|
|
(Utils.Cli.format_with_style [ANSITerminal.yellow])
|
2022-05-30 12:20:48 +03:00
|
|
|
(Marked.unmark suse.Ast.scope_use_name)
|
2020-12-18 15:13:51 +03:00
|
|
|
in
|
|
|
|
List.fold_left (process_scope_use_item s_name) ctxt suse.Ast.scope_use_items
|
|
|
|
|
2022-05-30 12:20:48 +03:00
|
|
|
let process_use_item (ctxt : context) (item : Ast.code_item Marked.pos) :
|
2020-12-18 15:13:51 +03:00
|
|
|
context =
|
2022-05-30 12:20:48 +03:00
|
|
|
match Marked.unmark item with
|
2020-12-18 15:13:51 +03:00
|
|
|
| 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;
|
2022-08-12 23:42:39 +03:00
|
|
|
structs = StructMap.empty;
|
2020-12-04 18:40:17 +03:00
|
|
|
struct_idmap = Desugared.Ast.IdentMap.empty;
|
|
|
|
field_idmap = Desugared.Ast.IdentMap.empty;
|
2022-08-12 23:42:39 +03:00
|
|
|
enums = EnumMap.empty;
|
2020-12-04 18:40:17 +03:00
|
|
|
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
|