add variant expression pattern-matching
This commit is contained in:
parent
72f5698c3d
commit
0aa01ddcd8
@ -103,7 +103,7 @@ and instruction ppf (i:instruction) = match i with
|
|||||||
|
|
||||||
let declaration ppf (d:declaration) =
|
let declaration ppf (d:declaration) =
|
||||||
match d with
|
match d with
|
||||||
| Declaration_constant {name ; annotated_expression = ae} ->
|
| Declaration_constant ({name ; annotated_expression = ae} , _) ->
|
||||||
fprintf ppf "const %s = %a" name annotated_expression ae
|
fprintf ppf "const %s = %a" name annotated_expression ae
|
||||||
|
|
||||||
let program ppf (p:program) =
|
let program ppf (p:program) =
|
||||||
|
@ -171,7 +171,7 @@ let get_a_bool (t:annotated_expression) =
|
|||||||
let get_declaration_by_name : program -> string -> declaration result = fun p name ->
|
let get_declaration_by_name : program -> string -> declaration result = fun p name ->
|
||||||
let aux : declaration -> bool = fun declaration ->
|
let aux : declaration -> bool = fun declaration ->
|
||||||
match declaration with
|
match declaration with
|
||||||
| Declaration_constant d -> d.name = name
|
| Declaration_constant (d , _) -> d.name = name
|
||||||
in
|
in
|
||||||
trace_option (simple_error "no declaration with given name") @@
|
trace_option (simple_error "no declaration with given name") @@
|
||||||
List.find_opt aux @@ List.map Location.unwrap p
|
List.find_opt aux @@ List.map Location.unwrap p
|
||||||
|
@ -14,7 +14,7 @@ type 'a type_name_map = 'a SMap.t
|
|||||||
type program = declaration Location.wrap list
|
type program = declaration Location.wrap list
|
||||||
|
|
||||||
and declaration =
|
and declaration =
|
||||||
| Declaration_constant of named_expression
|
| Declaration_constant of (named_expression * full_environment)
|
||||||
(* | Macro_declaration of macro_declaration *)
|
(* | Macro_declaration of macro_declaration *)
|
||||||
|
|
||||||
and environment_element = {
|
and environment_element = {
|
||||||
@ -141,7 +141,7 @@ open Trace
|
|||||||
let get_entry (p:program) (entry : string) : annotated_expression result =
|
let get_entry (p:program) (entry : string) : annotated_expression result =
|
||||||
let aux (d:declaration) =
|
let aux (d:declaration) =
|
||||||
match d with
|
match d with
|
||||||
| Declaration_constant {name ; annotated_expression} when entry = name -> Some annotated_expression
|
| Declaration_constant ({name ; annotated_expression} , _) when entry = name -> Some annotated_expression
|
||||||
| Declaration_constant _ -> None
|
| Declaration_constant _ -> None
|
||||||
in
|
in
|
||||||
let%bind result =
|
let%bind result =
|
||||||
|
@ -300,15 +300,15 @@ and translate_expression ?(first=false) (expr:expression) : michelson result =
|
|||||||
let%bind restrict_r = Compiler_environment.to_michelson_restrict r.environment in
|
let%bind restrict_r = Compiler_environment.to_michelson_restrict r.environment in
|
||||||
let%bind code = ok (seq [
|
let%bind code = ok (seq [
|
||||||
c' ; i_unpair ;
|
c' ; i_unpair ;
|
||||||
i_if_none (seq [
|
i_if_left (seq [
|
||||||
i_pair ;
|
i_swap ; dip i_pair ;
|
||||||
l' ;
|
l' ;
|
||||||
i_unpair ;
|
i_comment "restrict left" ;
|
||||||
dip restrict_l ;
|
dip restrict_l ;
|
||||||
]) (seq [
|
]) (seq [
|
||||||
i_pair ;
|
i_swap ; dip i_pair ;
|
||||||
r' ;
|
r' ;
|
||||||
i_unpair ;
|
i_comment "restrict right" ;
|
||||||
dip restrict_r ;
|
dip restrict_r ;
|
||||||
])
|
])
|
||||||
;
|
;
|
||||||
@ -324,7 +324,8 @@ and translate_expression ?(first=false) (expr:expression) : michelson result =
|
|||||||
i_unpair ;
|
i_unpair ;
|
||||||
i_swap ; dip i_pair ;
|
i_swap ; dip i_pair ;
|
||||||
body' ;
|
body' ;
|
||||||
restrict ;
|
i_comment "restrict let" ;
|
||||||
|
dip restrict ;
|
||||||
]) in
|
]) in
|
||||||
return code
|
return code
|
||||||
)
|
)
|
||||||
|
9
src/ligo/contracts/variant-matching.ligo
Normal file
9
src/ligo/contracts/variant-matching.ligo
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
type foobar is
|
||||||
|
| Foo of int
|
||||||
|
| Bar of bool
|
||||||
|
|
||||||
|
function fb(const p : foobar) : int is
|
||||||
|
block { skip } with (case p of
|
||||||
|
| Foo (n) -> n
|
||||||
|
| Bar (t) -> 42
|
||||||
|
end)
|
@ -6,8 +6,3 @@ const foo : foobar = Foo (42)
|
|||||||
|
|
||||||
const bar : foobar = Bar (True)
|
const bar : foobar = Bar (True)
|
||||||
|
|
||||||
function fb(const p : foobar) : int is
|
|
||||||
block { skip } with (case p of
|
|
||||||
| Foo (n) -> n
|
|
||||||
| Bar (t) -> 42
|
|
||||||
end)
|
|
||||||
|
@ -40,7 +40,7 @@ include struct
|
|||||||
let assert_valid_entry_point : program -> string -> unit result = fun p e ->
|
let assert_valid_entry_point : program -> string -> unit result = fun p e ->
|
||||||
let%bind declaration = get_declaration_by_name p e in
|
let%bind declaration = get_declaration_by_name p e in
|
||||||
match declaration with
|
match declaration with
|
||||||
| Declaration_constant d -> assert_entry_point_type d.annotated_expression.type_annotation
|
| Declaration_constant (d , _) -> assert_entry_point_type d.annotated_expression.type_annotation
|
||||||
end
|
end
|
||||||
|
|
||||||
let transpile_value
|
let transpile_value
|
||||||
@ -97,7 +97,7 @@ let compile_contract_parameter : string -> string -> string -> string result = f
|
|||||||
assert_valid_entry_point typed entry_point in
|
assert_valid_entry_point typed entry_point in
|
||||||
let%bind declaration = Ast_typed.Combinators.get_declaration_by_name typed entry_point in
|
let%bind declaration = Ast_typed.Combinators.get_declaration_by_name typed entry_point in
|
||||||
match declaration with
|
match declaration with
|
||||||
| Declaration_constant d -> ok d.annotated_expression.type_annotation
|
| Declaration_constant (d , _) -> ok d.annotated_expression.type_annotation
|
||||||
in
|
in
|
||||||
let%bind expr =
|
let%bind expr =
|
||||||
let%bind raw =
|
let%bind raw =
|
||||||
|
@ -126,7 +126,13 @@ let easy_run_typed_simplified
|
|||||||
Format.(printf "Mini_c : %a\n%!" Mini_c.PP.function_ mini_c_main.content)
|
Format.(printf "Mini_c : %a\n%!" Mini_c.PP.function_ mini_c_main.content)
|
||||||
) ;
|
) ;
|
||||||
|
|
||||||
let%bind typed_value = type_expression input in
|
let%bind typed_value =
|
||||||
|
let env =
|
||||||
|
let last_declaration = Location.unwrap List.(hd @@ rev program) in
|
||||||
|
match last_declaration with
|
||||||
|
| Declaration_constant (_ , env) -> env
|
||||||
|
in
|
||||||
|
type_expression ~env input in
|
||||||
let%bind mini_c_value = transpile_value typed_value in
|
let%bind mini_c_value = transpile_value typed_value in
|
||||||
|
|
||||||
let%bind mini_c_result =
|
let%bind mini_c_result =
|
||||||
|
@ -22,10 +22,15 @@ let variant () : unit result =
|
|||||||
let%bind () =
|
let%bind () =
|
||||||
let expected = e_a_constructor "Bar" (e_a_bool true) in
|
let expected = e_a_constructor "Bar" (e_a_bool true) in
|
||||||
expect_evaluate program "bar" expected in
|
expect_evaluate program "bar" expected in
|
||||||
(* let%bind () =
|
ok ()
|
||||||
* let make_expect = fun n -> (3 * n + 2) in
|
|
||||||
* expect_n_int program "fb" make_expect
|
let variant_matching () : unit result =
|
||||||
* in *)
|
let%bind program = type_file "./contracts/variant-matching.ligo" in
|
||||||
|
let%bind () =
|
||||||
|
let make_input = fun n -> e_a_constructor "Foo" (e_a_int n) in
|
||||||
|
let make_expected = e_a_int in
|
||||||
|
expect_n program "fb" make_input make_expected
|
||||||
|
in
|
||||||
ok ()
|
ok ()
|
||||||
|
|
||||||
let closure () : unit result =
|
let closure () : unit result =
|
||||||
@ -324,6 +329,7 @@ let main = "Integration (End to End)", [
|
|||||||
test "function" function_ ;
|
test "function" function_ ;
|
||||||
test "complex function" complex_function ;
|
test "complex function" complex_function ;
|
||||||
test "variant" variant ;
|
test "variant" variant ;
|
||||||
|
test "variant matching" variant_matching ;
|
||||||
test "closure" closure ;
|
test "closure" closure ;
|
||||||
test "shared function" shared_function ;
|
test "shared function" shared_function ;
|
||||||
test "shadow" shadow ;
|
test "shadow" shadow ;
|
||||||
|
@ -201,7 +201,7 @@ and tree_of_sum : AST.type_value -> (type_name * AST.type_value) Append_tree.t r
|
|||||||
|
|
||||||
and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_expression) : expression result =
|
and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_expression) : expression result =
|
||||||
let%bind tv = translate_type ae.type_annotation in
|
let%bind tv = translate_type ae.type_annotation in
|
||||||
let return ?(tv = tv) expr =
|
let return ?(tv = tv) ?(env = env) expr =
|
||||||
(* let%bind env' = transpile_environment ae.environment in *)
|
(* let%bind env' = transpile_environment ae.environment in *)
|
||||||
ok @@ Combinators.Expression.make_tpl (expr, tv, env) in
|
ok @@ Combinators.Expression.make_tpl (expr, tv, env) in
|
||||||
let f = translate_annotated_expression env in
|
let f = translate_annotated_expression env in
|
||||||
@ -374,7 +374,7 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
in aux tree'
|
in aux tree'
|
||||||
in
|
in
|
||||||
|
|
||||||
let rec aux acc t =
|
let rec aux (acc , env) t =
|
||||||
let top =
|
let top =
|
||||||
match acc with
|
match acc with
|
||||||
| None -> expr'
|
| None -> expr'
|
||||||
@ -386,26 +386,26 @@ and translate_annotated_expression (env:Environment.t) (ae:AST.annotated_express
|
|||||||
List.find_opt (fun ((constructor_name' , _) , _) -> constructor_name' = constructor_name) lst in
|
List.find_opt (fun ((constructor_name' , _) , _) -> constructor_name' = constructor_name) lst in
|
||||||
let env' = Environment.(add (name , tv) @@ extend env) in
|
let env' = Environment.(add (name , tv) @@ extend env) in
|
||||||
let%bind body' = translate_annotated_expression env' body in
|
let%bind body' = translate_annotated_expression env' body in
|
||||||
return @@ E_let_in ((name , tv) , top , body')
|
return ~env:env' @@ E_let_in ((name , tv) , top , body')
|
||||||
)
|
)
|
||||||
| ((`Node (a , b)) , tv) ->
|
| ((`Node (a , b)) , tv) ->
|
||||||
let%bind a' =
|
let%bind a' =
|
||||||
let%bind a_ty = get_t_left tv in
|
let%bind a_ty = get_t_left tv in
|
||||||
let a_var = "left" , a_ty in
|
let a_var = "left" , a_ty in
|
||||||
let env' = Environment.(add a_var @@ extend env) in
|
let env' = Environment.(add a_var @@ extend env) in
|
||||||
let%bind e = aux (Some (Expression.make (E_variable "left") a_ty env')) a in
|
let%bind e = aux ((Some (Expression.make (E_variable "left") a_ty env')) , env') a in
|
||||||
ok (a_var , e)
|
ok (a_var , e)
|
||||||
in
|
in
|
||||||
let%bind b' =
|
let%bind b' =
|
||||||
let%bind b_ty = get_t_right tv in
|
let%bind b_ty = get_t_right tv in
|
||||||
let b_var = "right" , b_ty in
|
let b_var = "right" , b_ty in
|
||||||
let env' = Environment.(add b_var @@ extend env) in
|
let env' = Environment.(add b_var @@ extend env) in
|
||||||
let%bind e = aux (Some (Expression.make (E_variable "right") b_ty env')) b in
|
let%bind e = aux ((Some (Expression.make (E_variable "right") b_ty env')) , env') b in
|
||||||
ok (b_var , e)
|
ok (b_var , e)
|
||||||
in
|
in
|
||||||
return @@ E_if_left (top , a' , b')
|
return ~env @@ E_if_left (top , a' , b')
|
||||||
in
|
in
|
||||||
aux None tree''
|
aux (None , env) tree''
|
||||||
)
|
)
|
||||||
| AST.Match_list _ | AST.Match_tuple (_, _) ->
|
| AST.Match_list _ | AST.Match_tuple (_, _) ->
|
||||||
simple_fail "only match bool and option exprs are translated yet"
|
simple_fail "only match bool and option exprs are translated yet"
|
||||||
@ -456,7 +456,7 @@ and translate_lambda env l =
|
|||||||
|
|
||||||
let translate_declaration env (d:AST.declaration) : toplevel_statement result =
|
let translate_declaration env (d:AST.declaration) : toplevel_statement result =
|
||||||
match d with
|
match d with
|
||||||
| Declaration_constant {name;annotated_expression} ->
|
| Declaration_constant ({name;annotated_expression} , _) ->
|
||||||
let%bind expression = translate_annotated_expression env annotated_expression in
|
let%bind expression = translate_annotated_expression env annotated_expression in
|
||||||
let tv = Combinators.Expression.get_type expression in
|
let tv = Combinators.Expression.get_type expression in
|
||||||
let env' = Environment.add (name, tv) env in
|
let env' = Environment.add (name, tv) env in
|
||||||
@ -495,7 +495,7 @@ let translate_entry (lst:AST.program) (name:string) : anon_function result =
|
|||||||
match lst with
|
match lst with
|
||||||
| [] -> None
|
| [] -> None
|
||||||
| hd :: tl -> (
|
| hd :: tl -> (
|
||||||
let (AST.Declaration_constant an) = temp_unwrap_loc hd in
|
let (AST.Declaration_constant (an , _)) = temp_unwrap_loc hd in
|
||||||
match an.name = name with
|
match an.name = name with
|
||||||
| true -> (
|
| true -> (
|
||||||
match an.annotated_expression.expression with
|
match an.annotated_expression.expression with
|
||||||
|
@ -74,7 +74,7 @@ and type_declaration env : I.declaration -> (environment * O.declaration option)
|
|||||||
trace (constant_declaration_error name annotated_expression) @@
|
trace (constant_declaration_error name annotated_expression) @@
|
||||||
type_annotated_expression env annotated_expression in
|
type_annotated_expression env annotated_expression in
|
||||||
let env' = Environment.add_ez name ae'.type_annotation env in
|
let env' = Environment.add_ez name ae'.type_annotation env in
|
||||||
ok (env', Some (O.Declaration_constant (make_n_e name ae')))
|
ok (env', Some (O.Declaration_constant ((make_n_e name ae') , env')))
|
||||||
|
|
||||||
and type_block_full (e:environment) (b:I.block) : (O.block * environment) result =
|
and type_block_full (e:environment) (b:I.block) : (O.block * environment) result =
|
||||||
let aux (e, acc:(environment * O.instruction list)) (i:I.instruction) =
|
let aux (e, acc:(environment * O.instruction list)) (i:I.instruction) =
|
||||||
|
Loading…
Reference in New Issue
Block a user