diff --git a/src/aeso_compiler.erl b/src/aeso_compiler.erl index 7d34ad5..3080e53 100644 --- a/src/aeso_compiler.erl +++ b/src/aeso_compiler.erl @@ -22,7 +22,7 @@ -type option() :: pp_sophia_code | pp_ast | pp_types | pp_typed_ast | - pp_icode| pp_assembler | pp_bytecode. + pp_icode| pp_assembler | pp_bytecode. -type options() :: [option()]. -export_type([ option/0 @@ -38,50 +38,50 @@ version() -> ?COMPILER_VERSION. --spec file(string()) -> map(). +-spec file(string()) -> {ok, map()} | {error, binary()}. file(Filename) -> file(Filename, []). --spec file(string(), options()) -> map(). +-spec file(string(), options()) -> {ok, map()} | {error, binary()}. file(File, Options) -> case read_contract(File) of {ok, Bin} -> from_string(Bin, Options); {error, Error} -> {error, {File, Error}} end. --spec from_string(binary() | string(), options()) -> map(). +-spec from_string(binary() | string(), options()) -> {ok, map()} | {error, binary()}. from_string(ContractBin, Options) when is_binary(ContractBin) -> from_string(binary_to_list(ContractBin), Options); from_string(ContractString, Options) -> try - Ast = parse(ContractString, Options), - ok = pp_sophia_code(Ast, Options), - ok = pp_ast(Ast, Options), - TypedAst = aeso_ast_infer_types:infer(Ast, Options), - %% pp_types is handled inside aeso_ast_infer_types. - ok = pp_typed_ast(TypedAst, Options), - ICode = to_icode(TypedAst, Options), - TypeInfo = extract_type_info(ICode), - ok = pp_icode(ICode, Options), - Assembler = assemble(ICode, Options), - ok = pp_assembler(Assembler, Options), - ByteCodeList = to_bytecode(Assembler, Options), - ByteCode = << << B:8 >> || B <- ByteCodeList >>, - ok = pp_bytecode(ByteCode, Options), - {ok,#{byte_code => ByteCode, - compiler_version => version(), - contract_source => ContractString, - type_info => TypeInfo - }} + Ast = parse(ContractString, Options), + ok = pp_sophia_code(Ast, Options), + ok = pp_ast(Ast, Options), + TypedAst = aeso_ast_infer_types:infer(Ast, Options), + %% pp_types is handled inside aeso_ast_infer_types. + ok = pp_typed_ast(TypedAst, Options), + ICode = to_icode(TypedAst, Options), + TypeInfo = extract_type_info(ICode), + ok = pp_icode(ICode, Options), + Assembler = assemble(ICode, Options), + ok = pp_assembler(Assembler, Options), + ByteCodeList = to_bytecode(Assembler, Options), + ByteCode = << << B:8 >> || B <- ByteCodeList >>, + ok = pp_bytecode(ByteCode, Options), + {ok, #{byte_code => ByteCode, + compiler_version => version(), + contract_source => ContractString, + type_info => TypeInfo + }} catch %% The compiler errors. - error:{parse_errors,Errors} -> - {error,join_errors("Parse errors", Errors, fun(E) -> E end)}; - error:{type_errors,Errors} -> - {error,join_errors("Type errors", Errors, fun(E) -> E end)}; - error:{code_errors,Errors} -> - {error,join_errors("Code errors", Errors, - fun (E) -> io_lib:format("~p", [E]) end)} + error:{parse_errors, Errors} -> + {error, join_errors("Parse errors", Errors, fun(E) -> E end)}; + error:{type_errors, Errors} -> + {error, join_errors("Type errors", Errors, fun(E) -> E end)}; + error:{code_errors, Errors} -> + {error, join_errors("Code errors", Errors, + fun (E) -> io_lib:format("~p", [E]) end)} %% General programming errors in the compiler just signal error. end. @@ -99,35 +99,35 @@ join_errors(Prefix, Errors, Pfun) -> when Type :: term(). check_call(ContractString, Options) -> try - Ast = parse(ContractString, Options), - ok = pp_sophia_code(Ast, Options), - ok = pp_ast(Ast, Options), - TypedAst = aeso_ast_infer_types:infer(Ast, [permissive_address_literals]), - {ok, {FunName, {fun_t, _, _, ArgTypes, RetType}}} = get_call_type(TypedAst), - ok = pp_typed_ast(TypedAst, Options), - Icode = to_icode(TypedAst, Options), - ArgVMTypes = [ aeso_ast_to_icode:ast_typerep(T, Icode) || T <- ArgTypes ], - RetVMType = case RetType of - {id, _, "_"} -> any; - _ -> aeso_ast_to_icode:ast_typerep(RetType, Icode) - end, - ok = pp_icode(Icode, Options), - #{ functions := Funs } = Icode, - ArgIcode = get_arg_icode(Funs), - ArgTerms = [ icode_to_term(T, Arg) || - {T, Arg} <- lists:zip(ArgVMTypes, ArgIcode) ], - {ok, FunName, {ArgVMTypes, RetVMType}, ArgTerms} + Ast = parse(ContractString, Options), + ok = pp_sophia_code(Ast, Options), + ok = pp_ast(Ast, Options), + TypedAst = aeso_ast_infer_types:infer(Ast, [permissive_address_literals]), + {ok, {FunName, {fun_t, _, _, ArgTypes, RetType}}} = get_call_type(TypedAst), + ok = pp_typed_ast(TypedAst, Options), + Icode = to_icode(TypedAst, Options), + ArgVMTypes = [ aeso_ast_to_icode:ast_typerep(T, Icode) || T <- ArgTypes ], + RetVMType = case RetType of + {id, _, "_"} -> any; + _ -> aeso_ast_to_icode:ast_typerep(RetType, Icode) + end, + ok = pp_icode(Icode, Options), + #{ functions := Funs } = Icode, + ArgIcode = get_arg_icode(Funs), + ArgTerms = [ icode_to_term(T, Arg) || + {T, Arg} <- lists:zip(ArgVMTypes, ArgIcode) ], + {ok, FunName, {ArgVMTypes, RetVMType}, ArgTerms} catch - error:{parse_errors, Errors} -> - {error,join_errors("Parse errors", Errors, fun (E) -> E end)}; - error:{type_errors, Errors} -> - {error,join_errors("Type errors", Errors, fun (E) -> E end)}; - error:{badmatch,{error,missing_call_function}} -> - {error,join_errors("Type errors", ["missing __call function"], - fun (E) -> E end)}; - throw:Error -> %Don't ask - {error,join_errors("Code errors", [Error], - fun (E) -> io_lib:format("~p", [E]) end)} + error:{parse_errors, Errors} -> + {error, join_errors("Parse errors", Errors, fun (E) -> E end)}; + error:{type_errors, Errors} -> + {error, join_errors("Type errors", Errors, fun (E) -> E end)}; + error:{badmatch, {error, missing_call_function}} -> + {error, join_errors("Type errors", ["missing __call function"], + fun (E) -> E end)}; + throw:Error -> %Don't ask + {error, join_errors("Code errors", [Error], + fun (E) -> io_lib:format("~p", [E]) end)} end. -spec create_calldata(map(), string(), string()) -> @@ -279,9 +279,9 @@ parse_string(Text) -> parse_error(Pos, ErrorString) end. -parse_error({Line,Pos}, ErrorString) -> - Error = io_lib:format("line ~p, column ~p: ~s", [Line,Pos,ErrorString]), - error({parse_errors,[Error]}). +parse_error({Line, Pos}, ErrorString) -> + Error = io_lib:format("line ~p, column ~p: ~s", [Line, Pos, ErrorString]), + error({parse_errors, [Error]}). read_contract(Name) -> file:read_file(Name).