add and test more ways to do function application in pascaligo

This commit is contained in:
galfour 2019-11-14 20:12:41 +01:00
parent 628d818163
commit d0efbd9f92
7 changed files with 101 additions and 28 deletions

View File

@ -580,7 +580,7 @@ and selection =
and tuple_expr = (expr, comma) nsepseq par reg
and fun_call = (fun_name * arguments) reg
and fun_call = (expr * arguments) reg
and arguments = tuple_expr

View File

@ -570,7 +570,7 @@ and selection =
and tuple_expr = (expr, comma) nsepseq par reg
and fun_call = (fun_name * arguments) reg
and fun_call = (expr * arguments) reg
and arguments = tuple_expr

View File

@ -863,14 +863,12 @@ core_expr:
| Unit { EUnit $1 }
| annot_expr { EAnnot $1 }
| tuple_expr { ETuple $1 }
| par(expr) { EPar $1 }
| list_expr { EList $1 }
| C_None { EConstr (NoneExpr $1) }
| fun_call { ECall $1 }
| fun_call_or_par_or_projection { $1 }
| map_expr { EMap $1 }
| set_expr { ESet $1 }
| record_expr { ERecord $1 }
| projection { EProj $1 }
| Constr arguments {
let region = cover $1.region $2.region in
EConstr (ConstrApp {region; value = $1, Some $2})
@ -882,6 +880,30 @@ core_expr:
let region = cover $1 $2.region in
EConstr (SomeApp {region; value = $1,$2})}
fun_call_or_par_or_projection:
| par(expr) option(arguments) {
let parenthesized = EPar $1 in
match $2 with
| None -> parenthesized
| Some args -> (
let region_1 = $1.region in
let region = cover region_1 args.region in
ECall {region; value = parenthesized,args}
)
}
| projection option(arguments) {
let project = EProj $1 in
match $2 with
| None -> project
| Some args -> (
let region_1 = $1.region in
let region = cover region_1 args.region in
ECall {region; value = project,args}
)
}
| fun_call { ECall $1 }
annot_expr:
LPAR disj_expr COLON type_expr RPAR {
let start = expr_to_region $2
@ -956,7 +978,7 @@ field_assignment:
fun_call:
fun_name arguments {
let region = cover $1.region $2.region
in {region; value = $1,$2}}
in {region; value = (EVar $1),$2}}
tuple_expr:
par(tuple_comp) { $1 }

View File

@ -655,8 +655,8 @@ and print_nil buffer value = print_token buffer value "nil"
and print_none_expr buffer value = print_token buffer value "None"
and print_fun_call buffer {value; _} =
let fun_name, arguments = value in
print_var buffer fun_name;
let expr, arguments = value in
print_expr buffer expr;
print_tuple_expr buffer arguments
and print_constr_app buffer {value; _} =
@ -1247,12 +1247,12 @@ and pp_var_binding buffer ~pad:(_,pc as pad) (source, image) =
pp_ident buffer ~pad:(mk_pad 2 0 pc) source;
pp_ident buffer ~pad:(mk_pad 2 1 pc) image
and pp_fun_call buffer ~pad:(_,pc) (name, args) =
and pp_fun_call buffer ~pad:(_,pc) (expr, args) =
let args = Utils.nsepseq_to_list args.value.inside in
let arity = List.length args in
let apply len rank =
pp_expr buffer ~pad:(mk_pad len rank pc)
in pp_ident buffer ~pad:(mk_pad (1+arity) 0 pc) name;
in pp_expr buffer ~pad:(mk_pad (1+arity) 0 pc) expr;
List.iteri (apply arity) args
and pp_record_patch buffer ~pad:(_,pc as pad) patch =

View File

@ -263,18 +263,26 @@ let rec simpl_expression (t:Raw.expr) : expr result =
| Some s -> return @@ e_constant ~loc s []
)
| ECall x -> (
let ((name, args) , loc) = r_split x in
let (f , f_loc) = r_split name in
let ((f, args) , loc) = r_split x in
let (args , args_loc) = r_split args in
let args' = npseq_to_list args.inside in
match List.assoc_opt f constants with
match f with
| EVar name -> (
let (f_name , f_loc) = r_split name in
match List.assoc_opt f_name constants with
| None ->
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
return @@ e_application ~loc (e_variable ~loc:f_loc f) arg
return @@ e_application ~loc (e_variable ~loc:f_loc f_name) arg
| Some s ->
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
)
)
| EPar x -> simpl_expression x.value.inside
| EUnit reg ->
let loc = Location.lift reg in
@ -630,18 +638,26 @@ and simpl_single_instruction : Raw.instruction -> (_ -> expression result) resul
fun t ->
match t with
| ProcCall x -> (
let ((name, args) , loc) = r_split x in
let (f , f_loc) = r_split name in
let ((f, args) , loc) = r_split x in
let (args , args_loc) = r_split args in
let args' = npseq_to_list args.inside in
match List.assoc_opt f constants with
match f with
| EVar name -> (
let (f_name , f_loc) = r_split name in
match List.assoc_opt f_name constants with
| None ->
let%bind arg = simpl_tuple_expression ~loc:args_loc args' in
return_statement @@ e_application ~loc (e_variable ~loc:f_loc f) arg
return_statement @@ e_application ~loc (e_variable ~loc:f_loc f_name) arg
| Some s ->
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
)
)
| Skip reg -> (
let loc = Location.lift reg in
return_statement @@ e_skip ~loc ()

View File

@ -0,0 +1,21 @@
// Test different ways of calling functions in PascaLIGO
type foo is record
bar : int -> int ;
end
function f (const i : int) : int is
begin
skip
end with i
function g (const i : unit) : int -> int is
begin skip end with f
const r : foo = record
bar = f ;
end
const x : int = f(42)
const y : int = r.bar(42)
const z : int = (g(unit))(42)

View File

@ -52,6 +52,19 @@ let complex_function () : unit result =
let make_expect = fun n -> (3 * n + 2) in
expect_eq_n_int program "main" make_expect
let application () : unit result =
let%bind program = type_file "./contracts/application.ligo" in
let%bind () =
let expected = e_int 42 in
expect_eq_evaluate program "x" expected in
let%bind () =
let expected = e_int 42 in
expect_eq_evaluate program "y" expected in
let%bind () =
let expected = e_int 42 in
expect_eq_evaluate program "z" expected in
ok ()
let variant () : unit result =
let%bind program = type_file "./contracts/variant.ligo" in
let%bind () =
@ -1164,6 +1177,7 @@ let main = test_suite "Integration (End to End)" [
test "assign" assign ;
test "declaration local" declaration_local ;
test "complex function" complex_function ;
test "various applications" application ;
test "closure" closure ;
test "shared function" shared_function ;
test "shared function (mligo)" shared_function_mligo ;