diff --git a/src/aeso_ast_to_fcode.erl b/src/aeso_ast_to_fcode.erl index d50e7e9..7689555 100644 --- a/src/aeso_ast_to_fcode.erl +++ b/src/aeso_ast_to_fcode.erl @@ -261,6 +261,11 @@ decls_to_fcode(Env, Decls) -> -spec decl_to_fcode(env(), aeso_syntax:decl()) -> env(). decl_to_fcode(Env, {type_decl, _, _, _}) -> Env; +decl_to_fcode(Env = #{context := {main_contract, _}}, {fun_decl, Ann, {id, _, Name}, _}) -> + case proplists:get_value(no_code, maps:get(options, Env, []), false) of + false -> fcode_error({missing_definition, Name, lists:keydelete(entrypoint, 1, Ann)}); + true -> Env + end; decl_to_fcode(Env, {fun_decl, _, _, _}) -> Env; decl_to_fcode(Env, {type_def, _Ann, Name, Args, Def}) -> typedef_to_fcode(Env, Name, Args, Def); @@ -1001,6 +1006,8 @@ add_fun_env(Env = #{ context := {abstract_contract, _} }, _) -> Env; %% no func add_fun_env(Env = #{ fun_env := FunEnv }, Decls) -> Entry = fun({letfun, Ann, {id, _, Name}, Args, _, _}) -> [{qname(Env, Name), {make_fun_name(Env, Ann, Name), length(Args)}}]; + ({fun_decl, Ann, {id, _, Name}, {fun_t, _, _, ArgTypes, _}}) -> + [{qname(Env, Name), {make_fun_name(Env, Ann, Name), length(ArgTypes)}}]; (_) -> [] end, FunEnv1 = maps:from_list(lists:flatmap(Entry, Decls)), Env#{ fun_env := maps:merge(FunEnv, FunEnv1) }. diff --git a/src/aeso_ast_to_icode.erl b/src/aeso_ast_to_icode.erl index 779173a..e611f8f 100644 --- a/src/aeso_ast_to_icode.erl +++ b/src/aeso_ast_to_icode.erl @@ -21,18 +21,19 @@ convert_typed(TypedTree, Options) -> {contract, _, {con, _, Con}, _} -> Con; _ -> gen_error(last_declaration_must_be_contract) end, - Icode = code(TypedTree, aeso_icode:set_name(Name, aeso_icode:new(Options))), + NewIcode = aeso_icode:set_name(Name, aeso_icode:new(Options)), + Icode = code(TypedTree, NewIcode, Options), deadcode_elimination(Icode). -code([{contract, _Attribs, Con, Code}|Rest], Icode) -> +code([{contract, _Attribs, Con, Code}|Rest], Icode, Options) -> NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Con, Icode)), - code(Rest, NewIcode); -code([{namespace, _Ann, Name, Code}|Rest], Icode) -> - %% TODO: nested namespaces + code(Rest, NewIcode, Options); +code([{namespace, _Ann, Name, Code}|Rest], Icode, Options) -> + %% TODO: nested namespaces NewIcode = contract_to_icode(Code, aeso_icode:set_namespace(Name, Icode)), - code(Rest, NewIcode); -code([], Icode) -> - add_default_init_function(add_builtins(Icode)). + code(Rest, NewIcode, Options); +code([], Icode, Options) -> + add_default_init_function(add_builtins(Icode), Options). %% Generate error on correct format. @@ -40,10 +41,12 @@ gen_error(Error) -> error({code_errors, [Error]}). %% Create default init function (only if state is unit). -add_default_init_function(Icode = #{functions := Funs, state_type := State}) -> +add_default_init_function(Icode = #{functions := Funs, state_type := State}, Options) -> + NoCode = proplists:get_value(no_code, Options, false), {_, _, QInit} = aeso_icode:qualify({id, [], "init"}, Icode), case lists:keymember(QInit, 1, Funs) of true -> Icode; + false when NoCode -> Icode; false when State /= {tuple, []} -> gen_error(missing_init_function); false -> diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index f2f1ef0..cd464d7 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -35,6 +35,7 @@ | pp_icode | pp_assembler | pp_bytecode + | no_code | {backend, aevm | fate} | {include, {file_system, [string()]} | {explicit_files, #{string() => binary()}}} @@ -134,7 +135,7 @@ from_string1(fate, ContractString, Options) -> fate_code => FateCode }}. --spec string_to_code(string(), [option()]) -> map(). +-spec string_to_code(string(), options()) -> map(). string_to_code(ContractString, Options) -> Ast = parse(ContractString, Options), pp_sophia_code(Ast, Options), @@ -361,7 +362,8 @@ create_calldata(Code, Fun, Args) -> -spec create_calldata(string(), string(), [string()], [{atom(), any()}]) -> {ok, binary()} | {error, term()}. -create_calldata(Code, Fun, Args, Options) -> +create_calldata(Code, Fun, Args, Options0) -> + Options = [no_code | Options0], case proplists:get_value(backend, Options, aevm) of aevm -> case check_call(Code, Fun, Args, Options) of @@ -383,7 +385,8 @@ create_calldata(Code, Fun, Args, Options) -> decode_calldata(ContractString, FunName, Calldata) -> decode_calldata(ContractString, FunName, Calldata, [{backend, aevm}]). -decode_calldata(ContractString, FunName, Calldata, Options) -> +decode_calldata(ContractString, FunName, Calldata, Options0) -> + Options = [no_code | Options0], try Code = string_to_code(ContractString, Options), #{ typed_ast := TypedAst, type_env := TypeEnv} = Code,