diff --git a/src/aeso_ast_infer_types.erl b/src/aeso_ast_infer_types.erl index dcd67b3..3a43886 100644 --- a/src/aeso_ast_infer_types.erl +++ b/src/aeso_ast_infer_types.erl @@ -406,6 +406,7 @@ global_env() -> Map = fun(A, B) -> {app_t, Ann, {id, Ann, "map"}, [A, B]} end, Pair = fun(A, B) -> {tuple_t, Ann, [A, B]} end, FunC = fun(C, Ts, T) -> {type_sig, Ann, C, [], Ts, T} end, + FunC1 = fun(C, S, T) -> {type_sig, Ann, C, [], [S], T} end, Fun = fun(Ts, T) -> FunC(none, Ts, T) end, Fun1 = fun(S, T) -> Fun([S], T) end, FunCN = fun(C, Named, Normal, Ret) -> {type_sig, Ann, C, Named, Normal, Ret} end, @@ -475,7 +476,7 @@ global_env() -> {"block_height", Int}, {"difficulty", Int}, {"gas_limit", Int}, - {"bytecode_hash",Fun1(Address, Option(Hash))}, + {"bytecode_hash",FunC1(bytecode_hash, A, Option(Hash))}, {"create", FunCN(create, [ {named_arg_t, Ann, {id, Ann, "value"}, Int, {typed, Ann, {int, Ann, 0}, Int}} , {named_arg_t, Ann, {id, Ann, "code"}, A, undefined} @@ -1909,7 +1910,6 @@ check_named_argument_constraint(Env, general_type = GenType, specialized_type = SpecType, context = {check_return, App} }) -> - io:format("CEHCK DEP: GEN ~p, SPEC: ~p\n", [GenType, SpecType]), NamedArgsT = dereference(NamedArgsT0), case dereference(NamedArgsT0) of [_ | _] = NamedArgsT -> @@ -1934,7 +1934,6 @@ specialize_dependent_type(Env, Type) -> {typed, _, {bool, _, false}, _} -> Else; _ -> type_error({named_argument_must_be_literal_bool, Arg, Val}), - io:format("CHYUJ: ~p\n", [Val]), fresh_uvar(aeso_syntax:get_ann(Val)) end; _ -> Type %% Currently no deep dependent types @@ -2510,8 +2509,14 @@ apply_typesig_constraint(Ann, bytes_concat, {fun_t, _, [], [A, B], C}) -> add_bytes_constraint({add_bytes, Ann, concat, A, B, C}); apply_typesig_constraint(Ann, bytes_split, {fun_t, _, [], [C], {tuple_t, _, [A, B]}}) -> add_bytes_constraint({add_bytes, Ann, split, A, B, C}); -apply_typesig_constraint(Ann, clone, {fun_t, _, Named, var_args, Ret}) -> - ok. +apply_typesig_constraint(Ann, clone, {fun_t, _, Named, var_args, _}) -> + [RefT] = [RefT || {named_arg_t, _, {id, _, "ref"}, RefT, _} <- Named], + constrain([#is_contract_constraint{ contract_t = RefT, + context = {clone, Ann} }]); +apply_typesig_constraint(Ann, bytecode_hash, {fun_t, _, _, [Con], _}) -> + constrain([#is_contract_constraint{ contract_t = Con, + context = {bytecode_hash, Ann} }]). + %% Dereferences all uvars and replaces the uninstantiated ones with a %% succession of tvars. @@ -2640,6 +2645,10 @@ mk_error({not_a_contract_type, Type, Cxt}) -> end, {Pos, Cxt1} = case Cxt of + {clone, Ann} -> + {pos(Ann), "when calling Chain.clone"}; + {bytecode_hash, Ann} -> + {pos(Ann), "when calling Chain.bytecode_hash"}; {contract_literal, Lit} -> {pos(Lit), io_lib:format("when checking that the contract literal\n~s\n" diff --git a/src/aeso_fcode_to_fate.erl b/src/aeso_fcode_to_fate.erl index 659fcab..a525dcc 100644 --- a/src/aeso_fcode_to_fate.erl +++ b/src/aeso_fcode_to_fate.erl @@ -557,7 +557,7 @@ builtin_to_scode(_Env, auth_tx_hash, []) -> builtin_to_scode(_Env, auth_tx, []) -> [aeb_fate_ops:auth_tx(?a)]; builtin_to_scode(Env, chain_bytecode_hash, [_Addr] = Args) -> - call_to_scode(Env, aeb_fate_ops:bytecode_hash(?a), Args); + call_to_scode(Env, aeb_fate_ops:bytecode_hash(?a, ?a), Args); builtin_to_scode(Env, chain_clone, [TypeRep, GasCap, Value, Prot, Contract | InitArgs]) -> call_to_scode(Env, aeb_fate_ops:clone_g(?a, ?a, ?a, ?a, ?a), diff --git a/test/aeso_compiler_tests.erl b/test/aeso_compiler_tests.erl index eca7383..19e8630 100644 --- a/test/aeso_compiler_tests.erl +++ b/test/aeso_compiler_tests.erl @@ -127,7 +127,7 @@ compile(Backend, Name, Options) -> %% compilable_contracts() -> [ContractName]. %% The currently compilable contracts. -compilable_contracts() -> ["clone"]; % FIXME remove +compilable_contracts() -> ["test"]; % FIXME remove compilable_contracts() -> ["complex_types", "counter", diff --git a/test/contracts/clone.aes b/test/contracts/clone.aes new file mode 100644 index 0000000..d66408d --- /dev/null +++ b/test/contracts/clone.aes @@ -0,0 +1,26 @@ + +contract interface HigherOrderState = + entrypoint init : () => void + entrypoint apply : int => int + stateful entrypoint inc : int => unit + +contract interface LowerDisorderAnarchy = + entrypoint init : int => void + + +main contract C = + stateful entrypoint run_clone(s : HigherOrderState, l : LowerDisorderAnarchy) : HigherOrderState = + let s1 = Chain.clone(ref=s) + let Some(s2) = Chain.clone(ref=s, protected=true) + let None = Chain.clone(ref=l, protected=true, 123) + let s3 = Chain.clone(ref=s1) + require(s1.apply(2137) == 2137, "APPLY_S1_0") + require(s2.apply(2137) == 2137, "APPLY_S2_0") + require(s3.apply(2137) == 2137, "APPLY_S3_0") + s1.inc(1) + s2.inc(1) + s1.inc(1) + require(s1.apply(2137) == 2139, "APPLY_S1_2") + require(s2.apply(2137) == 2138, "APPLY_S2_1") + require(s3.apply(2137) == 2137, "APPLY_S3_0") + s1 \ No newline at end of file diff --git a/test/contracts/clone_simple.aes b/test/contracts/clone_simple.aes new file mode 100644 index 0000000..72333e3 --- /dev/null +++ b/test/contracts/clone_simple.aes @@ -0,0 +1,7 @@ +contract interface I = + entrypoint init : () => void + +contract C = + entrypoint f(i : I) = + let Some(c1) = Chain.clone(ref=i, protected = true) + 2 \ No newline at end of file diff --git a/test/contracts/test.aes b/test/contracts/test.aes index c20002f..4fd2d73 100644 --- a/test/contracts/test.aes +++ b/test/contracts/test.aes @@ -1,102 +1,9 @@ +// If you need a quick compiler test — this file is for your playground +contract interface Remote = + entrypoint init : int => void + entrypoint f : int => int -contract Identity = - // type xy = {x:int, y:int} - // type xz = {x:int, z:int} - // type yz = {y:int, z:int} - record point = {x:int,y:int} - record cp('a) = {color: string, p:'a} - //type intpoint = point(int) - // //if (x==42) 1 else (x*x) - // } - //let baz() = {age:3, name:(4:int)} - //let foo(a,b,c) = c - // let rec fac(n) = if((n:int)==0) 1 else (n*fac(n-1)) - // and main(x) = x::[x+1] - // let lentr(l) = lent(0,l) - // let rec len(l) = - // switch(l) { - // | [] => 0 - // | x::xs => 1+len(xs) - // } - // let lent(n,l) = - // switch (l) { - // | [] => n - // | (x::xs) => lent(n+1,xs) - // } - // let rec app(a,b) = - // switch(a) { - // | [] => b - // | (x::xs) => x::app(xs,b) - // } - // let rec revt(l,r) = - // switch(l) { - // | [] => r - // | x::xs => revt(xs,x::r) - // } - // let rev(l) = revt(l,[]) - // let main(x:int) = { - // switch(rev([1,2,3])) { - // | h::_ => h - // } - // } - //let fac(n:int) = { - // if (n==0) 1 else (n*fac(n-1)) - //} - //let main(x) = switch((12,34)) { - //| (13,_) => x - //| (_,a) => x+a - // | y => y+1 - // } - //let main(x) = ({y:0>1, x:x==0}:point(bool)) - //let main(x) = x - //let main(x) = len(1::2::[]) - //let main(x) = ((x,x):list('a)) - // let main(x) = switch("a") { - // | "b" => 0 - // | "a" => 1 - // | "c" => 2 - // } - //let main(x) = x.color+1 - //let main(x) = switch(({x:x, y:x+1}:cp(int))) { - // | {y:xx} => xx - // } - //let main(x) = {x:0, y:1, z:2} - // let id(x) = x - // let double(x) = x+x - // let pair(x) = (1,2) - // let unit(x) = () - // let tuples(x) = ((1,x),(2,3,4)) - // let singleton(x) = [x] - // let rec seq(n) = if (n==0) [] else (app(seq(n-1),[n])) - // let idString(s:string) = s - // let pairString(s:string) = (s,s) - // let revStrings(ss:list(string))=rev(ss) - // let makePoint(x,y) = {x:x, y:y} - // let getx(x) = x.x - // let updatex(p,x) = p{x:x} - // let quad(x) = {let y=x+x; let z=y+y; z;} - // let noblock(x) = {x; x} - // let unit(x) = () - // let foo(x) = switch (x) { - // | y => y+1 -// } - // let p(x) = {color:"blue", p:{x:x, y:x+1}} - //let twice(f,x) = f(f(x)) - // let twice(f,x) = f(f(x)) - // let double(x) = x+x - // let main(x) = twice((y=>y+y),x) - // let rec map(f,xs) = switch(xs) { - // | [] => [] - // | (x::ys) => f(x)::map(f,ys) - // } - // let id(x) = x - // let main(xs) = map(double,xs) - function z(f,x) = x - function s(n) = (f,x)=>f(n(f,x)) - function add(m,n) = (f,x)=>m(f,n(f,x)) - - entrypoint main_fun() = - let three=s(s(s(z))) - add(three,three) - (((i)=>i+1),0) - +contract Test = + entrypoint kek(r : Remote) = + Chain.clone(ref=r, 123) + Chain.bytecode_hash(r) \ No newline at end of file