2019-12-10 12:00:21 -06:00
|
|
|
open Trace
|
2019-05-12 20:56:22 +00:00
|
|
|
open Ast_simplified
|
|
|
|
|
|
|
|
module Raw = Parser.Pascaligo.AST
|
|
|
|
module SMap = Map.String
|
2020-01-14 01:27:35 +01:00
|
|
|
module ParserLog = Parser_pascaligo.ParserLog
|
2019-05-12 20:56:22 +00:00
|
|
|
|
|
|
|
open Combinators
|
|
|
|
|
|
|
|
let nseq_to_list (hd, tl) = hd :: tl
|
|
|
|
let npseq_to_list (hd, tl) = hd :: (List.map snd tl)
|
|
|
|
let pseq_to_list = function
|
2020-01-21 18:35:36 +01:00
|
|
|
None -> []
|
|
|
|
| Some lst -> npseq_to_list lst
|
2019-05-12 20:56:22 +00:00
|
|
|
let get_value : 'a Raw.reg -> 'a = fun x -> x.value
|
2019-11-19 13:25:48 +00:00
|
|
|
|
2020-02-19 14:18:06 +01:00
|
|
|
and repair_mutable_variable_in_matching (for_body : expression) (element_names : expression_variable list) (env : expression_variable) =
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind captured_names = Self_ast_simplified.fold_map_expression
|
|
|
|
(* TODO : these should use Variables sets *)
|
|
|
|
(fun (decl_var,free_var : expression_variable list * expression_variable list) (ass_exp : expression) ->
|
|
|
|
match ass_exp.expression_content with
|
|
|
|
| E_let_in {let_binder;mut=false;rhs;let_result} ->
|
|
|
|
let (name,_) = let_binder in
|
|
|
|
ok (true,(name::decl_var, free_var),e_let_in let_binder false false rhs let_result)
|
|
|
|
| E_let_in {let_binder;mut=true; rhs;let_result} ->
|
|
|
|
let (name,_) = let_binder in
|
|
|
|
if List.mem name decl_var then
|
|
|
|
ok (true,(decl_var, free_var), e_let_in let_binder false false rhs let_result)
|
|
|
|
else(
|
|
|
|
let free_var = if (List.mem name free_var) then free_var else name::free_var in
|
2020-02-18 14:19:11 +01:00
|
|
|
let expr = e_let_in (env,None) false false (e_update (e_variable env) (Var.to_name name) (e_variable name)) let_result in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok (true,(decl_var, free_var), e_let_in let_binder false false rhs expr)
|
|
|
|
)
|
|
|
|
| E_variable name ->
|
|
|
|
if List.mem name decl_var || List.mem name free_var || Var.equal name env then
|
|
|
|
ok (true,(decl_var, free_var), e_variable name)
|
|
|
|
else
|
|
|
|
ok (true, (decl_var, name::free_var), e_variable name)
|
|
|
|
| E_constant {cons_name=C_MAP_FOLD;arguments= _}
|
|
|
|
| E_constant {cons_name=C_SET_FOLD;arguments= _}
|
|
|
|
| E_constant {cons_name=C_LIST_FOLD;arguments= _}
|
|
|
|
| E_matching _ -> ok @@ (false, (decl_var,free_var),ass_exp)
|
|
|
|
| _ -> ok (true, (decl_var, free_var),ass_exp)
|
|
|
|
)
|
|
|
|
(element_names,[])
|
|
|
|
for_body in
|
|
|
|
ok @@ captured_names
|
|
|
|
|
2020-02-19 14:18:06 +01:00
|
|
|
and repair_mutable_variable_in_loops (for_body : expression) (element_names : expression_variable list) (env : expression_variable) =
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind captured_names = Self_ast_simplified.fold_map_expression
|
|
|
|
(* TODO : these should use Variables sets *)
|
|
|
|
(fun (decl_var,free_var : expression_variable list * expression_variable list) (ass_exp : expression) ->
|
|
|
|
match ass_exp.expression_content with
|
|
|
|
| E_let_in {let_binder;mut=false;rhs;let_result} ->
|
|
|
|
let (name,_) = let_binder in
|
|
|
|
ok (true,(name::decl_var, free_var),e_let_in let_binder false false rhs let_result)
|
|
|
|
| E_let_in {let_binder;mut=true; rhs;let_result} ->
|
|
|
|
let (name,_) = let_binder in
|
|
|
|
if List.mem name decl_var then
|
|
|
|
ok (true,(decl_var, free_var), e_let_in let_binder false false rhs let_result)
|
|
|
|
else(
|
|
|
|
let free_var = if (List.mem name free_var) then free_var else name::free_var in
|
|
|
|
let expr = e_let_in (env,None) false false (
|
|
|
|
e_update (e_variable env) ("0")
|
2020-02-18 14:19:11 +01:00
|
|
|
(e_update (e_accessor (e_variable env) "0") (Var.to_name name) (e_variable name))
|
2019-12-04 18:30:52 +01:00
|
|
|
)
|
|
|
|
let_result in
|
|
|
|
ok (true,(decl_var, free_var), e_let_in let_binder false false rhs expr)
|
|
|
|
)
|
|
|
|
| E_variable name ->
|
|
|
|
if List.mem name decl_var || List.mem name free_var || Var.equal name env then
|
|
|
|
ok (true,(decl_var, free_var), e_variable name)
|
|
|
|
else
|
|
|
|
ok (true,(decl_var, name::free_var), e_variable name)
|
|
|
|
| E_constant {cons_name=C_MAP_FOLD;arguments= _}
|
|
|
|
| E_constant {cons_name=C_SET_FOLD;arguments= _}
|
|
|
|
| E_constant {cons_name=C_LIST_FOLD;arguments= _}
|
|
|
|
| E_matching _ -> ok @@ (false,(decl_var,free_var),ass_exp)
|
|
|
|
| _ -> ok (true,(decl_var, free_var),ass_exp)
|
|
|
|
)
|
|
|
|
(element_names,[])
|
|
|
|
for_body in
|
|
|
|
ok @@ captured_names
|
|
|
|
|
|
|
|
and store_mutable_variable (free_vars : expression_variable list) =
|
|
|
|
if (List.length free_vars == 0) then
|
|
|
|
e_unit ()
|
|
|
|
else
|
2020-02-18 14:19:11 +01:00
|
|
|
let aux var = (Var.to_name var, e_variable var) in
|
2019-12-04 18:30:52 +01:00
|
|
|
e_record_ez (List.map aux free_vars)
|
|
|
|
|
2020-02-19 14:18:06 +01:00
|
|
|
and restore_mutable_variable (expr : expression->expression) (free_vars : expression_variable list) (env :expression_variable) =
|
2019-12-04 18:30:52 +01:00
|
|
|
let aux (f:expression -> expression) (ev:expression_variable) =
|
2020-02-18 14:19:11 +01:00
|
|
|
ok @@ fun expr -> f (e_let_in (ev,None) true false (e_accessor (e_variable env) (Var.to_name ev)) expr)
|
2019-12-04 18:30:52 +01:00
|
|
|
in
|
|
|
|
let%bind ef = bind_fold_list aux (fun e -> e) free_vars in
|
|
|
|
ok @@ fun expr'_opt -> match expr'_opt with
|
2020-02-19 14:18:06 +01:00
|
|
|
| None -> ok @@ expr (ef (e_skip ()))
|
|
|
|
| Some expr' -> ok @@ expr (ef expr')
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
2019-06-04 16:12:17 +02:00
|
|
|
module Errors = struct
|
2019-06-13 16:57:40 +02:00
|
|
|
let unsupported_cst_constr p =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-13 16:57:40 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nConstant constructors are not supported yet.\n" in
|
2019-06-13 16:57:40 +02:00
|
|
|
let pattern_loc = Raw.pattern_to_region p in
|
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-13 16:57:40 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
2019-06-04 16:12:17 +02:00
|
|
|
let unknown_predefined_type name =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "\nType constants" in
|
2019-06-04 16:12:17 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "Unknown predefined type \"%s\".\n" name.Region.value in
|
2019-06-04 16:12:17 +02:00
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-04 16:12:17 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ name.Region.region)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
2019-06-05 17:51:06 +02:00
|
|
|
let unsupported_non_var_pattern p =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nNon-variable patterns in constructors \
|
|
|
|
are not supported yet.\n" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let pattern_loc = Raw.pattern_to_region p in
|
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-05 17:51:06 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
|
|
|
let only_constructors p =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nCurrently, only constructors \
|
|
|
|
are supported in patterns.\n" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let pattern_loc = Raw.pattern_to_region p in
|
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-05 17:51:06 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
|
|
|
let unsupported_tuple_pattern p =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nTuple patterns are not supported yet.\n" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let pattern_loc = Raw.pattern_to_region p in
|
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-09-21 11:30:41 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc) ;
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
(** TODO: The labelled arguments should be flowing from the CLI. *)
|
2019-09-21 11:30:41 +02:00
|
|
|
("pattern",
|
2020-01-14 01:27:35 +01:00
|
|
|
fun () -> ParserLog.pattern_to_string
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
~offsets:true ~mode:`Point p)
|
2019-06-05 17:51:06 +02:00
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
|
|
|
let unsupported_deep_Some_patterns pattern =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nCurrently, only variables in constructors \
|
|
|
|
\"Some\" in patterns are supported.\n" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let pattern_loc = Raw.pattern_to_region pattern in
|
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-05 17:51:06 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ pattern_loc)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
|
|
|
let unsupported_deep_list_patterns cons =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () =
|
2020-01-24 14:03:25 +01:00
|
|
|
Format.asprintf "\nCurrently, only empty lists and x::y \
|
|
|
|
are supported in patterns.\n" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let data = [
|
2019-12-30 15:24:42 -06:00
|
|
|
("location",
|
2019-06-05 17:51:06 +02:00
|
|
|
fun () -> Format.asprintf "%a" Location.pp_lift @@ cons.Region.region)
|
|
|
|
] in
|
|
|
|
error ~data title message
|
|
|
|
|
|
|
|
(* Logging *)
|
|
|
|
|
|
|
|
let simplifying_instruction t =
|
2020-01-24 14:03:25 +01:00
|
|
|
let title () = "\nSimplifiying instruction" in
|
2019-06-05 17:51:06 +02:00
|
|
|
let message () = "" in
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
(** TODO: The labelled arguments should be flowing from the CLI. *)
|
2019-06-05 17:51:06 +02:00
|
|
|
let data = [
|
|
|
|
("instruction",
|
2020-01-14 01:27:35 +01:00
|
|
|
fun () -> ParserLog.instruction_to_string
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
~offsets:true ~mode:`Point t)
|
2019-06-05 17:51:06 +02:00
|
|
|
] in
|
|
|
|
error ~data title message
|
2019-06-04 16:12:17 +02:00
|
|
|
end
|
|
|
|
|
|
|
|
open Errors
|
2019-05-23 12:16:12 +00:00
|
|
|
open Operators.Simplify.Pascaligo
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
let r_split = Location.r_split
|
|
|
|
|
2020-01-09 17:26:07 +01:00
|
|
|
(* Statements can't be simplified in isolation. [a ; b ; c] can get
|
|
|
|
simplified either as [let x = expr in (b ; c)] if [a] is a [const x
|
|
|
|
= expr] declaration or as [sequence(a, sequence(b, c))] for
|
|
|
|
everything else. Because of this, simplifying sequences depend on
|
|
|
|
their contents. To avoid peeking in their contents, we instead
|
|
|
|
simplify sequences elements as functions from their next elements
|
|
|
|
to the actual result.
|
|
|
|
|
|
|
|
For [return_let_in], if there is no follow-up element, an error is
|
|
|
|
triggered, as you can't have [let x = expr in ...] with no [...]. A
|
|
|
|
cleaner option might be to add a [unit] instead of failing.
|
2019-09-10 12:42:49 +02:00
|
|
|
|
2020-01-09 17:26:07 +01:00
|
|
|
[return_statement] is used for non-let-in statements.
|
|
|
|
*)
|
2019-09-10 12:42:49 +02:00
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
let return_let_in ?loc binder mut inline rhs = ok @@ fun expr'_opt ->
|
2019-05-22 00:46:54 +00:00
|
|
|
match expr'_opt with
|
2019-12-04 18:30:52 +01:00
|
|
|
| None -> ok @@ e_let_in ?loc binder mut inline rhs (e_skip ())
|
|
|
|
| Some expr' -> ok @@ e_let_in ?loc binder mut inline rhs expr'
|
2019-05-22 00:46:54 +00:00
|
|
|
|
2019-09-10 12:42:49 +02:00
|
|
|
let return_statement expr = ok @@ fun expr'_opt ->
|
|
|
|
match expr'_opt with
|
|
|
|
| None -> ok @@ expr
|
|
|
|
| Some expr' -> ok @@ e_sequence expr expr'
|
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
|
2019-05-12 20:56:22 +00:00
|
|
|
let rec simpl_type_expression (t:Raw.type_expr) : type_expression result =
|
|
|
|
match t with
|
2019-11-06 17:23:49 +01:00
|
|
|
TPar x -> simpl_type_expression x.value.inside
|
|
|
|
| TVar v -> (
|
2019-12-04 11:40:58 +00:00
|
|
|
match type_constants v.value with
|
|
|
|
| Ok (s,_) -> ok @@ make_t @@ T_constant s
|
|
|
|
| Error _ -> ok @@ make_t @@ T_variable (Var.of_name v.value)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| TFun x -> (
|
|
|
|
let%bind (a , b) =
|
|
|
|
let (a , _ , b) = x.value in
|
|
|
|
bind_map_pair simpl_type_expression (a , b) in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok @@ make_t @@ T_arrow {type1=a;type2=b}
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| TApp x ->
|
|
|
|
let (name, tuple) = x.value in
|
|
|
|
let lst = npseq_to_list tuple.value.inside in
|
2020-01-09 17:26:07 +01:00
|
|
|
let%bind lst =
|
|
|
|
bind_list @@ List.map simpl_type_expression lst in (** TODO: fix constant and operator*)
|
2019-05-23 12:16:12 +00:00
|
|
|
let%bind cst =
|
2019-12-04 11:40:58 +00:00
|
|
|
trace (unknown_predefined_type name) @@
|
|
|
|
type_operators name.value in
|
2019-12-24 12:20:39 +01:00
|
|
|
t_operator cst lst
|
2019-05-12 20:56:22 +00:00
|
|
|
| TProd p ->
|
|
|
|
let%bind tpl = simpl_list_type_expression
|
2019-09-10 12:42:49 +02:00
|
|
|
@@ npseq_to_list p.value in
|
2019-05-12 20:56:22 +00:00
|
|
|
ok tpl
|
|
|
|
| TRecord r ->
|
2019-09-10 12:42:49 +02:00
|
|
|
let aux = fun (x, y) ->
|
|
|
|
let%bind y = simpl_type_expression y in
|
|
|
|
ok (x, y)
|
|
|
|
in
|
2019-06-04 16:12:17 +02:00
|
|
|
let apply =
|
|
|
|
fun (x:Raw.field_decl Raw.reg) -> (x.value.field_name.value, x.value.field_type) in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind lst = bind_list
|
|
|
|
@@ List.map aux
|
2019-06-04 16:12:17 +02:00
|
|
|
@@ List.map apply
|
2019-10-23 00:35:29 +02:00
|
|
|
@@ npseq_to_list r.value.ne_elements in
|
2019-12-04 11:40:58 +00:00
|
|
|
let m = List.fold_left (fun m (x, y) -> LMap.add (Label x) y m) LMap.empty lst in
|
|
|
|
ok @@ make_t @@ T_record m
|
2019-05-12 20:56:22 +00:00
|
|
|
| TSum s ->
|
|
|
|
let aux (v:Raw.variant Raw.reg) =
|
2019-05-17 16:29:22 +02:00
|
|
|
let args =
|
2019-11-06 17:23:49 +01:00
|
|
|
match v.value.arg with
|
2019-05-17 16:29:22 +02:00
|
|
|
None -> []
|
2019-11-06 17:23:49 +01:00
|
|
|
| Some (_, TProd product) -> npseq_to_list product.value
|
|
|
|
| Some (_, t_expr) -> [t_expr] in
|
2019-10-15 21:03:46 +02:00
|
|
|
let%bind te = simpl_list_type_expression @@ args in
|
2019-05-12 20:56:22 +00:00
|
|
|
ok (v.value.constr.value, te)
|
|
|
|
in
|
|
|
|
let%bind lst = bind_list
|
|
|
|
@@ List.map aux
|
|
|
|
@@ npseq_to_list s.value in
|
2019-12-04 11:40:58 +00:00
|
|
|
let m = List.fold_left (fun m (x, y) -> CMap.add (Constructor x) y m) CMap.empty lst in
|
|
|
|
ok @@ make_t @@ T_sum m
|
2019-05-12 20:56:22 +00:00
|
|
|
|
|
|
|
and simpl_list_type_expression (lst:Raw.type_expr list) : type_expression result =
|
|
|
|
match lst with
|
2019-06-06 20:49:36 +00:00
|
|
|
| [] -> ok @@ t_unit
|
2019-05-12 20:56:22 +00:00
|
|
|
| [hd] -> simpl_type_expression hd
|
|
|
|
| lst ->
|
|
|
|
let%bind lst = bind_list @@ List.map simpl_type_expression lst in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok @@ t_tuple lst
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-09-10 12:42:49 +02:00
|
|
|
let simpl_projection : Raw.projection Region.reg -> _ = fun p ->
|
|
|
|
let (p' , loc) = r_split p in
|
|
|
|
let var =
|
2019-12-04 11:40:58 +00:00
|
|
|
let name = Var.of_name p'.struct_name.value in
|
2019-09-10 12:42:49 +02:00
|
|
|
e_variable name in
|
|
|
|
let path = p'.field_path in
|
2020-02-20 05:25:30 +00:00
|
|
|
let path' =
|
2019-09-10 12:42:49 +02:00
|
|
|
let aux (s:Raw.selection) =
|
|
|
|
match s with
|
2020-02-20 05:25:30 +00:00
|
|
|
| FieldName property -> property.value
|
|
|
|
| Component index -> (Z.to_string (snd index.value))
|
2019-09-10 12:42:49 +02:00
|
|
|
in
|
2020-02-20 05:25:30 +00:00
|
|
|
List.map aux @@ npseq_to_list path in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok @@ List.fold_left (e_accessor ~loc) var path'
|
2019-09-10 12:42:49 +02:00
|
|
|
|
|
|
|
|
2019-05-23 06:22:58 +00:00
|
|
|
let rec simpl_expression (t:Raw.expr) : expr result =
|
|
|
|
let return x = ok x in
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
|
|
|
| EAnnot a -> (
|
2019-05-28 15:36:14 +00:00
|
|
|
let ((expr , type_expr) , loc) = r_split a in
|
2019-05-23 06:22:58 +00:00
|
|
|
let%bind expr' = simpl_expression expr in
|
|
|
|
let%bind type_expr' = simpl_type_expression type_expr in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_annotation ~loc expr' type_expr'
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| EVar c -> (
|
2019-05-28 15:36:14 +00:00
|
|
|
let (c' , loc) = r_split c in
|
2019-12-04 11:40:58 +00:00
|
|
|
match constants c' with
|
|
|
|
| Error _ -> return @@ e_variable ~loc (Var.of_name c.value)
|
|
|
|
| Ok (s,_) -> return @@ e_constant ~loc s []
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| ECall x -> (
|
2019-11-14 20:12:41 +01:00
|
|
|
let ((f, args) , loc) = r_split x in
|
2019-05-28 15:36:14 +00:00
|
|
|
let (args , args_loc) = r_split args in
|
|
|
|
let args' = npseq_to_list args.inside in
|
2019-11-14 20:12:41 +01:00
|
|
|
match f with
|
|
|
|
| EVar name -> (
|
|
|
|
let (f_name , f_loc) = r_split name in
|
2019-12-04 11:40:58 +00:00
|
|
|
match constants f_name with
|
|
|
|
| Error _ ->
|
2019-11-14 20:12:41 +01:00
|
|
|
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
2019-12-04 11:40:58 +00:00
|
|
|
return @@ e_application ~loc (e_variable ~loc:f_loc (Var.of_name f_name)) arg
|
|
|
|
| Ok (s,_) ->
|
2019-11-14 20:12:41 +01:00
|
|
|
let%bind lst = bind_map_list simpl_expression args' in
|
|
|
|
return @@ e_constant ~loc s lst
|
|
|
|
)
|
|
|
|
| f -> (
|
|
|
|
let%bind f' = simpl_expression f in
|
|
|
|
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
|
|
|
return @@ e_application ~loc f' arg
|
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
2019-05-23 06:22:58 +00:00
|
|
|
| EPar x -> simpl_expression x.value.inside
|
2019-05-28 15:36:14 +00:00
|
|
|
| EUnit reg ->
|
|
|
|
let loc = Location.lift reg in
|
|
|
|
return @@ e_literal ~loc Literal_unit
|
|
|
|
| EBytes x ->
|
|
|
|
let (x' , loc) = r_split x in
|
2020-01-09 16:50:27 -06:00
|
|
|
return @@ e_literal ~loc (Literal_bytes (Hex.to_bytes @@ snd x'))
|
2019-05-12 20:56:22 +00:00
|
|
|
| ETuple tpl ->
|
2019-10-15 21:03:46 +02:00
|
|
|
let (tpl' , loc) = r_split tpl in
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_tuple_expression ~loc @@ npseq_to_list tpl'.inside
|
2019-05-12 20:56:22 +00:00
|
|
|
| ERecord r ->
|
|
|
|
let%bind fields = bind_list
|
|
|
|
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = simpl_expression v in ok (k.value, v))
|
|
|
|
@@ List.map (fun (x:Raw.field_assign Raw.reg) -> (x.value.field_name, x.value.field_expr))
|
2019-11-06 17:23:49 +01:00
|
|
|
@@ npseq_to_list r.value.ne_elements in
|
2019-05-12 20:56:22 +00:00
|
|
|
let aux prev (k, v) = SMap.add k v prev in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_record (List.fold_left aux SMap.empty fields)
|
|
|
|
| EProj p -> simpl_projection p
|
2020-01-09 18:23:37 +01:00
|
|
|
| EUpdate u -> simpl_update u
|
2019-05-28 15:36:14 +00:00
|
|
|
| EConstr (ConstrApp c) -> (
|
|
|
|
let ((c, args) , loc) = r_split c in
|
2019-06-11 17:10:27 +02:00
|
|
|
match args with
|
2020-02-24 17:29:45 +01:00
|
|
|
None ->
|
|
|
|
return @@ e_constructor ~loc c.value (e_unit ())
|
2019-06-11 17:10:27 +02:00
|
|
|
| Some args ->
|
|
|
|
let args, args_loc = r_split args in
|
|
|
|
let%bind arg =
|
|
|
|
simpl_tuple_expression ~loc:args_loc
|
|
|
|
@@ npseq_to_list args.inside in
|
|
|
|
return @@ e_constructor ~loc c.value arg
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| EConstr (SomeApp a) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let ((_, args) , loc) = r_split a in
|
|
|
|
let (args , args_loc) = r_split args in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind arg =
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_tuple_expression ~loc:args_loc
|
|
|
|
@@ npseq_to_list args.inside in
|
2019-12-04 11:40:58 +00:00
|
|
|
return @@ e_constant ~loc C_SOME [arg]
|
2019-05-28 15:36:14 +00:00
|
|
|
| EConstr (NoneExpr reg) -> (
|
|
|
|
let loc = Location.lift reg in
|
|
|
|
return @@ e_none ~loc ()
|
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Add c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "ADD" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Sub c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "SUB" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Mult c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "TIMES" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Div c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "DIV" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Mod c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "MOD" c
|
|
|
|
| EArith (Int n) -> (
|
|
|
|
let (n , loc) = r_split n in
|
|
|
|
let n = Z.to_int @@ snd n in
|
|
|
|
return @@ e_literal ~loc (Literal_int n)
|
|
|
|
)
|
|
|
|
| EArith (Nat n) -> (
|
|
|
|
let (n , loc) = r_split n in
|
|
|
|
let n = Z.to_int @@ snd @@ n in
|
|
|
|
return @@ e_literal ~loc (Literal_nat n)
|
|
|
|
)
|
2019-10-27 11:50:24 -05:00
|
|
|
| EArith (Mutez n) -> (
|
2019-07-19 12:13:09 +02:00
|
|
|
let (n , loc) = r_split n in
|
|
|
|
let n = Z.to_int @@ snd @@ n in
|
2019-09-24 14:29:18 +02:00
|
|
|
return @@ e_literal ~loc (Literal_mutez n)
|
2019-07-19 12:13:09 +02:00
|
|
|
)
|
|
|
|
| EArith (Neg e) -> simpl_unop "NEG" e
|
2019-05-12 20:56:22 +00:00
|
|
|
| EString (String s) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let (s , loc) = r_split s in
|
2019-05-12 20:56:22 +00:00
|
|
|
let s' =
|
2019-05-28 15:36:14 +00:00
|
|
|
(* S contains quotes *)
|
2019-06-04 16:12:17 +02:00
|
|
|
String.(sub s 1 (length s - 2))
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_literal ~loc (Literal_string s')
|
2019-10-07 17:16:03 +02:00
|
|
|
| EString (Cat bo) ->
|
|
|
|
let (bo , loc) = r_split bo in
|
|
|
|
let%bind sl = simpl_expression bo.arg1 in
|
|
|
|
let%bind sr = simpl_expression bo.arg2 in
|
|
|
|
return @@ e_string_cat ~loc sl sr
|
2019-05-23 06:22:58 +00:00
|
|
|
| ELogic l -> simpl_logic_expression l
|
|
|
|
| EList l -> simpl_list_expression l
|
2019-07-19 14:35:47 +02:00
|
|
|
| ESet s -> simpl_set_expression s
|
2019-10-18 14:47:04 +02:00
|
|
|
| ECond c ->
|
2019-10-18 14:32:58 +02:00
|
|
|
let (c , loc) = r_split c in
|
|
|
|
let%bind expr = simpl_expression c.test in
|
|
|
|
let%bind match_true = simpl_expression c.ifso in
|
|
|
|
let%bind match_false = simpl_expression c.ifnot in
|
2019-12-04 18:30:52 +01:00
|
|
|
let match_expr = e_matching expr ~loc (Match_bool {match_true; match_false}) in
|
|
|
|
let env = Var.fresh () in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind (_, match_expr) = repair_mutable_variable_in_matching match_expr [] env in
|
2019-12-04 18:30:52 +01:00
|
|
|
return @@ match_expr
|
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
| ECase c -> (
|
|
|
|
let (c , loc) = r_split c in
|
|
|
|
let%bind e = simpl_expression c.expr in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind lst =
|
|
|
|
let aux (x : Raw.expr Raw.case_clause) =
|
|
|
|
let%bind expr = simpl_expression x.rhs in
|
|
|
|
ok (x.pattern, expr) in
|
|
|
|
bind_list
|
|
|
|
@@ List.map aux
|
|
|
|
@@ List.map get_value
|
2019-05-28 15:36:14 +00:00
|
|
|
@@ npseq_to_list c.cases.value in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind cases = simpl_cases lst in
|
2019-12-04 18:30:52 +01:00
|
|
|
let match_expr = e_matching ~loc e cases in
|
|
|
|
let env = Var.fresh () in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind (_, match_expr) = repair_mutable_variable_in_matching match_expr [] env in
|
2019-12-04 18:30:52 +01:00
|
|
|
return @@ match_expr
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
2019-10-21 13:04:28 +02:00
|
|
|
| EMap (MapInj mi) -> (
|
2019-05-28 15:36:14 +00:00
|
|
|
let (mi , loc) = r_split mi in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind lst =
|
2019-05-28 15:36:14 +00:00
|
|
|
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
2019-06-04 16:12:17 +02:00
|
|
|
let aux : Raw.binding -> (expression * expression) result =
|
|
|
|
fun b ->
|
|
|
|
let%bind src = simpl_expression b.source in
|
|
|
|
let%bind dst = simpl_expression b.image in
|
|
|
|
ok (src, dst) in
|
2019-05-12 20:56:22 +00:00
|
|
|
bind_map_list aux lst in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_map ~loc lst
|
|
|
|
)
|
2019-10-21 13:04:28 +02:00
|
|
|
| EMap (BigMapInj mi) -> (
|
|
|
|
let (mi , loc) = r_split mi in
|
|
|
|
let%bind lst =
|
|
|
|
let lst = List.map get_value @@ pseq_to_list mi.elements in
|
|
|
|
let aux : Raw.binding -> (expression * expression) result =
|
|
|
|
fun b ->
|
|
|
|
let%bind src = simpl_expression b.source in
|
|
|
|
let%bind dst = simpl_expression b.image in
|
|
|
|
ok (src, dst) in
|
|
|
|
bind_map_list aux lst in
|
|
|
|
return @@ e_big_map ~loc lst
|
|
|
|
)
|
2019-05-28 15:36:14 +00:00
|
|
|
| EMap (MapLookUp lu) -> (
|
|
|
|
let (lu , loc) = r_split lu in
|
|
|
|
let%bind path = match lu.path with
|
|
|
|
| Name v -> (
|
|
|
|
let (v , loc) = r_split v in
|
2019-12-04 11:40:58 +00:00
|
|
|
return @@ e_variable ~loc (Var.of_name v)
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
|
|
|
| Path p -> simpl_projection p
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
2019-05-28 15:36:14 +00:00
|
|
|
let%bind index = simpl_expression lu.index.value.inside in
|
|
|
|
return @@ e_look_up ~loc path index
|
|
|
|
)
|
2020-01-09 17:26:07 +01:00
|
|
|
| EFun f ->
|
2019-11-18 16:10:48 +01:00
|
|
|
let (f , loc) = r_split f in
|
2020-01-09 17:26:07 +01:00
|
|
|
let%bind (_ty_opt, f') = simpl_fun_expression ~loc f
|
|
|
|
in return @@ f'
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-01-09 18:23:37 +01:00
|
|
|
|
|
|
|
and simpl_update = fun (u:Raw.update Region.reg) ->
|
|
|
|
let (u, loc) = r_split u in
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name, path) = simpl_path u.record in
|
2020-01-21 18:35:36 +01:00
|
|
|
let record = match path with
|
2020-01-09 18:23:37 +01:00
|
|
|
| [] -> e_variable (Var.of_name name)
|
2019-12-04 18:30:52 +01:00
|
|
|
| _ -> e_accessor_list (e_variable (Var.of_name name)) path in
|
2020-01-09 18:23:37 +01:00
|
|
|
let updates = u.updates.value.ne_elements in
|
|
|
|
let%bind updates' =
|
2020-01-28 14:12:46 +00:00
|
|
|
let aux (f:Raw.field_path_assign Raw.reg) =
|
2020-01-09 18:23:37 +01:00
|
|
|
let (f,_) = r_split f in
|
|
|
|
let%bind expr = simpl_expression f.field_expr in
|
2020-01-28 14:12:46 +00:00
|
|
|
ok ( List.map (fun (x: _ Raw.reg) -> x.value) (npseq_to_list f.field_path), expr)
|
2020-01-09 18:23:37 +01:00
|
|
|
in
|
2020-01-21 18:35:36 +01:00
|
|
|
bind_map_list aux @@ npseq_to_list updates
|
2020-01-09 18:23:37 +01:00
|
|
|
in
|
2020-01-28 14:12:46 +00:00
|
|
|
let aux ur (path, expr) =
|
|
|
|
let rec aux record = function
|
|
|
|
| [] -> failwith "error in parsing"
|
|
|
|
| hd :: [] -> ok @@ e_update ~loc record hd expr
|
|
|
|
| hd :: tl ->
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind expr = (aux (e_accessor ~loc record hd) tl) in
|
2020-01-28 14:12:46 +00:00
|
|
|
ok @@ e_update ~loc record hd expr
|
|
|
|
in
|
|
|
|
aux ur path in
|
|
|
|
bind_fold_list aux record updates'
|
2020-01-09 18:23:37 +01:00
|
|
|
|
2019-05-23 06:22:58 +00:00
|
|
|
and simpl_logic_expression (t:Raw.logic_expr) : expression result =
|
|
|
|
let return x = ok x in
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
2019-05-28 15:36:14 +00:00
|
|
|
| BoolExpr (False reg) -> (
|
|
|
|
let loc = Location.lift reg in
|
|
|
|
return @@ e_literal ~loc (Literal_bool false)
|
|
|
|
)
|
|
|
|
| BoolExpr (True reg) -> (
|
|
|
|
let loc = Location.lift reg in
|
|
|
|
return @@ e_literal ~loc (Literal_bool true)
|
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (Or b) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "OR" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (And b) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "AND" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (Not b) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_unop "NOT" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Lt c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "LT" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Gt c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "GT" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Leq c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "LE" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Geq c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "GE" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Equal c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "EQ" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Neq c) ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "NEQ" c
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-05-23 06:22:58 +00:00
|
|
|
and simpl_list_expression (t:Raw.list_expr) : expression result =
|
|
|
|
let return x = ok x in
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
2019-11-06 17:23:49 +01:00
|
|
|
ECons c ->
|
2019-05-28 15:36:14 +00:00
|
|
|
simpl_binop "CONS" c
|
2019-11-06 17:23:49 +01:00
|
|
|
| EListComp lst ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let (lst , loc) = r_split lst in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind lst' =
|
|
|
|
bind_map_list simpl_expression @@
|
2019-05-28 15:36:14 +00:00
|
|
|
pseq_to_list lst.elements in
|
|
|
|
return @@ e_list ~loc lst'
|
2019-11-06 17:23:49 +01:00
|
|
|
| ENil reg ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let loc = Location.lift reg in
|
|
|
|
return @@ e_list ~loc []
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-07-19 14:35:47 +02:00
|
|
|
and simpl_set_expression (t:Raw.set_expr) : expression result =
|
|
|
|
match t with
|
|
|
|
| SetMem x -> (
|
|
|
|
let (x' , loc) = r_split x in
|
|
|
|
let%bind set' = simpl_expression x'.set in
|
|
|
|
let%bind element' = simpl_expression x'.element in
|
2019-12-04 11:40:58 +00:00
|
|
|
ok @@ e_constant ~loc C_SET_MEM [ element' ; set' ]
|
2019-07-19 14:35:47 +02:00
|
|
|
)
|
|
|
|
| SetInj x -> (
|
|
|
|
let (x' , loc) = r_split x in
|
|
|
|
let elements = pseq_to_list x'.elements in
|
|
|
|
let%bind elements' = bind_map_list simpl_expression elements in
|
|
|
|
ok @@ e_set ~loc elements'
|
|
|
|
)
|
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
and simpl_binop (name:string) (t:_ Raw.bin_op Region.reg) : expression result =
|
2019-05-23 06:22:58 +00:00
|
|
|
let return x = ok x in
|
2019-05-28 15:36:14 +00:00
|
|
|
let (t , loc) = r_split t in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind a = simpl_expression t.arg1 in
|
|
|
|
let%bind b = simpl_expression t.arg2 in
|
2019-12-04 11:40:58 +00:00
|
|
|
let%bind name = constants name in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_constant ~loc name [ a ; b ]
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
and simpl_unop (name:string) (t:_ Raw.un_op Region.reg) : expression result =
|
2019-05-23 06:22:58 +00:00
|
|
|
let return x = ok x in
|
2019-05-28 15:36:14 +00:00
|
|
|
let (t , loc) = r_split t in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind a = simpl_expression t.arg in
|
2019-12-04 11:40:58 +00:00
|
|
|
let%bind name = constants name in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_constant ~loc name [ a ]
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
and simpl_tuple_expression ?loc (lst:Raw.expr list) : expression result =
|
2019-05-23 06:22:58 +00:00
|
|
|
let return x = ok x in
|
2019-05-12 20:56:22 +00:00
|
|
|
match lst with
|
2019-05-28 15:36:14 +00:00
|
|
|
| [] -> return @@ e_literal Literal_unit
|
2019-05-23 06:22:58 +00:00
|
|
|
| [hd] -> simpl_expression hd
|
2019-06-04 16:12:17 +02:00
|
|
|
| lst ->
|
2020-01-21 18:35:36 +01:00
|
|
|
let%bind lst = bind_list @@ List.map simpl_expression lst
|
|
|
|
in return @@ e_tuple ?loc lst
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-01-21 18:35:36 +01:00
|
|
|
and simpl_data_declaration : Raw.data_decl -> _ result =
|
|
|
|
fun t ->
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
|
|
|
| LocalVar x ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let (x , loc) = r_split x in
|
2019-05-12 20:56:22 +00:00
|
|
|
let name = x.name.value in
|
|
|
|
let%bind t = simpl_type_expression x.var_type in
|
2019-05-23 06:22:58 +00:00
|
|
|
let%bind expression = simpl_expression x.init in
|
2019-12-04 18:30:52 +01:00
|
|
|
return_let_in ~loc (Var.of_name name, Some t) false false expression
|
2019-05-12 20:56:22 +00:00
|
|
|
| LocalConst x ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let (x , loc) = r_split x in
|
2019-05-12 20:56:22 +00:00
|
|
|
let name = x.name.value in
|
|
|
|
let%bind t = simpl_type_expression x.const_type in
|
2019-05-23 06:22:58 +00:00
|
|
|
let%bind expression = simpl_expression x.init in
|
2020-01-21 18:35:36 +01:00
|
|
|
let inline =
|
|
|
|
match x.attributes with
|
|
|
|
None -> false
|
|
|
|
| Some {value; _} ->
|
|
|
|
npseq_to_list value.ne_elements
|
|
|
|
|> List.exists (fun Region.{value; _} -> value = "\"inline\"")
|
2019-12-04 18:30:52 +01:00
|
|
|
in return_let_in ~loc (Var.of_name name, Some t) false inline expression
|
2019-11-18 16:10:48 +01:00
|
|
|
| LocalFun f ->
|
|
|
|
let (f , loc) = r_split f in
|
2020-01-16 19:36:04 +00:00
|
|
|
let%bind (binder, expr) = simpl_fun_decl ~loc f in
|
2020-01-21 18:35:36 +01:00
|
|
|
let inline =
|
|
|
|
match f.attributes with
|
|
|
|
None -> false
|
|
|
|
| Some {value; _} ->
|
|
|
|
npseq_to_list value.ne_elements
|
|
|
|
|> List.exists (fun Region.{value; _} -> value = "\"inline\"")
|
2019-12-04 18:30:52 +01:00
|
|
|
in return_let_in ~loc binder false inline expr
|
2020-01-21 18:35:36 +01:00
|
|
|
|
|
|
|
and simpl_param :
|
2019-12-04 18:30:52 +01:00
|
|
|
Raw.param_decl -> (string * type_expression) result =
|
2019-06-04 16:12:17 +02:00
|
|
|
fun t ->
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
|
|
|
| ParamConst c ->
|
|
|
|
let c = c.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
let param_name = c.var.value in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind type_expression = simpl_type_expression c.param_type in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok (param_name , type_expression)
|
2019-05-12 20:56:22 +00:00
|
|
|
| ParamVar v ->
|
|
|
|
let c = v.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
let param_name = c.var.value in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind type_expression = simpl_type_expression c.param_type in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok (param_name , type_expression)
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-01-09 17:26:07 +01:00
|
|
|
and simpl_fun_decl :
|
2020-01-21 18:35:36 +01:00
|
|
|
loc:_ -> Raw.fun_decl ->
|
|
|
|
((expression_variable * type_expression option) * expression) result =
|
2019-06-04 16:12:17 +02:00
|
|
|
fun ~loc x ->
|
2019-05-12 20:56:22 +00:00
|
|
|
let open! Raw in
|
2020-01-21 18:35:36 +01:00
|
|
|
let {fun_name; param; ret_type; block_with;
|
|
|
|
return; attributes} : fun_decl = x in
|
|
|
|
let inline =
|
|
|
|
match attributes with
|
|
|
|
None -> false
|
|
|
|
| Some {value; _} ->
|
|
|
|
npseq_to_list value.ne_elements
|
|
|
|
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
|
2019-10-19 10:46:24 -07:00
|
|
|
let statements =
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
match block_with with
|
|
|
|
| Some (block,_) -> npseq_to_list block.value.statements
|
2019-10-19 10:46:24 -07:00
|
|
|
| None -> []
|
2019-10-19 09:11:18 -07:00
|
|
|
in
|
2019-10-17 18:46:40 +02:00
|
|
|
(match param.value.inside with
|
|
|
|
a, [] -> (
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind input = simpl_param a in
|
2019-05-23 06:22:58 +00:00
|
|
|
let (binder , input_type) = input in
|
2020-01-21 18:35:36 +01:00
|
|
|
let%bind instructions = simpl_statement_list statements in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind result = simpl_expression return in
|
|
|
|
let%bind output_type = simpl_type_expression ret_type in
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
let body = instructions in
|
2019-05-22 00:46:54 +00:00
|
|
|
let%bind result =
|
|
|
|
let aux prec cur = cur (Some prec) in
|
|
|
|
bind_fold_right_list aux result body in
|
2019-12-04 18:30:52 +01:00
|
|
|
let expression : expression = e_lambda ~loc (Var.of_name binder) (Some input_type)
|
2019-05-28 15:36:14 +00:00
|
|
|
(Some output_type) result in
|
2020-01-09 17:26:07 +01:00
|
|
|
let type_annotation =
|
2019-12-04 18:30:52 +01:00
|
|
|
Some (make_t @@ T_arrow {type1=input_type;type2=output_type}) in
|
2020-01-09 17:26:07 +01:00
|
|
|
ok ((Var.of_name fun_name.value, type_annotation), expression)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| lst -> (
|
2019-10-17 18:46:40 +02:00
|
|
|
let lst = npseq_to_list lst in
|
2020-01-09 17:26:07 +01:00
|
|
|
(* TODO wrong, should be fresh? *)
|
|
|
|
let arguments_name = Var.of_name "arguments" in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind params = bind_map_list simpl_param lst in
|
2019-05-23 06:22:58 +00:00
|
|
|
let (binder , input_type) =
|
2019-12-06 18:32:00 +01:00
|
|
|
let type_expression = t_tuple (List.map snd params) in
|
2019-05-23 06:22:58 +00:00
|
|
|
(arguments_name , type_expression) in
|
2019-05-22 00:46:54 +00:00
|
|
|
let%bind tpl_declarations =
|
2019-12-04 18:30:52 +01:00
|
|
|
let aux = fun i (param, type_expr) ->
|
2020-01-09 17:26:07 +01:00
|
|
|
let expr =
|
2019-12-04 18:30:52 +01:00
|
|
|
e_accessor (e_variable arguments_name) (string_of_int i) in
|
|
|
|
let type_variable = Some type_expr in
|
|
|
|
let ass = return_let_in (Var.of_name param , type_variable) false inline expr in
|
2019-05-12 20:56:22 +00:00
|
|
|
ass
|
|
|
|
in
|
2019-05-22 00:46:54 +00:00
|
|
|
bind_list @@ List.mapi aux params in
|
2020-01-21 18:35:36 +01:00
|
|
|
let%bind instructions = simpl_statement_list statements in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind result = simpl_expression return in
|
2019-05-22 00:46:54 +00:00
|
|
|
let%bind output_type = simpl_type_expression ret_type in
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
let body = tpl_declarations @ instructions in
|
2019-05-22 00:46:54 +00:00
|
|
|
let%bind result =
|
|
|
|
let aux prec cur = cur (Some prec) in
|
|
|
|
bind_fold_right_list aux result body in
|
2019-06-04 16:12:17 +02:00
|
|
|
let expression =
|
2019-12-04 18:30:52 +01:00
|
|
|
e_lambda ~loc binder (Some (input_type)) (Some output_type) result in
|
|
|
|
let type_annotation = Some (make_t @@ T_arrow {type1=input_type; type2=output_type}) in
|
2020-01-09 17:26:07 +01:00
|
|
|
ok ((Var.of_name fun_name.value, type_annotation), expression)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
)
|
2020-01-09 17:26:07 +01:00
|
|
|
|
|
|
|
and simpl_fun_expression :
|
|
|
|
loc:_ -> Raw.fun_expr -> (type_expression option * expression) result =
|
|
|
|
fun ~loc x ->
|
|
|
|
let open! Raw in
|
|
|
|
let {param;ret_type;return;_} : fun_expr = x in
|
|
|
|
let statements = [] in
|
|
|
|
(match param.value.inside with
|
|
|
|
a, [] -> (
|
|
|
|
let%bind input = simpl_param a in
|
|
|
|
let (binder , input_type) = input in
|
2020-01-21 18:35:36 +01:00
|
|
|
let%bind instructions = simpl_statement_list statements in
|
2020-01-09 17:26:07 +01:00
|
|
|
let%bind result = simpl_expression return in
|
|
|
|
let%bind output_type = simpl_type_expression ret_type in
|
|
|
|
let body = instructions in
|
|
|
|
let%bind result =
|
|
|
|
let aux prec cur = cur (Some prec) in
|
|
|
|
bind_fold_right_list aux result body in
|
2019-12-04 18:30:52 +01:00
|
|
|
let expression : expression = e_lambda ~loc (Var.of_name binder) (Some input_type)
|
2020-01-09 17:26:07 +01:00
|
|
|
(Some output_type) result in
|
2019-12-04 18:30:52 +01:00
|
|
|
let type_annotation = Some (make_t @@ T_arrow {type1=input_type;type2=output_type}) in
|
|
|
|
ok (type_annotation , expression)
|
2020-01-09 17:26:07 +01:00
|
|
|
)
|
|
|
|
| lst -> (
|
|
|
|
let lst = npseq_to_list lst in
|
|
|
|
(* TODO wrong, should be fresh? *)
|
|
|
|
let arguments_name = Var.of_name "arguments" in
|
|
|
|
let%bind params = bind_map_list simpl_param lst in
|
|
|
|
let (binder , input_type) =
|
2019-12-06 18:32:00 +01:00
|
|
|
let type_expression = t_tuple (List.map snd params) in
|
2020-01-09 17:26:07 +01:00
|
|
|
(arguments_name , type_expression) in
|
|
|
|
let%bind tpl_declarations =
|
2019-12-04 18:30:52 +01:00
|
|
|
let aux = fun i (param, param_type) ->
|
|
|
|
let expr = e_accessor (e_variable arguments_name) (string_of_int i) in
|
|
|
|
let type_variable = Some param_type in
|
|
|
|
let ass = return_let_in (Var.of_name param , type_variable) false false expr in
|
2020-01-09 17:26:07 +01:00
|
|
|
ass
|
|
|
|
in
|
|
|
|
bind_list @@ List.mapi aux params in
|
2020-01-21 18:35:36 +01:00
|
|
|
let%bind instructions = simpl_statement_list statements in
|
2020-01-09 17:26:07 +01:00
|
|
|
let%bind result = simpl_expression return in
|
|
|
|
let%bind output_type = simpl_type_expression ret_type in
|
|
|
|
let body = tpl_declarations @ instructions in
|
|
|
|
let%bind result =
|
|
|
|
let aux prec cur = cur (Some prec) in
|
|
|
|
bind_fold_right_list aux result body in
|
|
|
|
let expression =
|
2019-12-06 18:32:00 +01:00
|
|
|
e_lambda ~loc binder (Some (input_type)) (Some output_type) result in
|
2019-12-04 18:30:52 +01:00
|
|
|
let type_annotation = Some (make_t @@ T_arrow {type1=input_type;type2=output_type}) in
|
|
|
|
ok (type_annotation , expression)
|
2020-01-09 17:26:07 +01:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2020-01-21 18:35:36 +01:00
|
|
|
and simpl_statement_list statements =
|
|
|
|
let open Raw in
|
|
|
|
let rec hook acc = function
|
|
|
|
[] -> acc
|
|
|
|
| [Attr _] ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
acc
|
|
|
|
| Attr _ :: (Attr _ :: _ as statements) ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
hook acc statements
|
|
|
|
| Attr decl :: Data (LocalConst {value; region}) :: statements ->
|
|
|
|
let new_const =
|
|
|
|
Data (LocalConst {value = {value with attributes = Some decl}; region})
|
|
|
|
in hook acc (new_const :: statements)
|
|
|
|
| Attr decl :: Data (LocalFun {value; region}) :: statements ->
|
|
|
|
let new_fun =
|
|
|
|
Data (LocalFun {value = {value with attributes = Some decl}; region})
|
|
|
|
in hook acc (new_fun :: statements)
|
|
|
|
| Attr _ :: statements ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
hook acc statements
|
|
|
|
| Instr i :: statements ->
|
|
|
|
hook (simpl_instruction i :: acc) statements
|
|
|
|
| Data d :: statements ->
|
|
|
|
hook (simpl_data_declaration d :: acc) statements
|
|
|
|
in bind_list @@ hook [] (List.rev statements)
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
and get_case_variables (t:Raw.pattern) : expression_variable list result =
|
|
|
|
match t with
|
|
|
|
| PConstr PFalse _
|
|
|
|
| PConstr PTrue _
|
|
|
|
| PConstr PNone _ -> ok @@ []
|
|
|
|
| PConstr PSomeApp v -> (let (_,v) = v.value in get_case_variables (v.value.inside))
|
|
|
|
| PConstr PConstrApp v -> (
|
|
|
|
match v.value with
|
|
|
|
| constr, None -> ok @@ [ Var.of_name constr.value]
|
|
|
|
| constr, pat_opt ->
|
|
|
|
let%bind pat =
|
|
|
|
trace_option (unsupported_cst_constr t) @@
|
|
|
|
pat_opt in
|
|
|
|
let pat = npseq_to_list pat.value.inside in
|
|
|
|
let%bind var = bind_map_list get_case_variables pat in
|
|
|
|
ok @@ [Var.of_name constr.value ] @ (List.concat var)
|
|
|
|
)
|
|
|
|
| PList PNil _ -> ok @@ []
|
|
|
|
| PList PCons c -> (
|
|
|
|
match c.value with
|
|
|
|
| a, [(_, b)] ->
|
|
|
|
let%bind a = get_case_variables a in
|
|
|
|
let%bind b = get_case_variables b in
|
|
|
|
ok @@ a@b
|
|
|
|
| _ -> fail @@ unsupported_deep_list_patterns c
|
|
|
|
)
|
|
|
|
| PVar v -> ok @@ [Var.of_name v.value]
|
|
|
|
| p -> fail @@ unsupported_cst_constr p
|
|
|
|
|
2019-10-17 18:33:58 +02:00
|
|
|
and simpl_single_instruction : Raw.instruction -> (_ -> expression result) result =
|
2019-06-04 16:12:17 +02:00
|
|
|
fun t ->
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
2019-07-20 13:46:42 +02:00
|
|
|
| ProcCall x -> (
|
2020-01-21 18:35:36 +01:00
|
|
|
let (f, args) , loc = r_split x in
|
|
|
|
let args, args_loc = r_split args in
|
2019-11-14 20:12:41 +01:00
|
|
|
let args' = npseq_to_list args.inside in
|
|
|
|
match f with
|
|
|
|
| EVar name -> (
|
|
|
|
let (f_name , f_loc) = r_split name in
|
2019-12-04 11:40:58 +00:00
|
|
|
match constants f_name with
|
|
|
|
| Error _ ->
|
2019-11-14 20:12:41 +01:00
|
|
|
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
2019-12-04 11:40:58 +00:00
|
|
|
return_statement @@ e_application ~loc (e_variable ~loc:f_loc (Var.of_name f_name)) arg
|
|
|
|
| Ok (s,_) ->
|
2019-11-14 20:12:41 +01:00
|
|
|
let%bind lst = bind_map_list simpl_expression args' in
|
|
|
|
return_statement @@ e_constant ~loc s lst
|
|
|
|
)
|
|
|
|
| f -> (
|
|
|
|
let%bind f' = simpl_expression f in
|
|
|
|
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
|
|
|
|
return_statement @@ e_application ~loc f' arg
|
2019-07-20 13:46:42 +02:00
|
|
|
)
|
2019-11-14 20:12:41 +01:00
|
|
|
)
|
2019-05-28 15:36:14 +00:00
|
|
|
| Skip reg -> (
|
|
|
|
let loc = Location.lift reg in
|
2019-09-10 12:42:49 +02:00
|
|
|
return_statement @@ e_skip ~loc ()
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| Loop (While l) ->
|
2019-12-04 18:30:52 +01:00
|
|
|
simpl_while_loop l.value
|
|
|
|
| Loop (For (ForInt fi)) -> (
|
2019-10-11 18:31:04 +02:00
|
|
|
let%bind loop = simpl_for_int fi.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok loop
|
|
|
|
)
|
2019-10-15 13:14:00 +02:00
|
|
|
| Loop (For (ForCollect fc)) ->
|
|
|
|
let%bind loop = simpl_for_collect fc.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok loop
|
2019-05-28 15:36:14 +00:00
|
|
|
| Cond c -> (
|
|
|
|
let (c , loc) = r_split c in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind expr = simpl_expression c.test in
|
|
|
|
let%bind match_true = match c.ifso with
|
2019-10-17 18:33:58 +02:00
|
|
|
ClauseInstr i ->
|
|
|
|
simpl_single_instruction i
|
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
|
|
|
simpl_block value
|
|
|
|
| ShortBlock {value; _} ->
|
|
|
|
simpl_statements @@ fst value.inside in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind match_false = match c.ifnot with
|
2019-10-17 18:33:58 +02:00
|
|
|
ClauseInstr i ->
|
|
|
|
simpl_single_instruction i
|
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
|
|
|
simpl_block value
|
|
|
|
| ShortBlock {value; _} ->
|
|
|
|
simpl_statements @@ fst value.inside in
|
2019-12-04 18:30:52 +01:00
|
|
|
let env = Var.fresh () in
|
|
|
|
|
|
|
|
let%bind match_true' = match_true None in
|
|
|
|
let%bind match_false' = match_false None in
|
|
|
|
let%bind match_true = match_true @@ Some (e_variable env) in
|
|
|
|
let%bind match_false = match_false @@ Some (e_variable env) in
|
|
|
|
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind ((_,free_vars_true), match_true) = repair_mutable_variable_in_matching match_true [] env in
|
|
|
|
let%bind ((_,free_vars_false), match_false) = repair_mutable_variable_in_matching match_false [] env in
|
2019-12-04 18:30:52 +01:00
|
|
|
let free_vars = free_vars_true @ free_vars_false in
|
|
|
|
if (List.length free_vars != 0) then
|
|
|
|
let match_expr = e_matching expr ~loc (Match_bool {match_true; match_false}) in
|
2020-02-19 14:18:06 +01:00
|
|
|
let return_expr = fun expr ->
|
|
|
|
e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
|
|
|
e_let_in (env,None) false false match_expr @@
|
|
|
|
expr
|
|
|
|
in
|
2019-12-04 18:30:52 +01:00
|
|
|
restore_mutable_variable return_expr free_vars env
|
|
|
|
else
|
|
|
|
return_statement @@ e_matching expr ~loc (Match_bool {match_true=match_true'; match_false=match_false'})
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| Assign a -> (
|
2019-05-28 15:36:14 +00:00
|
|
|
let (a , loc) = r_split a in
|
2019-10-07 09:24:56 -05:00
|
|
|
let%bind value_expr = simpl_expression a.rhs in
|
2019-05-12 20:56:22 +00:00
|
|
|
match a.lhs with
|
|
|
|
| Path path -> (
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name , path') = simpl_path path in
|
2019-12-04 18:30:52 +01:00
|
|
|
let (let_binder, mut, rhs, inline) = e_assign_with_let ~loc name path' value_expr in
|
|
|
|
return_let_in let_binder mut inline rhs
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| MapPath v -> (
|
|
|
|
let v' = v.value in
|
2019-10-08 16:41:47 +02:00
|
|
|
let%bind (varname,map,path) = match v'.path with
|
2019-12-04 11:40:58 +00:00
|
|
|
| Name name -> ok (name.value , e_variable (Var.of_name name.value), [])
|
2019-10-08 16:41:47 +02:00
|
|
|
| Path p ->
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name,p') = simpl_path v'.path in
|
2019-10-13 20:15:50 +02:00
|
|
|
let%bind accessor = simpl_projection p in
|
2019-10-08 18:20:32 +02:00
|
|
|
ok @@ (name , accessor , p')
|
2019-10-08 16:41:47 +02:00
|
|
|
in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind key_expr = simpl_expression v'.index.value.inside in
|
2019-10-08 16:41:47 +02:00
|
|
|
let expr' = e_map_add key_expr value_expr map in
|
2019-12-04 18:30:52 +01:00
|
|
|
let (let_binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr' in
|
|
|
|
return_let_in let_binder mut inline rhs
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
)
|
2019-05-22 00:46:54 +00:00
|
|
|
| CaseInstr c -> (
|
2019-05-28 15:36:14 +00:00
|
|
|
let (c , loc) = r_split c in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind expr = simpl_expression c.expr in
|
2019-12-04 18:30:52 +01:00
|
|
|
let env = Var.fresh () in
|
|
|
|
let%bind (fv,cases) =
|
|
|
|
let aux fv (x : Raw.if_clause Raw.case_clause Raw.reg) =
|
2019-10-24 09:58:33 +02:00
|
|
|
let%bind case_clause =
|
|
|
|
match x.value.rhs with
|
|
|
|
ClauseInstr i ->
|
|
|
|
simpl_single_instruction i
|
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
|
|
|
simpl_block value
|
|
|
|
| ShortBlock {value; _} ->
|
2019-10-24 10:29:41 +02:00
|
|
|
simpl_statements @@ fst value.inside in
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind case_clause'= case_clause @@ None in
|
|
|
|
let%bind case_clause = case_clause @@ Some(e_variable env) in
|
|
|
|
let%bind case_vars = get_case_variables x.value.pattern in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind ((_,free_vars), case_clause) = repair_mutable_variable_in_matching case_clause case_vars env in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok (free_vars::fv,(x.value.pattern, case_clause, case_clause')) in
|
|
|
|
bind_fold_map_list aux [] (npseq_to_list c.cases.value) in
|
|
|
|
let free_vars = List.concat fv in
|
|
|
|
if (List.length free_vars == 0) then (
|
|
|
|
let cases = List.map (fun case -> let (a,_,b) = case in (a,b)) cases in
|
|
|
|
let%bind m = simpl_cases cases in
|
|
|
|
return_statement @@ e_matching ~loc expr m
|
|
|
|
) else (
|
|
|
|
let cases = List.map (fun case -> let (a,b,_) = case in (a,b)) cases in
|
|
|
|
let%bind m = simpl_cases cases in
|
|
|
|
let match_expr = e_matching ~loc expr m in
|
2020-02-19 14:18:06 +01:00
|
|
|
let return_expr = fun expr ->
|
|
|
|
e_let_in (env,None) false false (store_mutable_variable free_vars) @@
|
|
|
|
e_let_in (env,None) false false match_expr @@
|
|
|
|
expr
|
|
|
|
in
|
2019-12-04 18:30:52 +01:00
|
|
|
restore_mutable_variable return_expr free_vars env
|
|
|
|
)
|
2019-05-22 00:46:54 +00:00
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
| RecordPatch r -> (
|
2019-12-04 18:30:52 +01:00
|
|
|
let reg = r.region in
|
|
|
|
let (r,loc) = r_split r in
|
|
|
|
let aux (fa :Raw.field_assign Raw.reg) : Raw.field_path_assign Raw.reg=
|
|
|
|
{value = {field_path = (fa.value.field_name, []); equal=fa.value.equal; field_expr = fa.value.field_expr};
|
|
|
|
region = fa.region}
|
|
|
|
in
|
|
|
|
let update : Raw.field_path_assign Raw.reg Raw.ne_injection Raw.reg = {
|
|
|
|
value = Raw.map_ne_injection aux r.record_inj.value;
|
|
|
|
region=r.record_inj.region
|
|
|
|
} in
|
|
|
|
let u : Raw.update = {record=r.path;kwd_with=r.kwd_with; updates=update} in
|
|
|
|
let%bind expr = simpl_update {value=u;region=reg} in
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name , access_path) = simpl_path r.path in
|
2019-12-04 18:30:52 +01:00
|
|
|
let loc = Some loc in
|
|
|
|
let (binder, mut, rhs, inline) = e_assign_with_let ?loc name access_path expr in
|
|
|
|
return_let_in binder mut inline rhs
|
2019-10-23 00:35:29 +02:00
|
|
|
|
|
|
|
)
|
2019-10-10 18:26:28 -07:00
|
|
|
| MapPatch patch -> (
|
|
|
|
let (map_p, loc) = r_split patch in
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name, access_path) = simpl_path map_p.path in
|
2019-10-11 15:44:16 -07:00
|
|
|
let%bind inj = bind_list
|
|
|
|
@@ List.map (fun (x:Raw.binding Region.reg) ->
|
|
|
|
let x = x.value in
|
2019-10-10 18:26:28 -07:00
|
|
|
let (key, value) = x.source, x.image in
|
|
|
|
let%bind key' = simpl_expression key in
|
|
|
|
let%bind value' = simpl_expression value
|
2019-10-11 15:44:16 -07:00
|
|
|
in ok @@ (key', value')
|
2019-10-10 18:26:28 -07:00
|
|
|
)
|
2019-10-23 00:35:29 +02:00
|
|
|
@@ npseq_to_list map_p.map_inj.value.ne_elements in
|
2019-12-04 18:30:52 +01:00
|
|
|
match inj with
|
|
|
|
| [] -> return_statement @@ e_skip ~loc ()
|
|
|
|
| _ :: _ ->
|
|
|
|
let assigns = List.fold_right
|
|
|
|
(fun (key, value) map -> (e_map_add key value map))
|
|
|
|
inj
|
|
|
|
(e_accessor_list ~loc (e_variable (Var.of_name name)) access_path)
|
|
|
|
in
|
|
|
|
let (binder, mut, rhs, inline) = e_assign_with_let ~loc name access_path assigns in
|
|
|
|
return_let_in binder mut inline rhs
|
2019-10-10 18:26:28 -07:00
|
|
|
)
|
2019-10-09 17:08:58 -07:00
|
|
|
| SetPatch patch -> (
|
2019-10-10 13:35:38 -07:00
|
|
|
let (setp, loc) = r_split patch in
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name , access_path) = simpl_path setp.path in
|
2019-10-11 15:10:08 -05:00
|
|
|
let%bind inj =
|
|
|
|
bind_list @@
|
|
|
|
List.map simpl_expression @@
|
2019-10-23 00:35:29 +02:00
|
|
|
npseq_to_list setp.set_inj.value.ne_elements in
|
2019-12-04 18:30:52 +01:00
|
|
|
match inj with
|
|
|
|
| [] -> return_statement @@ e_skip ~loc ()
|
|
|
|
| _ :: _ ->
|
|
|
|
let assigns = List.fold_right
|
|
|
|
(fun hd s -> e_constant C_SET_ADD [hd ; s])
|
|
|
|
inj (e_accessor_list ~loc (e_variable (Var.of_name name)) access_path) in
|
|
|
|
let (binder, mut, rhs, inline) = e_assign_with_let ~loc name access_path assigns in
|
|
|
|
return_let_in binder mut inline rhs
|
2019-10-09 17:08:58 -07:00
|
|
|
)
|
2019-05-28 15:36:14 +00:00
|
|
|
| MapRemove r -> (
|
|
|
|
let (v , loc) = r_split r in
|
2019-05-12 20:56:22 +00:00
|
|
|
let key = v.key in
|
2019-10-08 16:41:47 +02:00
|
|
|
let%bind (varname,map,path) = match v.map with
|
2019-12-04 11:40:58 +00:00
|
|
|
| Name v -> ok (v.value , e_variable (Var.of_name v.value) , [])
|
2019-10-08 16:41:47 +02:00
|
|
|
| Path p ->
|
2020-02-20 05:25:30 +00:00
|
|
|
let (name,p') = simpl_path v.map in
|
2019-10-13 20:15:50 +02:00
|
|
|
let%bind accessor = simpl_projection p in
|
2019-10-08 18:20:32 +02:00
|
|
|
ok @@ (name , accessor , p')
|
2019-10-08 16:41:47 +02:00
|
|
|
in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind key' = simpl_expression key in
|
2019-12-04 11:40:58 +00:00
|
|
|
let expr = e_constant ~loc C_MAP_REMOVE [key' ; map] in
|
2019-12-04 18:30:52 +01:00
|
|
|
let (binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr in
|
|
|
|
return_let_in binder mut inline rhs
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
2019-10-07 21:41:36 -07:00
|
|
|
| SetRemove r -> (
|
|
|
|
let (set_rm, loc) = r_split r in
|
2019-10-14 16:04:48 -07:00
|
|
|
let%bind (varname, set, path) = match set_rm.set with
|
2019-12-04 11:40:58 +00:00
|
|
|
| Name v -> ok (v.value, e_variable (Var.of_name v.value), [])
|
2019-10-14 16:04:48 -07:00
|
|
|
| Path path ->
|
2020-02-20 05:25:30 +00:00
|
|
|
let(name, p') = simpl_path set_rm.set in
|
2019-10-14 16:04:48 -07:00
|
|
|
let%bind accessor = simpl_projection path in
|
|
|
|
ok @@ (name, accessor, p')
|
|
|
|
in
|
2019-10-07 21:41:36 -07:00
|
|
|
let%bind removed' = simpl_expression set_rm.element in
|
2019-12-04 11:40:58 +00:00
|
|
|
let expr = e_constant ~loc C_SET_REMOVE [removed' ; set] in
|
2019-12-04 18:30:52 +01:00
|
|
|
let (binder, mut, rhs, inline) = e_assign_with_let ~loc varname path expr in
|
|
|
|
return_let_in binder mut inline rhs
|
2019-10-07 21:41:36 -07:00
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-02-20 05:25:30 +00:00
|
|
|
and simpl_path : Raw.path -> string * string list = fun p ->
|
2019-05-12 20:56:22 +00:00
|
|
|
match p with
|
2020-02-20 05:25:30 +00:00
|
|
|
| Raw.Name v -> (v.value , [])
|
2019-05-12 20:56:22 +00:00
|
|
|
| Raw.Path p -> (
|
|
|
|
let p' = p.value in
|
|
|
|
let var = p'.struct_name.value in
|
|
|
|
let path = p'.field_path in
|
2020-02-20 05:25:30 +00:00
|
|
|
let path' =
|
2019-05-12 20:56:22 +00:00
|
|
|
let aux (s:Raw.selection) =
|
|
|
|
match s with
|
2020-02-20 05:25:30 +00:00
|
|
|
| FieldName property -> property.value
|
|
|
|
| Component index -> (Z.to_string (snd index.value))
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
2020-02-20 05:25:30 +00:00
|
|
|
List.map aux @@ npseq_to_list path in
|
|
|
|
(var , path')
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
and simpl_cases : (Raw.pattern * expression) list -> matching_expr result = fun t ->
|
2019-05-12 20:56:22 +00:00
|
|
|
let open Raw in
|
2019-06-05 17:51:06 +02:00
|
|
|
let get_var (t:Raw.pattern) =
|
|
|
|
match t with
|
2019-05-12 20:56:22 +00:00
|
|
|
| PVar v -> ok v.value
|
2019-06-13 16:57:40 +02:00
|
|
|
| p -> fail @@ unsupported_non_var_pattern p in
|
|
|
|
let get_tuple (t: Raw.pattern) =
|
|
|
|
match t with
|
2019-05-12 20:56:22 +00:00
|
|
|
| PTuple v -> npseq_to_list v.value.inside
|
2019-06-13 16:57:40 +02:00
|
|
|
| x -> [ x ] in
|
|
|
|
let get_single (t: Raw.pattern) =
|
2019-05-12 20:56:22 +00:00
|
|
|
let t' = get_tuple t in
|
|
|
|
let%bind () =
|
2019-06-05 17:51:06 +02:00
|
|
|
trace_strong (unsupported_tuple_pattern t) @@
|
2019-05-12 20:56:22 +00:00
|
|
|
Assert.assert_list_size t' 1 in
|
|
|
|
ok (List.hd t') in
|
2019-09-21 11:30:41 +02:00
|
|
|
let get_toplevel (t : Raw.pattern) =
|
|
|
|
match t with
|
2019-11-06 17:23:49 +01:00
|
|
|
| PList PCons x -> (
|
2019-09-21 11:30:41 +02:00
|
|
|
let (x' , lst) = x.value in
|
|
|
|
match lst with
|
|
|
|
| [] -> ok x'
|
|
|
|
| _ -> ok t
|
|
|
|
)
|
2019-10-13 20:15:50 +02:00
|
|
|
| pattern -> ok pattern in
|
2019-06-13 16:57:40 +02:00
|
|
|
let get_constr (t: Raw.pattern) =
|
|
|
|
match t with
|
2019-11-06 17:23:49 +01:00
|
|
|
| PConstr (PConstrApp v) -> (
|
2020-01-03 13:01:13 +00:00
|
|
|
let value = v.value in
|
|
|
|
match value with
|
2020-01-09 17:26:07 +01:00
|
|
|
| constr, None ->
|
|
|
|
ok (constr.value, "unit")
|
|
|
|
| _ ->
|
2019-11-06 17:23:49 +01:00
|
|
|
let const, pat_opt = v.value in
|
2019-06-13 16:57:40 +02:00
|
|
|
let%bind pat =
|
|
|
|
trace_option (unsupported_cst_constr t) @@
|
|
|
|
pat_opt in
|
|
|
|
let%bind single_pat = get_single (PTuple pat) in
|
|
|
|
let%bind var = get_var single_pat in
|
|
|
|
ok (const.value , var)
|
|
|
|
)
|
|
|
|
| _ -> fail @@ only_constructors t in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind patterns =
|
|
|
|
let aux (x , y) =
|
2019-09-21 11:30:41 +02:00
|
|
|
let%bind x' = get_toplevel x in
|
|
|
|
ok (x' , y)
|
2019-06-13 16:57:40 +02:00
|
|
|
in bind_map_list aux t in
|
2019-05-12 20:56:22 +00:00
|
|
|
match patterns with
|
2019-11-06 17:23:49 +01:00
|
|
|
| [(PConstr PFalse _ , f) ; (PConstr PTrue _ , t)]
|
|
|
|
| [(PConstr PTrue _ , t) ; (PConstr PFalse _ , f)] ->
|
2019-06-05 17:51:06 +02:00
|
|
|
ok @@ Match_bool {match_true = t ; match_false = f}
|
2019-11-06 17:23:49 +01:00
|
|
|
| [(PConstr PSomeApp v , some) ; (PConstr PNone _ , none)]
|
|
|
|
| [(PConstr PNone _ , none) ; (PConstr PSomeApp v , some)] -> (
|
2019-05-12 20:56:22 +00:00
|
|
|
let (_, v) = v.value in
|
|
|
|
let%bind v = match v.value.inside with
|
|
|
|
| PVar v -> ok v.value
|
2019-06-05 17:51:06 +02:00
|
|
|
| p -> fail @@ unsupported_deep_Some_patterns p in
|
2019-12-04 11:40:58 +00:00
|
|
|
ok @@ Match_option {match_none = none ; match_some = (Var.of_name v, some, ()) }
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
2019-11-06 17:23:49 +01:00
|
|
|
| [(PList PCons c, cons) ; (PList (PNil _), nil)]
|
|
|
|
| [(PList (PNil _), nil) ; (PList PCons c, cons)] ->
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind (a, b) =
|
|
|
|
match c.value with
|
|
|
|
| a, [(_, b)] ->
|
|
|
|
let%bind a = get_var a in
|
|
|
|
let%bind b = get_var b in
|
|
|
|
ok (a, b)
|
2019-06-05 17:51:06 +02:00
|
|
|
| _ -> fail @@ unsupported_deep_list_patterns c
|
2019-12-04 11:40:58 +00:00
|
|
|
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
2019-12-04 11:40:58 +00:00
|
|
|
ok @@ Match_list {match_cons = (Var.of_name a, Var.of_name b, cons,()) ; match_nil = nil}
|
2019-05-12 20:56:22 +00:00
|
|
|
| lst ->
|
2019-06-05 17:51:06 +02:00
|
|
|
trace (simple_info "currently, only booleans, options, lists and \
|
|
|
|
user-defined constructors are supported in patterns") @@
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind constrs =
|
|
|
|
let aux (x , y) =
|
|
|
|
let error =
|
|
|
|
let title () = "Pattern" in
|
2020-01-21 18:35:36 +01:00
|
|
|
(* TODO: The labelled arguments should be flowing from the CLI. *)
|
2019-05-12 20:56:22 +00:00
|
|
|
let content () =
|
2019-10-09 16:07:13 +02:00
|
|
|
Printf.sprintf "Pattern : %s"
|
2020-01-14 01:27:35 +01:00
|
|
|
(ParserLog.pattern_to_string
|
Refactoring of comments (for [dune build @doc]).
Refactoring of parsing command-line arguments
* The type [options] is now abstract and implemented as an
object type to avoid struggling with scoping and type
inference when record types share some common field names.
Refactoring of ParserLog for PascaLIGO and CameLIGO
* The immediate motivation behind that refactoring was to
remove the use of a couple of global references. A
consequence is that we have a nicer and more compact code, by
threading a state. The files [pascaligo/Tests/pp.ligo] and
[ligodity/Tests/pp.mligo].
* Another consequence is that the choice of making strings from
AST nodes depends on the CLI (offsets? mode?). After this
refactoring, that choice is hardcoded in the simplifiers in a
few places (TODO), waiting for a general solution that would
have all CL options flow through the compiler.
* I removed the use of vendors [x_option.ml], [x_map.ml] and
[x_list.ml] when handling optional values. (Less dependencies
this way.)
Refactoring of the ASTs
* I removed the node [local_decl], which was set to [[]]
already in a previous commit (which removed local
declarations as being redundant, as statements could already
be instructions or declarations).
* I changed [StrLit] to [String] in the AST of CameLIGO and
ReasonLIGO.
* I also changed the type [fun_expr] so now either a block is
present, and therefore followed by the [with] keyword, or it
is not. (Before, the presence of a block was not enforced in
the type with the presence of the keyword.)
Notes
* [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO
are almost identical and differ in the same way (language
name and file extension), which suggests that they should be
in the [shared] folder and instanciated as a functor in the
future (TODO).
* I removed the blank characters at the end of many lines in
the parser of ReasonLIGO.
2019-12-13 12:21:52 +01:00
|
|
|
~offsets:true ~mode:`Point x) in
|
2019-05-12 20:56:22 +00:00
|
|
|
error title content in
|
|
|
|
let%bind x' =
|
|
|
|
trace error @@
|
|
|
|
get_constr x in
|
|
|
|
ok (x' , y) in
|
|
|
|
bind_map_list aux lst in
|
2019-12-04 11:40:58 +00:00
|
|
|
ok @@ ez_match_variant constrs
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-06-05 17:51:06 +02:00
|
|
|
and simpl_instruction : Raw.instruction -> (_ -> expression result) result =
|
2020-01-21 18:35:36 +01:00
|
|
|
fun t -> trace (simplifying_instruction t) @@ simpl_single_instruction t
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-06-05 17:51:06 +02:00
|
|
|
and simpl_statements : Raw.statements -> (_ -> expression result) result =
|
2020-01-21 18:35:36 +01:00
|
|
|
fun statements ->
|
|
|
|
let lst = npseq_to_list statements in
|
|
|
|
let%bind fs = simpl_statement_list lst in
|
|
|
|
let aux : _ -> (expression option -> expression result) -> _ =
|
|
|
|
fun prec cur ->
|
|
|
|
let%bind res = cur prec
|
|
|
|
in ok @@ Some res in
|
|
|
|
ok @@ fun (expr' : _ option) ->
|
|
|
|
let%bind ret = bind_fold_right_list aux expr' fs in
|
|
|
|
ok @@ Option.unopt_exn ret
|
|
|
|
|
|
|
|
and simpl_block : Raw.block -> (_ -> expression result) result =
|
|
|
|
fun t -> simpl_statements t.statements
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
and simpl_while_loop : Raw.while_loop -> (_ -> expression result) result = fun wl ->
|
|
|
|
let env_rec = Var.fresh () in
|
|
|
|
let binder = Var.fresh () in
|
|
|
|
|
|
|
|
let%bind cond = simpl_expression wl.cond in
|
|
|
|
let ctrl =
|
|
|
|
(e_variable binder)
|
2020-02-19 14:18:06 +01:00
|
|
|
in
|
|
|
|
|
|
|
|
let%bind for_body = simpl_block wl.block.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind for_body = for_body @@ Some( ctrl ) in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind ((_,captured_name_list),for_body) = repair_mutable_variable_in_loops for_body [] binder in
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
let aux name expr=
|
2020-02-19 14:18:06 +01:00
|
|
|
e_let_in (name,None) false false (e_accessor (e_accessor (e_variable binder) "0") (Var.to_name name)) expr
|
2019-12-04 18:30:52 +01:00
|
|
|
in
|
2020-02-19 14:18:06 +01:00
|
|
|
let init_rec = e_tuple [store_mutable_variable @@ captured_name_list] in
|
2019-12-04 18:30:52 +01:00
|
|
|
let restore = fun expr -> List.fold_right aux captured_name_list expr in
|
2020-03-06 23:44:28 +01:00
|
|
|
let continue_expr = e_constant C_FOLD_CONTINUE [for_body] in
|
|
|
|
let stop_expr = e_constant C_FOLD_STOP [e_variable binder] in
|
2020-02-19 14:18:06 +01:00
|
|
|
let aux_func =
|
|
|
|
e_lambda binder None None @@
|
|
|
|
restore @@
|
|
|
|
e_cond cond continue_expr stop_expr in
|
2019-12-04 18:30:52 +01:00
|
|
|
let loop = e_constant C_FOLD_WHILE [aux_func; e_variable env_rec] in
|
2020-02-19 14:18:06 +01:00
|
|
|
let return_expr = fun expr ->
|
|
|
|
e_let_in (env_rec,None) false false init_rec @@
|
|
|
|
e_let_in (env_rec,None) false false loop @@
|
|
|
|
e_let_in (env_rec,None) false false (e_accessor (e_variable env_rec) "0") @@
|
|
|
|
expr
|
|
|
|
in
|
2019-12-04 18:30:52 +01:00
|
|
|
restore_mutable_variable return_expr captured_name_list env_rec
|
|
|
|
|
|
|
|
|
2019-10-11 18:31:04 +02:00
|
|
|
and simpl_for_int : Raw.for_int -> (_ -> expression result) result = fun fi ->
|
2019-12-04 18:30:52 +01:00
|
|
|
let env_rec = Var.fresh () in
|
|
|
|
let binder = Var.fresh () in
|
|
|
|
let name = fi.assign.value.name.value in
|
|
|
|
let it = Var.of_name name in
|
|
|
|
let var = e_variable it in
|
|
|
|
(*Make the cond and the step *)
|
2019-10-11 18:31:04 +02:00
|
|
|
let%bind value = simpl_expression fi.assign.value.expr in
|
|
|
|
let%bind bound = simpl_expression fi.bound in
|
2019-12-04 18:30:52 +01:00
|
|
|
let cond = e_annotation (e_constant C_LE [var ; bound]) t_bool in
|
2019-10-22 12:12:19 +02:00
|
|
|
let step = e_int 1 in
|
2019-12-04 18:30:52 +01:00
|
|
|
let ctrl =
|
|
|
|
e_let_in (it,Some t_int) false false (e_constant C_ADD [ var ; step ])
|
2020-02-19 14:18:06 +01:00
|
|
|
(e_let_in (binder, None) false false (e_update (e_variable binder) "1" var)
|
2019-12-04 18:30:52 +01:00
|
|
|
(e_variable binder))
|
|
|
|
in
|
|
|
|
(* Modify the body loop*)
|
|
|
|
let%bind for_body = simpl_block fi.block.value in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind for_body = for_body @@ Some ctrl in
|
|
|
|
let%bind ((_,captured_name_list),for_body) = repair_mutable_variable_in_loops for_body [it] binder in
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
let aux name expr=
|
2020-02-19 14:18:06 +01:00
|
|
|
e_let_in (name,None) false false (e_accessor (e_accessor (e_variable binder) "0") (Var.to_name name)) expr
|
2019-12-04 18:30:52 +01:00
|
|
|
in
|
|
|
|
|
|
|
|
(* restores the initial value of the free_var*)
|
|
|
|
let restore = fun expr -> List.fold_right aux captured_name_list expr in
|
|
|
|
|
|
|
|
(*Prep the lambda for the fold*)
|
2020-03-06 23:44:28 +01:00
|
|
|
let continue_expr = e_constant C_FOLD_CONTINUE [restore(for_body)] in
|
|
|
|
let stop_expr = e_constant C_FOLD_STOP [e_variable binder] in
|
2020-02-19 14:18:06 +01:00
|
|
|
let aux_func = e_lambda binder None None @@
|
|
|
|
e_let_in (it,Some t_int) false false (e_accessor (e_variable binder) "1") @@
|
|
|
|
e_cond cond continue_expr (stop_expr) in
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
(* Make the fold_while en precharge the vakye *)
|
|
|
|
let loop = e_constant C_FOLD_WHILE [aux_func; e_variable env_rec] in
|
2020-02-19 14:18:06 +01:00
|
|
|
let init_rec = e_pair (store_mutable_variable @@ captured_name_list) var in
|
|
|
|
|
|
|
|
let return_expr = fun expr ->
|
|
|
|
e_let_in (it, Some t_int) false false value @@
|
|
|
|
e_let_in (env_rec,None) false false init_rec @@
|
|
|
|
e_let_in (env_rec,None) false false loop @@
|
|
|
|
e_let_in (env_rec,None) false false (e_accessor (e_variable env_rec) "0") @@
|
|
|
|
expr
|
|
|
|
in
|
2019-12-04 18:30:52 +01:00
|
|
|
restore_mutable_variable return_expr captured_name_list env_rec
|
|
|
|
|
2019-10-15 13:14:00 +02:00
|
|
|
and simpl_for_collect : Raw.for_collect -> (_ -> expression result) result = fun fc ->
|
2019-12-04 18:30:52 +01:00
|
|
|
let binder = Var.of_name "arguments" in
|
|
|
|
let%bind element_names = ok @@ match fc.bind_to with
|
2019-12-04 11:40:58 +00:00
|
|
|
| Some v -> [Var.of_name fc.var.value;Var.of_name (snd v).value]
|
|
|
|
| None -> [Var.of_name fc.var.value] in
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
let env = Var.fresh () in
|
2019-10-29 11:41:59 +01:00
|
|
|
let%bind for_body = simpl_block fc.block.value in
|
2019-12-04 18:30:52 +01:00
|
|
|
let%bind for_body = for_body @@ Some (e_accessor (e_variable binder) "0") in
|
2020-02-19 14:18:06 +01:00
|
|
|
let%bind ((_,free_vars), for_body) = repair_mutable_variable_in_loops for_body element_names binder in
|
2019-12-04 18:30:52 +01:00
|
|
|
|
|
|
|
let init_record = store_mutable_variable free_vars in
|
2019-10-26 14:18:06 +02:00
|
|
|
let%bind collect = simpl_expression fc.expr in
|
2019-12-04 18:30:52 +01:00
|
|
|
let aux name expr=
|
|
|
|
e_let_in (name,None) false false (e_accessor (e_accessor (e_variable binder) "0") (Var.to_name name)) expr
|
|
|
|
in
|
|
|
|
let restore = fun expr -> List.fold_right aux free_vars expr in
|
|
|
|
let restore = match fc.collection with
|
|
|
|
| Map _ -> (match fc.bind_to with
|
|
|
|
| Some v -> fun expr -> restore (e_let_in (Var.of_name fc.var.value, None) false false (e_accessor (e_accessor (e_variable binder) "1") "0")
|
|
|
|
(e_let_in (Var.of_name (snd v).value, None) false false (e_accessor (e_accessor (e_variable binder) "1") "1") expr))
|
|
|
|
| None -> fun expr -> restore (e_let_in (Var.of_name fc.var.value, None) false false (e_accessor (e_accessor (e_variable binder) "1") "0") expr)
|
|
|
|
)
|
|
|
|
| _ -> fun expr -> restore (e_let_in (Var.of_name fc.var.value, None) false false (e_accessor (e_variable binder) "1") expr)
|
|
|
|
in
|
|
|
|
let lambda = e_lambda binder None None (restore for_body) in
|
2019-10-26 14:27:29 +02:00
|
|
|
let op_name = match fc.collection with
|
2019-12-04 11:40:58 +00:00
|
|
|
| Map _ -> C_MAP_FOLD | Set _ -> C_SET_FOLD | List _ -> C_LIST_FOLD in
|
2020-02-19 14:18:06 +01:00
|
|
|
let fold = fun expr ->
|
|
|
|
e_let_in (env,None) false false (e_constant op_name [lambda; collect ; init_record]) @@
|
|
|
|
expr
|
|
|
|
in
|
2019-12-04 18:30:52 +01:00
|
|
|
restore_mutable_variable fold free_vars env
|
2019-10-26 14:18:06 +02:00
|
|
|
|
2020-01-21 18:35:36 +01:00
|
|
|
and simpl_declaration_list declarations :
|
2020-01-24 12:56:05 +01:00
|
|
|
Ast_simplified.declaration Location.wrap list result =
|
2020-01-21 18:35:36 +01:00
|
|
|
let open Raw in
|
|
|
|
let rec hook acc = function
|
|
|
|
[] -> acc
|
|
|
|
| [AttrDecl _] ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
acc
|
|
|
|
| AttrDecl _ :: (AttrDecl _ :: _ as declarations) ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
hook acc declarations
|
|
|
|
| AttrDecl decl :: ConstDecl {value; region} :: declarations ->
|
|
|
|
let new_const =
|
|
|
|
ConstDecl {value = {value with attributes = Some decl}; region}
|
|
|
|
in hook acc (new_const :: declarations)
|
|
|
|
| AttrDecl decl :: FunDecl {value; region} :: declarations ->
|
|
|
|
let new_fun =
|
|
|
|
FunDecl {value = {value with attributes = Some decl}; region}
|
|
|
|
in hook acc (new_fun :: declarations)
|
|
|
|
| AttrDecl _ :: declarations ->
|
|
|
|
(* Detached attributes are erased. TODO: Warning. *)
|
|
|
|
hook acc declarations
|
|
|
|
| TypeDecl decl :: declarations ->
|
|
|
|
let decl, loc = r_split decl in
|
|
|
|
let {name; type_expr} : Raw.type_decl = decl in
|
|
|
|
let%bind type_expression = simpl_type_expression type_expr in
|
|
|
|
let new_decl =
|
|
|
|
Declaration_type (Var.of_name name.value, type_expression) in
|
2020-01-21 19:04:51 +01:00
|
|
|
let res = Location.wrap ~loc new_decl in
|
|
|
|
hook (bind_list_cons res acc) declarations
|
2020-01-21 18:35:36 +01:00
|
|
|
| ConstDecl decl :: declarations ->
|
|
|
|
let simpl_const_decl =
|
|
|
|
fun {name;const_type; init; attributes} ->
|
|
|
|
let%bind expression = simpl_expression init in
|
|
|
|
let%bind t = simpl_type_expression const_type in
|
|
|
|
let type_annotation = Some t in
|
|
|
|
let inline =
|
|
|
|
match attributes with
|
|
|
|
None -> false
|
|
|
|
| Some {value; _} ->
|
|
|
|
npseq_to_list value.ne_elements
|
|
|
|
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
|
|
|
|
let new_decl =
|
|
|
|
Declaration_constant
|
|
|
|
(Var.of_name name.value, type_annotation, inline, expression)
|
|
|
|
in ok new_decl in
|
2020-01-21 19:04:51 +01:00
|
|
|
let%bind res =
|
2020-01-21 18:35:36 +01:00
|
|
|
bind_map_location simpl_const_decl (Location.lift_region decl)
|
2020-01-21 19:04:51 +01:00
|
|
|
in hook (bind_list_cons res acc) declarations
|
2020-01-21 18:35:36 +01:00
|
|
|
| FunDecl fun_decl :: declarations ->
|
|
|
|
let decl, loc = r_split fun_decl in
|
|
|
|
let%bind ((name, ty_opt), expr) = simpl_fun_decl ~loc decl in
|
|
|
|
let inline =
|
|
|
|
match fun_decl.value.attributes with
|
|
|
|
None -> false
|
|
|
|
| Some {value; _} ->
|
|
|
|
npseq_to_list value.ne_elements
|
|
|
|
|> List.exists (fun Region.{value; _} -> value = "\"inline\"") in
|
|
|
|
let new_decl =
|
|
|
|
Declaration_constant (name, ty_opt, inline, expr) in
|
2020-01-21 19:04:51 +01:00
|
|
|
let res = Location.wrap ~loc new_decl in
|
|
|
|
hook (bind_list_cons res acc) declarations
|
2020-01-24 12:56:05 +01:00
|
|
|
in hook (ok @@ []) (List.rev declarations)
|
2020-01-21 18:35:36 +01:00
|
|
|
|
|
|
|
let simpl_program : Raw.ast -> program result =
|
|
|
|
fun t -> simpl_declaration_list @@ nseq_to_list t.decl
|