2020-06-12 13:33:14 +02:00
|
|
|
open Errors_pascaligo
|
2019-12-10 12:00:21 -06:00
|
|
|
open Trace
|
2020-03-12 23:20:39 +01:00
|
|
|
open Ast_imperative
|
2019-05-12 20:56:22 +00:00
|
|
|
|
|
|
|
module Raw = Parser.Pascaligo.AST
|
|
|
|
module SMap = Map.String
|
2020-06-12 13:33:14 +02: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-03-16 14:53:56 +01:00
|
|
|
open Operators.Concrete_to_imperative.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
|
2020-03-12 23:20:39 +01:00
|
|
|
everything else. Because of this, abstracting sequences depend on
|
2020-01-09 17:26:07 +01:00
|
|
|
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
|
|
|
|
2020-03-23 16:00:50 +01:00
|
|
|
let return_let_in ?loc binder inline rhs = ok @@ fun expr'_opt ->
|
2019-05-22 00:46:54 +00:00
|
|
|
match expr'_opt with
|
2020-03-23 16:00:50 +01:00
|
|
|
| None -> ok @@ e_let_in ?loc binder inline rhs (e_skip ())
|
|
|
|
| Some expr' -> ok @@ e_let_in ?loc binder 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'
|
|
|
|
|
2020-04-16 22:48:34 +02:00
|
|
|
let get_t_string_singleton_opt = function
|
2020-05-25 15:15:27 +02:00
|
|
|
| Raw.TString s -> Some s.value
|
2020-04-16 22:48:34 +02:00
|
|
|
| _ -> None
|
|
|
|
|
2019-12-04 18:30:52 +01:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
let rec compile_type_expression (t:Raw.type_expr) : (type_expression , (abs_error)) result =
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
2020-03-16 14:53:56 +01:00
|
|
|
TPar x -> compile_type_expression x.value.inside
|
2019-11-06 17:23:49 +01:00
|
|
|
| TVar v -> (
|
2020-04-09 18:19:22 +02:00
|
|
|
let (v,loc) = r_split v in
|
|
|
|
match type_constants v with
|
2020-04-20 17:39:36 +02:00
|
|
|
| Some s -> ok @@ make_t ~loc @@ T_constant s
|
|
|
|
| None -> ok @@ make_t ~loc @@ T_variable (Var.of_name v)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| TFun x -> (
|
2020-04-09 18:19:22 +02:00
|
|
|
let (x,loc) = r_split x in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind (a , b) =
|
2020-04-09 18:19:22 +02:00
|
|
|
let (a , _ , b) = x in
|
2020-03-16 14:53:56 +01:00
|
|
|
bind_map_pair compile_type_expression (a , b) in
|
2020-04-09 18:19:22 +02:00
|
|
|
ok @@ make_t ~loc @@ T_arrow {type1=a;type2=b}
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| TApp x ->
|
2020-04-09 18:19:22 +02:00
|
|
|
let (x, loc) = r_split x in
|
|
|
|
let (name, tuple) = x in
|
2020-04-16 22:48:34 +02:00
|
|
|
(match name.value with
|
2020-05-03 10:40:11 +02:00
|
|
|
| "michelson_or" ->
|
2020-04-16 22:48:34 +02:00
|
|
|
let lst = npseq_to_list tuple.value.inside in
|
|
|
|
(match lst with
|
|
|
|
| [a ; b ; c ; d ] -> (
|
|
|
|
let%bind b' =
|
2020-06-12 13:33:14 +02:00
|
|
|
trace_option (michelson_type_wrong t name.value) @@
|
2020-04-16 22:48:34 +02:00
|
|
|
get_t_string_singleton_opt b in
|
|
|
|
let%bind d' =
|
2020-06-12 13:33:14 +02:00
|
|
|
trace_option (michelson_type_wrong t name.value) @@
|
2020-04-16 22:48:34 +02:00
|
|
|
get_t_string_singleton_opt d in
|
|
|
|
let%bind a' = compile_type_expression a in
|
|
|
|
let%bind c' = compile_type_expression c in
|
|
|
|
ok @@ t_michelson_or ~loc a' b' c' d'
|
|
|
|
)
|
2020-06-12 13:33:14 +02:00
|
|
|
| _ -> fail @@ michelson_type_wrong_arity loc name.value)
|
2020-04-18 00:02:33 +02:00
|
|
|
| "michelson_pair" ->
|
|
|
|
let lst = npseq_to_list tuple.value.inside in
|
|
|
|
(match lst with
|
|
|
|
| [a ; b ; c ; d ] -> (
|
|
|
|
let%bind b' =
|
2020-06-12 13:33:14 +02:00
|
|
|
trace_option (michelson_type_wrong t name.value) @@
|
2020-04-18 00:02:33 +02:00
|
|
|
get_t_string_singleton_opt b in
|
|
|
|
let%bind d' =
|
2020-06-12 13:33:14 +02:00
|
|
|
trace_option (michelson_type_wrong t name.value) @@
|
2020-04-18 00:02:33 +02:00
|
|
|
get_t_string_singleton_opt d in
|
|
|
|
let%bind a' = compile_type_expression a in
|
|
|
|
let%bind c' = compile_type_expression c in
|
|
|
|
ok @@ t_michelson_pair ~loc a' b' c' d'
|
|
|
|
)
|
2020-06-12 13:33:14 +02:00
|
|
|
| _ -> fail @@ michelson_type_wrong_arity loc name.value)
|
2020-04-16 22:48:34 +02:00
|
|
|
| _ ->
|
|
|
|
let lst = npseq_to_list tuple.value.inside in
|
|
|
|
let%bind lst =
|
|
|
|
bind_list @@ List.map compile_type_expression lst in (** TODO: fix constant and operator*)
|
|
|
|
let%bind cst =
|
2020-04-20 17:39:36 +02:00
|
|
|
trace_option (unknown_predefined_type name) @@
|
2020-04-16 22:48:34 +02:00
|
|
|
type_operators name.value in
|
2020-06-12 13:33:14 +02:00
|
|
|
ok @@ t_operator ~loc cst lst )
|
2019-05-12 20:56:22 +00:00
|
|
|
| TProd p ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind tpl = compile_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 ->
|
2020-04-09 18:19:22 +02:00
|
|
|
let (r,loc ) = r_split r in
|
2019-09-10 12:42:49 +02:00
|
|
|
let aux = fun (x, y) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind y = compile_type_expression y in
|
2019-09-10 12:42:49 +02:00
|
|
|
ok (x, y)
|
|
|
|
in
|
2020-04-22 19:44:21 +02:00
|
|
|
let order = fun i (x,y) ->
|
|
|
|
((x,i),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
|
2020-04-22 19:44:21 +02:00
|
|
|
@@ List.mapi order
|
2019-06-04 16:12:17 +02:00
|
|
|
@@ List.map apply
|
2020-04-09 18:19:22 +02:00
|
|
|
@@ npseq_to_list r.ne_elements in
|
2020-04-28 16:58:47 +02:00
|
|
|
let m = List.fold_left (fun m ((x,i), y) -> LMap.add (Label x) {field_type=y;field_decl_pos=i} m) LMap.empty lst in
|
2020-04-09 18:19:22 +02:00
|
|
|
ok @@ make_t ~loc @@ T_record m
|
2019-05-12 20:56:22 +00:00
|
|
|
| TSum s ->
|
2020-04-09 18:19:22 +02:00
|
|
|
let (s,loc) = r_split s in
|
2020-04-29 23:17:29 +02:00
|
|
|
let aux i (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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind te = compile_list_type_expression @@ args in
|
2020-04-29 23:17:29 +02:00
|
|
|
ok ((v.value.constr.value,i), te)
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
|
|
|
let%bind lst = bind_list
|
2020-04-29 23:17:29 +02:00
|
|
|
@@ List.mapi aux
|
2020-04-09 18:19:22 +02:00
|
|
|
@@ npseq_to_list s in
|
2020-04-29 23:17:29 +02:00
|
|
|
let m = List.fold_left (fun m ((x,i), y) -> CMap.add (Constructor x) {ctor_type=y;ctor_decl_pos=i} m) CMap.empty lst in
|
2020-04-09 18:19:22 +02:00
|
|
|
ok @@ make_t ~loc @@ T_sum m
|
2020-06-12 13:33:14 +02:00
|
|
|
| TString _s -> fail @@ unsupported_string_singleton t
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_list_type_expression (lst:Raw.type_expr list) : (type_expression , (abs_error)) result =
|
2019-05-12 20:56:22 +00:00
|
|
|
match lst with
|
2020-04-09 18:19:22 +02:00
|
|
|
| [] -> ok @@ t_unit ()
|
2020-03-16 14:53:56 +01:00
|
|
|
| [hd] -> compile_type_expression hd
|
2019-05-12 20:56:22 +00:00
|
|
|
| lst ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind lst = bind_list @@ List.map compile_type_expression lst in
|
2019-12-04 18:30:52 +01:00
|
|
|
ok @@ t_tuple lst
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-03-16 14:53:56 +01:00
|
|
|
let compile_projection : Raw.projection Region.reg -> _ = fun p ->
|
2019-09-10 12:42:49 +02:00
|
|
|
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-06-05 17:45:11 +02:00
|
|
|
| FieldName property -> Access_record property.value
|
|
|
|
| Component index -> (Access_tuple (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
|
2020-06-05 17:45:11 +02:00
|
|
|
ok @@ e_accessor ~loc var path'
|
2019-09-10 12:42:49 +02:00
|
|
|
|
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
let rec compile_expression (t:Raw.expr) : (expr , (abs_error)) result =
|
2019-05-23 06:22:58 +00:00
|
|
|
let return x = ok x in
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
|
|
|
| EAnnot a -> (
|
2020-06-08 12:40:14 +02:00
|
|
|
let par, loc = r_split a in
|
|
|
|
let expr, _, type_expr = par.inside in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr' = compile_expression expr in
|
|
|
|
let%bind type_expr' = compile_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 -> (
|
2020-06-08 12:40:14 +02:00
|
|
|
let (c', loc) = r_split c in
|
2019-12-04 11:40:58 +00:00
|
|
|
match constants c' with
|
2020-04-20 17:39:36 +02:00
|
|
|
| None -> return @@ e_variable ~loc (Var.of_name c.value)
|
|
|
|
| Some s -> return @@ e_constant ~loc s []
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
| ECall x -> (
|
2020-06-08 12:40:14 +02:00
|
|
|
let ((f, args), loc) = r_split x in
|
|
|
|
let (args, args_loc) = r_split args in
|
2019-05-28 15:36:14 +00:00
|
|
|
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
|
2020-04-20 17:39:36 +02:00
|
|
|
| None ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind arg = compile_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
|
2020-04-20 17:39:36 +02:00
|
|
|
| Some s ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind lst = bind_map_list compile_expression args' in
|
2019-11-14 20:12:41 +01:00
|
|
|
return @@ e_constant ~loc s lst
|
|
|
|
)
|
|
|
|
| f -> (
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind f' = compile_expression f in
|
|
|
|
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
2019-11-14 20:12:41 +01:00
|
|
|
return @@ e_application ~loc f' arg
|
|
|
|
)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
2020-03-16 14:53:56 +01:00
|
|
|
| EPar x -> compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_tuple_expression ~loc @@ npseq_to_list tpl'.inside
|
2019-05-12 20:56:22 +00:00
|
|
|
| ERecord r ->
|
|
|
|
let%bind fields = bind_list
|
2020-03-16 14:53:56 +01:00
|
|
|
@@ List.map (fun ((k : _ Raw.reg), v) -> let%bind v = compile_expression v in ok (k.value, v))
|
2020-06-10 16:58:59 +02:00
|
|
|
@@ List.map (fun (x:Raw.field_assignment 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)
|
2020-03-16 14:53:56 +01:00
|
|
|
| EProj p -> compile_projection p
|
|
|
|
| EUpdate u -> compile_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 =
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_tuple_expression ~loc:args_loc
|
2019-06-11 17:10:27 +02:00
|
|
|
@@ 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 =
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_tuple_expression ~loc:args_loc
|
2019-05-28 15:36:14 +00:00
|
|
|
@@ 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) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "ADD" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Sub c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "SUB" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Mult c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "TIMES" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Div c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "DIV" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| EArith (Mod c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "MOD" c
|
2019-05-28 15:36:14 +00:00
|
|
|
| EArith (Int n) -> (
|
|
|
|
let (n , loc) = r_split n in
|
2020-04-27 16:15:26 +02:00
|
|
|
let n = snd n in
|
2019-05-28 15:36:14 +00:00
|
|
|
return @@ e_literal ~loc (Literal_int n)
|
|
|
|
)
|
|
|
|
| EArith (Nat n) -> (
|
|
|
|
let (n , loc) = r_split n in
|
2020-04-27 16:15:26 +02:00
|
|
|
let n = snd @@ n in
|
2019-05-28 15:36:14 +00:00
|
|
|
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
|
2020-04-27 16:15:26 +02:00
|
|
|
let n = 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
|
|
|
)
|
2020-03-16 14:53:56 +01:00
|
|
|
| EArith (Neg e) -> compile_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
|
2020-04-27 11:31:16 +02:00
|
|
|
return @@ e_literal ~loc (Literal_string (Standard s))
|
|
|
|
| EString (Verbatim v) ->
|
|
|
|
let (v , loc) = r_split v in
|
|
|
|
return @@ e_literal ~loc (Literal_string (Verbatim v))
|
2019-10-07 17:16:03 +02:00
|
|
|
| EString (Cat bo) ->
|
|
|
|
let (bo , loc) = r_split bo in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind sl = compile_expression bo.arg1 in
|
|
|
|
let%bind sr = compile_expression bo.arg2 in
|
2019-10-07 17:16:03 +02:00
|
|
|
return @@ e_string_cat ~loc sl sr
|
2020-03-16 14:53:56 +01:00
|
|
|
| ELogic l -> compile_logic_expression l
|
|
|
|
| EList l -> compile_list_expression l
|
|
|
|
| ESet s -> compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr = compile_expression c.test in
|
|
|
|
let%bind match_true = compile_expression c.ifso in
|
|
|
|
let%bind match_false = compile_expression c.ifnot in
|
2020-04-23 17:53:10 +02:00
|
|
|
return @@ e_cond ~loc expr match_true match_false
|
2019-12-04 18:30:52 +01:00
|
|
|
|
2019-05-28 15:36:14 +00:00
|
|
|
| ECase c -> (
|
|
|
|
let (c , loc) = r_split c in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind e = compile_expression c.expr in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind lst =
|
|
|
|
let aux (x : Raw.expr Raw.case_clause) =
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr = compile_expression x.rhs in
|
2019-05-12 20:56:22 +00:00
|
|
|
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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind cases = compile_cases lst in
|
2020-03-27 14:57:56 +01:00
|
|
|
return @@ e_matching ~loc e cases
|
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
|
2020-06-12 13:33:14 +02:00
|
|
|
let aux : Raw.binding -> (expression * expression, (abs_error)) result =
|
2019-06-04 16:12:17 +02:00
|
|
|
fun b ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind src = compile_expression b.source in
|
|
|
|
let%bind dst = compile_expression b.image in
|
2019-06-04 16:12:17 +02:00
|
|
|
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
|
2020-06-12 13:33:14 +02:00
|
|
|
let aux : Raw.binding -> (expression * expression, (abs_error)) result =
|
2019-10-21 13:04:28 +02:00
|
|
|
fun b ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind src = compile_expression b.source in
|
|
|
|
let%bind dst = compile_expression b.image in
|
2019-10-21 13:04:28 +02:00
|
|
|
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
|
|
|
)
|
2020-03-16 14:53:56 +01:00
|
|
|
| Path p -> compile_projection p
|
2019-05-12 20:56:22 +00:00
|
|
|
in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind index = compile_expression lu.index.value.inside in
|
2020-06-05 17:45:11 +02:00
|
|
|
return @@ e_accessor ~loc path [Access_map index]
|
2019-05-28 15:36:14 +00:00
|
|
|
)
|
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-03-16 14:53:56 +01:00
|
|
|
let%bind (_ty_opt, f') = compile_fun_expression ~loc f
|
2020-01-09 17:26:07 +01:00
|
|
|
in return @@ f'
|
2020-04-15 17:15:55 +02:00
|
|
|
| ECodeInsert ci ->
|
|
|
|
let (ci, loc) = r_split ci in
|
|
|
|
let language = ci.language.value in
|
2020-04-17 13:36:33 +02:00
|
|
|
let%bind code = compile_expression ci.code in
|
|
|
|
return @@ e_raw_code ~loc language code
|
2020-04-15 17:15:55 +02:00
|
|
|
|
2020-06-10 16:58:59 +02:00
|
|
|
and compile_update (u: Raw.update Region.reg) =
|
|
|
|
let u, loc = r_split u in
|
|
|
|
let name, path = compile_path u.record in
|
|
|
|
let var = e_variable (Var.of_name name) in
|
|
|
|
let record = if path = [] then var else e_accessor var path in
|
|
|
|
let updates = u.updates.value.ne_elements in
|
2020-01-09 18:23:37 +01:00
|
|
|
let%bind updates' =
|
2020-06-10 16:58:59 +02:00
|
|
|
let aux (f: Raw.field_path_assignment Raw.reg) =
|
|
|
|
let f, _ = r_split f in
|
|
|
|
let%bind expr = compile_expression f.field_expr
|
|
|
|
in ok (compile_path f.field_path, expr)
|
|
|
|
in bind_map_list aux @@ npseq_to_list updates in
|
|
|
|
let aux ur ((var, path), expr) =
|
|
|
|
ok @@ e_update ~loc ur (Access_record var :: path) expr
|
2020-06-08 16:05:23 +02:00
|
|
|
in bind_fold_list aux record updates'
|
2020-01-09 18:23:37 +01:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_logic_expression (t:Raw.logic_expr) : (expression , (abs_error)) result =
|
2019-05-12 20:56:22 +00:00
|
|
|
match t with
|
2020-06-10 16:58:59 +02:00
|
|
|
| BoolExpr (False reg) ->
|
|
|
|
ok @@ e_bool ~loc:(Location.lift reg) false
|
|
|
|
| BoolExpr (True reg) ->
|
|
|
|
ok @@ e_bool ~loc:(Location.lift reg) true
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (Or b) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "OR" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (And b) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "AND" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| BoolExpr (Not b) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_unop "NOT" b
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Lt c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "LT" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Gt c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "GT" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Leq c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "LE" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Geq c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "GE" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Equal c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "EQ" c
|
2019-05-12 20:56:22 +00:00
|
|
|
| CompExpr (Neq c) ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_binop "NEQ" c
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_list_expression (t:Raw.list_expr) : (expression , (abs_error)) result =
|
2019-05-23 06:22:58 +00:00
|
|
|
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 ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_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' =
|
2020-03-16 14:53:56 +01:00
|
|
|
bind_map_list compile_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
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_set_expression (t:Raw.set_expr) : (expression , (abs_error)) result =
|
2019-07-19 14:35:47 +02:00
|
|
|
match t with
|
|
|
|
| SetMem x -> (
|
|
|
|
let (x' , loc) = r_split x in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind set' = compile_expression x'.set in
|
|
|
|
let%bind element' = compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind elements' = bind_map_list compile_expression elements in
|
2019-07-19 14:35:47 +02:00
|
|
|
ok @@ e_set ~loc elements'
|
|
|
|
)
|
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_binop (name:string) (t:_ Raw.bin_op Region.reg) : (expression , (abs_error)) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind a = compile_expression t.arg1 in
|
|
|
|
let%bind b = compile_expression t.arg2 in
|
2020-04-20 17:39:36 +02:00
|
|
|
let%bind name = trace_option (unknown_built_in 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
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_unop (name:string) (t:_ Raw.un_op Region.reg) : (expression , (abs_error)) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind a = compile_expression t.arg in
|
2020-04-20 17:39:36 +02:00
|
|
|
let%bind name = trace_option (unknown_built_in 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
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_tuple_expression ?loc (lst:Raw.expr list) : (expression , (abs_error)) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
| [hd] -> compile_expression hd
|
2019-06-04 16:12:17 +02:00
|
|
|
| lst ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind lst = bind_list @@ List.map compile_expression lst
|
2020-01-21 18:35:36 +01:00
|
|
|
in return @@ e_tuple ?loc lst
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-03-16 14:53:56 +01:00
|
|
|
and compile_data_declaration : Raw.data_decl -> _ result =
|
2020-01-21 18:35:36 +01:00
|
|
|
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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind t = compile_type_expression x.var_type in
|
|
|
|
let%bind expression = compile_expression x.init in
|
2020-03-23 16:00:50 +01:00
|
|
|
return_let_in ~loc (Var.of_name name, Some t) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind t = compile_type_expression x.const_type in
|
|
|
|
let%bind expression = compile_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\"")
|
2020-03-23 16:00:50 +01:00
|
|
|
in return_let_in ~loc (Var.of_name name, Some t) inline expression
|
2019-11-18 16:10:48 +01:00
|
|
|
| LocalFun f ->
|
|
|
|
let (f , loc) = r_split f in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind (binder, expr) = compile_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\"")
|
2020-03-23 16:00:50 +01:00
|
|
|
in return_let_in ~loc binder inline expr
|
2020-01-21 18:35:36 +01:00
|
|
|
|
2020-03-16 14:53:56 +01:00
|
|
|
and compile_param :
|
2020-06-12 13:33:14 +02:00
|
|
|
Raw.param_decl -> (string * type_expression, (abs_error)) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind type_expression = compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind type_expression = compile_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-03-16 14:53:56 +01:00
|
|
|
and compile_fun_decl :
|
2020-01-21 18:35:36 +01:00
|
|
|
loc:_ -> Raw.fun_decl ->
|
2020-06-12 13:33:14 +02:00
|
|
|
((expression_variable * type_expression option) * expression , (abs_error)) 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-03-07 01:19:22 +01:00
|
|
|
let {kwd_recursive;fun_name; param; ret_type; block_with;
|
2020-01-21 18:35:36 +01:00
|
|
|
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, [] -> (
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind input = compile_param a in
|
2019-05-23 06:22:58 +00:00
|
|
|
let (binder , input_type) = input in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind instructions = compile_statement_list statements in
|
|
|
|
let%bind result = compile_expression return in
|
|
|
|
let%bind output_type = compile_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
|
2020-03-07 01:19:22 +01:00
|
|
|
let binder = Var.of_name binder in
|
|
|
|
let fun_name = Var.of_name fun_name.value in
|
|
|
|
let fun_type = t_function input_type output_type in
|
2020-05-03 10:40:11 +02:00
|
|
|
let expression : expression =
|
2020-03-07 01:19:22 +01:00
|
|
|
e_lambda ~loc binder (Some input_type)(Some output_type) result in
|
|
|
|
let%bind expression = match kwd_recursive with
|
|
|
|
None -> ok @@ expression |
|
2020-05-03 10:40:11 +02:00
|
|
|
Some _ -> ok @@ e_recursive ~loc fun_name fun_type
|
2020-03-07 01:19:22 +01:00
|
|
|
@@ {binder;input_type=Some input_type; output_type= Some output_type; result}
|
|
|
|
in
|
|
|
|
ok ((fun_name, Some fun_type), 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind params = bind_map_list compile_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 =
|
2020-06-05 17:45:11 +02:00
|
|
|
e_accessor (e_variable arguments_name) [Access_record (string_of_int i)] in
|
2019-12-04 18:30:52 +01:00
|
|
|
let type_variable = Some type_expr in
|
2020-03-23 16:00:50 +01:00
|
|
|
let ass = return_let_in (Var.of_name param , type_variable) 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-03-16 14:53:56 +01:00
|
|
|
let%bind instructions = compile_statement_list statements in
|
|
|
|
let%bind result = compile_expression return in
|
|
|
|
let%bind output_type = compile_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
|
2020-03-07 01:19:22 +01:00
|
|
|
let fun_name = Var.of_name fun_name.value in
|
|
|
|
let fun_type = t_function input_type output_type in
|
2020-05-03 10:40:11 +02:00
|
|
|
let expression : expression =
|
2020-03-07 01:19:22 +01:00
|
|
|
e_lambda ~loc binder (Some input_type)(Some output_type) result in
|
|
|
|
let%bind expression = match kwd_recursive with
|
|
|
|
None -> ok @@ expression |
|
2020-05-03 10:40:11 +02:00
|
|
|
Some _ -> ok @@ e_recursive ~loc fun_name fun_type
|
2020-03-07 01:19:22 +01:00
|
|
|
@@ {binder;input_type=Some input_type; output_type= Some output_type; result}
|
|
|
|
in
|
|
|
|
ok ((fun_name, Some fun_type), expression)
|
2019-05-12 20:56:22 +00:00
|
|
|
)
|
|
|
|
)
|
2020-01-09 17:26:07 +01:00
|
|
|
|
2020-03-16 14:53:56 +01:00
|
|
|
and compile_fun_expression :
|
2020-06-12 13:33:14 +02:00
|
|
|
loc:_ -> Raw.fun_expr -> (type_expression option * expression , (abs_error)) result =
|
2020-01-09 17:26:07 +01:00
|
|
|
fun ~loc x ->
|
|
|
|
let open! Raw in
|
2020-06-08 12:40:14 +02:00
|
|
|
let {param; ret_type; return; _} : fun_expr = x in
|
2020-01-09 17:26:07 +01:00
|
|
|
let statements = [] in
|
|
|
|
(match param.value.inside with
|
2020-03-07 01:19:22 +01:00
|
|
|
a, [] -> (
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind input = compile_param a in
|
2020-03-11 17:04:49 +01:00
|
|
|
let (binder , input_type) = input in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind instructions = compile_statement_list statements in
|
|
|
|
let%bind result = compile_expression return in
|
|
|
|
let%bind output_type = compile_type_expression ret_type in
|
2020-03-12 23:20:39 +01:00
|
|
|
|
2020-03-11 17:04:49 +01:00
|
|
|
let body = instructions in
|
|
|
|
let%bind result =
|
|
|
|
let aux prec cur = cur (Some prec) in
|
|
|
|
bind_fold_right_list aux result body in
|
|
|
|
let binder = Var.of_name binder in
|
|
|
|
let fun_type = t_function input_type output_type in
|
2020-06-08 12:40:14 +02:00
|
|
|
let expression =
|
|
|
|
e_lambda ~loc binder (Some input_type)(Some output_type) result
|
2020-03-11 17:04:49 +01:00
|
|
|
in
|
|
|
|
ok (Some fun_type , 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind params = bind_map_list compile_param lst in
|
2020-01-09 17:26:07 +01:00
|
|
|
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) ->
|
2020-06-05 17:45:11 +02:00
|
|
|
let expr = e_accessor (e_variable arguments_name) [Access_tuple (Z.of_int i)] in
|
2019-12-04 18:30:52 +01:00
|
|
|
let type_variable = Some param_type in
|
2020-03-23 16:00:50 +01:00
|
|
|
let ass = return_let_in (Var.of_name param , type_variable) false expr in
|
2020-01-09 17:26:07 +01:00
|
|
|
ass
|
|
|
|
in
|
|
|
|
bind_list @@ List.mapi aux params in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind instructions = compile_statement_list statements in
|
|
|
|
let%bind result = compile_expression return in
|
|
|
|
let%bind output_type = compile_type_expression ret_type in
|
2020-01-09 17:26:07 +01:00
|
|
|
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
|
2020-03-07 01:19:22 +01:00
|
|
|
let fun_type = t_function input_type output_type in
|
2020-06-08 12:40:14 +02:00
|
|
|
let expression =
|
|
|
|
e_lambda ~loc binder (Some input_type)(Some output_type) result
|
2020-03-07 01:19:22 +01:00
|
|
|
in
|
|
|
|
ok (Some fun_type , expression)
|
2020-01-09 17:26:07 +01:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2020-03-16 14:53:56 +01:00
|
|
|
and compile_statement_list statements =
|
2020-01-21 18:35:36 +01:00
|
|
|
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 ->
|
2020-03-16 14:53:56 +01:00
|
|
|
hook (compile_instruction i :: acc) statements
|
2020-01-21 18:35:36 +01:00
|
|
|
| Data d :: statements ->
|
2020-03-16 14:53:56 +01:00
|
|
|
hook (compile_data_declaration d :: acc) statements
|
2020-01-21 18:35:36 +01:00
|
|
|
in bind_list @@ hook [] (List.rev statements)
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_single_instruction : Raw.instruction -> ((_ -> (expression , (abs_error)) result), (abs_error)) 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
|
2020-04-20 17:39:36 +02:00
|
|
|
| None ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind arg = compile_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
|
2020-04-20 17:39:36 +02:00
|
|
|
| Some s ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind lst = bind_map_list compile_expression args' in
|
2019-11-14 20:12:41 +01:00
|
|
|
return_statement @@ e_constant ~loc s lst
|
|
|
|
)
|
|
|
|
| f -> (
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind f' = compile_expression f in
|
|
|
|
let%bind arg = compile_tuple_expression ~loc:args_loc args' in
|
2019-11-14 20:12:41 +01:00
|
|
|
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) ->
|
2020-03-27 14:57:56 +01:00
|
|
|
let (wl, loc) = r_split l in
|
|
|
|
let%bind condition = compile_expression wl.cond in
|
|
|
|
let%bind body = compile_block wl.block.value in
|
|
|
|
let%bind body = body @@ None in
|
|
|
|
return_statement @@ e_while ~loc condition body
|
2019-12-04 18:30:52 +01:00
|
|
|
| Loop (For (ForInt fi)) -> (
|
2020-03-27 14:57:56 +01:00
|
|
|
let (fi,loc) = r_split fi in
|
|
|
|
let binder = Var.of_name fi.assign.value.name.value in
|
|
|
|
let%bind start = compile_expression fi.assign.value.expr in
|
|
|
|
let%bind bound = compile_expression fi.bound in
|
2020-04-09 19:17:51 +02:00
|
|
|
let%bind step = match fi.step with
|
2020-04-27 16:15:26 +02:00
|
|
|
| None -> ok @@ e_int_z Z.one
|
2020-06-08 12:40:14 +02:00
|
|
|
| Some (_, step) -> compile_expression step in
|
2020-03-27 14:57:56 +01:00
|
|
|
let%bind body = compile_block fi.block.value in
|
|
|
|
let%bind body = body @@ None in
|
2020-04-09 19:17:51 +02:00
|
|
|
return_statement @@ e_for ~loc binder start bound step body
|
2019-12-04 18:30:52 +01:00
|
|
|
)
|
2019-10-15 13:14:00 +02:00
|
|
|
| Loop (For (ForCollect fc)) ->
|
2020-03-27 14:57:56 +01:00
|
|
|
let (fc,loc) = r_split fc in
|
|
|
|
let binder = (Var.of_name fc.var.value, Option.map (fun x -> Var.of_name (snd x:string Raw.reg).value) fc.bind_to) in
|
|
|
|
let%bind collection = compile_expression fc.expr in
|
|
|
|
let collection_type = match fc.collection with
|
|
|
|
| Map _ -> Map
|
|
|
|
| Set _ -> Set
|
|
|
|
| List _ -> List
|
|
|
|
in
|
|
|
|
let%bind body = compile_block fc.block.value in
|
|
|
|
let%bind body = body @@ None in
|
|
|
|
return_statement @@ e_for_each ~loc binder collection collection_type body
|
2019-05-28 15:36:14 +00:00
|
|
|
| Cond c -> (
|
|
|
|
let (c , loc) = r_split c in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr = compile_expression c.test in
|
2019-05-12 20:56:22 +00:00
|
|
|
let%bind match_true = match c.ifso with
|
2019-10-17 18:33:58 +02:00
|
|
|
ClauseInstr i ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_single_instruction i
|
2019-10-17 18:33:58 +02:00
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_block value
|
2019-10-17 18:33:58 +02:00
|
|
|
| ShortBlock {value; _} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_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 ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_single_instruction i
|
2019-10-17 18:33:58 +02:00
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_block value
|
2019-10-17 18:33:58 +02:00
|
|
|
| ShortBlock {value; _} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_statements @@ fst value.inside in
|
2020-05-03 10:40:11 +02:00
|
|
|
|
2020-03-27 14:57:56 +01:00
|
|
|
let%bind match_true = match_true None in
|
|
|
|
let%bind match_false = match_false None in
|
2020-04-23 17:53:10 +02:00
|
|
|
return_statement @@ e_cond ~loc expr match_true 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind value_expr = compile_expression a.rhs in
|
2019-05-12 20:56:22 +00:00
|
|
|
match a.lhs with
|
2020-06-10 16:58:59 +02:00
|
|
|
| Path path ->
|
|
|
|
let name , path' = compile_path path in
|
2020-06-05 17:45:11 +02:00
|
|
|
let name = Var.of_name name in
|
|
|
|
return_statement @@ e_assign ~loc name path' value_expr
|
2020-06-10 16:58:59 +02:00
|
|
|
| MapPath v ->
|
2019-05-12 20:56:22 +00:00
|
|
|
let v' = v.value in
|
2019-10-08 16:41:47 +02:00
|
|
|
let%bind (varname,map,path) = match v'.path with
|
2020-06-10 16:58:59 +02:00
|
|
|
| Name name ->
|
|
|
|
ok (name.value ,
|
|
|
|
e_variable (Var.of_name name.value), [])
|
2019-10-08 16:41:47 +02:00
|
|
|
| Path p ->
|
2020-06-10 16:58:59 +02:00
|
|
|
let name, p' = compile_path v'.path in
|
|
|
|
let%bind accessor = compile_projection p in
|
|
|
|
ok @@ (name, accessor, p') in
|
|
|
|
let%bind key_expr =
|
|
|
|
compile_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
|
2020-06-05 17:45:11 +02:00
|
|
|
let varname = Var.of_name varname in
|
|
|
|
return_statement @@ e_assign ~loc varname path expr'
|
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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr = compile_expression c.expr in
|
2020-03-27 14:57:56 +01:00
|
|
|
let%bind cases =
|
|
|
|
let aux (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 ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_single_instruction i
|
2019-10-24 09:58:33 +02:00
|
|
|
| ClauseBlock b ->
|
|
|
|
match b with
|
|
|
|
LongBlock {value; _} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
compile_block value
|
2019-10-24 09:58:33 +02:00
|
|
|
| ShortBlock {value; _} ->
|
2020-06-10 16:58:59 +02:00
|
|
|
compile_statements @@ fst value.inside in
|
2020-03-27 14:57:56 +01:00
|
|
|
let%bind case_clause = case_clause None in
|
|
|
|
ok (x.value.pattern, case_clause) in
|
|
|
|
bind_list
|
|
|
|
@@ List.map aux
|
|
|
|
@@ npseq_to_list c.cases.value in
|
|
|
|
let%bind m = compile_cases cases in
|
|
|
|
return_statement @@ e_matching ~loc expr m
|
2019-05-22 00:46:54 +00:00
|
|
|
)
|
2020-06-08 12:40:14 +02:00
|
|
|
| RecordPatch r ->
|
2019-12-04 18:30:52 +01:00
|
|
|
let reg = r.region in
|
2020-06-10 16:58:59 +02:00
|
|
|
let r, loc = r_split r in
|
|
|
|
let aux (fa: Raw.field_assignment Raw.reg) : Raw.field_path_assignment Raw.reg =
|
|
|
|
{value = {field_path = Name fa.value.field_name;
|
2020-06-08 12:40:14 +02:00
|
|
|
assignment = fa.value.assignment;
|
|
|
|
field_expr = fa.value.field_expr};
|
|
|
|
region = fa.region} in
|
2020-06-10 16:58:59 +02:00
|
|
|
let update : Raw.field_path_assignment Raw.reg Raw.ne_injection Raw.reg = {
|
2020-06-08 12:40:14 +02:00
|
|
|
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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expr = compile_update {value=u;region=reg} in
|
2020-06-10 16:58:59 +02:00
|
|
|
let name, access_path = compile_path r.path in
|
2020-06-05 17:45:11 +02:00
|
|
|
let name = Var.of_name name in
|
|
|
|
return_statement @@ e_assign ~loc name access_path expr
|
2020-06-08 16:05:23 +02:00
|
|
|
| MapPatch patch ->
|
2020-06-10 16:58:59 +02:00
|
|
|
let map_p, loc = r_split patch in
|
|
|
|
let name, access_path = compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind key' = compile_expression key in
|
|
|
|
let%bind value' = compile_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
|
2020-06-10 16:58:59 +02:00
|
|
|
(match inj with
|
2019-12-04 18:30:52 +01:00
|
|
|
| [] -> return_statement @@ e_skip ~loc ()
|
|
|
|
| _ :: _ ->
|
|
|
|
let assigns = List.fold_right
|
|
|
|
(fun (key, value) map -> (e_map_add key value map))
|
|
|
|
inj
|
2020-06-05 17:45:11 +02:00
|
|
|
(e_accessor ~loc (e_variable (Var.of_name name)) access_path)
|
2020-06-08 16:05:23 +02:00
|
|
|
and name = Var.of_name name in
|
2020-06-10 16:58:59 +02:00
|
|
|
return_statement @@ e_assign ~loc name access_path assigns)
|
2019-10-09 17:08:58 -07:00
|
|
|
| SetPatch patch -> (
|
2020-06-10 16:58:59 +02:00
|
|
|
let setp, loc = r_split patch in
|
|
|
|
let name, access_path = compile_path setp.path in
|
2019-10-11 15:10:08 -05:00
|
|
|
let%bind inj =
|
|
|
|
bind_list @@
|
2020-03-16 14:53:56 +01:00
|
|
|
List.map compile_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])
|
2020-06-05 17:45:11 +02:00
|
|
|
inj (e_accessor ~loc (e_variable (Var.of_name name)) access_path) in
|
|
|
|
let name = Var.of_name name in
|
|
|
|
return_statement @@ e_assign ~loc name access_path assigns
|
2019-10-09 17:08:58 -07:00
|
|
|
)
|
2020-06-10 16:58:59 +02:00
|
|
|
| MapRemove r ->
|
2019-05-28 15:36:14 +00:00
|
|
|
let (v , loc) = r_split r in
|
2019-05-12 20:56:22 +00:00
|
|
|
let key = v.key in
|
2020-06-05 17:45:11 +02:00
|
|
|
let%bind (name,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-06-10 16:58:59 +02:00
|
|
|
let name, p' = compile_path v.map in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind accessor = compile_projection p in
|
2019-10-08 18:20:32 +02:00
|
|
|
ok @@ (name , accessor , p')
|
2019-10-08 16:41:47 +02:00
|
|
|
in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind key' = compile_expression key in
|
2019-12-04 11:40:58 +00:00
|
|
|
let expr = e_constant ~loc C_MAP_REMOVE [key' ; map] in
|
2020-06-05 17:45:11 +02:00
|
|
|
let name = Var.of_name name in
|
|
|
|
return_statement @@ e_assign ~loc name path expr
|
2020-06-10 16:58:59 +02:00
|
|
|
| SetRemove r ->
|
|
|
|
let set_rm, loc = r_split r in
|
|
|
|
let%bind (name, set, path) =
|
|
|
|
match set_rm.set with
|
|
|
|
| Name v ->
|
|
|
|
ok (v.value, e_variable (Var.of_name v.value), [])
|
2019-10-14 16:04:48 -07:00
|
|
|
| Path path ->
|
2020-06-10 16:58:59 +02:00
|
|
|
let name, p' = compile_path set_rm.set in
|
|
|
|
let%bind accessor = compile_projection path in
|
|
|
|
ok @@ (name, accessor, p') in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind removed' = compile_expression set_rm.element in
|
2019-12-04 11:40:58 +00:00
|
|
|
let expr = e_constant ~loc C_SET_REMOVE [removed' ; set] in
|
2020-06-05 17:45:11 +02:00
|
|
|
let name = Var.of_name name in
|
|
|
|
return_statement @@ e_assign ~loc name path expr
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-06-10 16:58:59 +02:00
|
|
|
and compile_path : Raw.path -> string * access list = function
|
|
|
|
Raw.Name v -> v.value, []
|
|
|
|
| Raw.Path {value; _} ->
|
|
|
|
let Raw.{struct_name; field_path; _} = value in
|
|
|
|
let var = struct_name.value in
|
|
|
|
let path = List.map compile_selection @@ npseq_to_list field_path
|
|
|
|
in var, path
|
|
|
|
|
|
|
|
and compile_selection : Raw.selection -> access = function
|
|
|
|
FieldName property -> Access_record property.value
|
|
|
|
| Component index -> Access_tuple (snd index.value)
|
2020-06-05 17:45:11 +02:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_cases : (Raw.pattern * expression) list -> (matching_expr , (abs_error)) 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 () =
|
2020-06-12 13:33:14 +02:00
|
|
|
Assert.assert_list_size (unsupported_tuple_pattern t) t' 1 in
|
2019-05-12 20:56:22 +00:00
|
|
|
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)] ->
|
2020-06-04 15:30:14 +02:00
|
|
|
ok @@ Match_variant ([((Constructor "true", Var.of_name "_"), t); ((Constructor "false", Var.of_name "_"), 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
|
2020-06-12 13:33:14 +02:00
|
|
|
| p -> fail @@ unsupported_deep_some_patterns p in
|
2020-06-04 15:30:14 +02: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
|
2020-06-04 15:30:14 +02: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 ->
|
|
|
|
let%bind constrs =
|
2020-06-12 13:33:14 +02:00
|
|
|
trace_strong (unsupported_pattern_type (List.map fst lst)) @@
|
2019-05-12 20:56:22 +00:00
|
|
|
let aux (x , y) =
|
|
|
|
let%bind x' =
|
|
|
|
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
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_instruction : Raw.instruction -> ((_ -> (expression, (abs_error)) result) , (abs_error)) result =
|
|
|
|
fun t -> trace (abstracting_instruction_tracer t) @@ compile_single_instruction t
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_statements : Raw.statements -> ((_ -> (expression,(abs_error)) result) , (abs_error)) result =
|
2020-01-21 18:35:36 +01:00
|
|
|
fun statements ->
|
|
|
|
let lst = npseq_to_list statements in
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind fs = compile_statement_list lst in
|
2020-06-12 13:33:14 +02:00
|
|
|
let aux : _ -> (expression option -> (expression, (abs_error)) result) -> _ =
|
2020-01-21 18:35:36 +01:00
|
|
|
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
|
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_block : Raw.block -> ((_ -> (expression , (abs_error)) result) , (abs_error)) result =
|
2020-03-16 14:53:56 +01:00
|
|
|
fun t -> compile_statements t.statements
|
2019-05-12 20:56:22 +00:00
|
|
|
|
2019-10-26 14:18:06 +02:00
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
and compile_declaration_list declarations : (declaration Location.wrap list, (abs_error)) 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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind type_expression = compile_type_expression type_expr in
|
2020-01-21 18:35:36 +01:00
|
|
|
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 ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let compile_const_decl =
|
2020-01-21 18:35:36 +01:00
|
|
|
fun {name;const_type; init; attributes} ->
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind expression = compile_expression init in
|
|
|
|
let%bind t = compile_type_expression const_type in
|
2020-01-21 18:35:36 +01:00
|
|
|
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-03-16 14:53:56 +01:00
|
|
|
bind_map_location compile_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
|
2020-03-16 14:53:56 +01:00
|
|
|
let%bind ((name, ty_opt), expr) = compile_fun_decl ~loc decl in
|
2020-01-21 18:35:36 +01:00
|
|
|
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
|
|
|
|
2020-06-12 13:33:14 +02:00
|
|
|
let compile_program : Raw.ast -> (program , (abs_error)) result =
|
|
|
|
fun t ->
|
|
|
|
let declarations = nseq_to_list t.decl in
|
|
|
|
trace (program_tracer declarations) @@
|
|
|
|
compile_declaration_list declarations
|