From ab150ce7f89afb6baf19c0b3518b74fcaf5a488a Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 27 Feb 2019 11:55:53 +0100 Subject: [PATCH] Generate the code from the makefile. Remove generated files. --- .circleci/config.yml | 2 +- .gitignore | 3 + Makefile | 16 +- include/aeb_fate_opcodes.hrl | 121 ----------- src/aeb_fate_code.erl | 389 ---------------------------------- src/aeb_fate_generate_ops.erl | 86 +++++--- src/aeb_fate_opcodes.erl | 363 ------------------------------- 7 files changed, 69 insertions(+), 911 deletions(-) delete mode 100644 include/aeb_fate_opcodes.hrl delete mode 100644 src/aeb_fate_code.erl delete mode 100644 src/aeb_fate_opcodes.erl diff --git a/.circleci/config.yml b/.circleci/config.yml index e34c31c..c1b8283 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -19,7 +19,7 @@ jobs: - dialyzer-cache-v1- - run: name: Build - command: rebar3 compile + command: make - run: name: Static Analysis command: rebar3 dialyzer diff --git a/.gitignore b/.gitignore index 4ad6576..385e93a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,6 @@ aeb_asm_scan.erl aeb_fate_asm_scan.erl _build/ aefateasm +include/aeb_fate_opcodes.hrl +src/aeb_fate_code.erl +src/aeb_fate_opcodes.erl diff --git a/Makefile b/Makefile index 1d04708..f4e9034 100644 --- a/Makefile +++ b/Makefile @@ -4,17 +4,29 @@ REBAR ?= rebar3 all: local -local: +local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl @$(REBAR) as local release -console: +console: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl @$(REBAR) as local shell clean: @$(REBAR) clean + rm -f src/aeb_fate_opcodes.erl + rm -f src/aeb_fate_code.erl + rm -f include/aeb_fate_opcodes.hrl distclean: clean @rm -rf _build/ test: local @$(REBAR) as local eunit + +ebin/aeb_fate_generate_ops.beam: src/aeb_fate_generate_ops.erl ebin + erlc -o $(dir $@) $< + +src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl: ebin/aeb_fate_generate_ops.beam + erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/ + +ebin: + mkdir ebin diff --git a/include/aeb_fate_opcodes.hrl b/include/aeb_fate_opcodes.hrl deleted file mode 100644 index 90f5b6a..0000000 --- a/include/aeb_fate_opcodes.hrl +++ /dev/null @@ -1,121 +0,0 @@ - -%% FATE opcodes --define('NOP' , 16#00). --define('RETURN' , 16#01). --define('CALL' , 16#02). --define('CALL_R' , 16#03). --define('CALL_T' , 16#04). --define('CALL_TR' , 16#05). --define('JUMP' , 16#06). --define('JUMPIF' , 16#07). --define('SWITCH' , 16#08). --define('PUSH' , 16#09). --define('DUP' , 16#0a). --define('POP' , 16#0b). --define('STORE' , 16#10). --define('ADD' , 16#11). --define('MUL' , 16#12). --define('SUB' , 16#13). --define('DIV' , 16#14). --define('MOD' , 16#15). --define('POW' , 16#16). --define('LT' , 16#17). --define('GT' , 16#18). --define('EQ' , 16#19). --define('ELT' , 16#1a). --define('EGT' , 16#1b). --define('NEQ' , 16#1c). --define('AND' , 16#1d). --define('OR' , 16#1e). --define('NOT' , 16#1f). --define('TUPLE' , 16#20). --define('ELEMENT' , 16#21). --define('MAP_EMPTY' , 16#22). --define('MAP_LOOKUP' , 16#23). --define('MAP_UPDATE' , 16#24). --define('MAP_DELETE' , 16#25). --define('MAP_MEMBER' , 16#26). --define('MAP_FROM_LIST' , 16#27). --define('NIL' , 16#28). --define('IS_NIL' , 16#29). --define('CONS' , 16#2a). --define('HD' , 16#2b). --define('TL' , 16#2c). --define('LENGTH' , 16#2d). --define('STR_EQ' , 16#2e). --define('STR_JOIN' , 16#2f). --define('ADDR_TO_STR' , 16#30). --define('STR_REVERSE' , 16#31). --define('INT_TO_ADDR' , 16#32). --define('VARIANT' , 16#33). --define('VARIANT_TEST' , 16#34). --define('VARIANT_ELEMENT', 16#35). --define('BITS_NONE' , 16#36). --define('BITS_ALL' , 16#37). --define('BITS_SET' , 16#38). --define('BITS_CLEAR' , 16#39). --define('BITS_TEST' , 16#3a). --define('BITS_SUM' , 16#3b). --define('BITS_OR' , 16#3c). --define('BITS_AND' , 16#3d). --define('BITS_DIFF' , 16#3e). --define('ADDRESS' , 16#3f). --define('BALANCE' , 16#40). --define('ORIGIN' , 16#41). --define('CALLER' , 16#42). --define('GASPRICE' , 16#43). --define('BLOCKHASH' , 16#44). --define('BENEFICIARY' , 16#45). --define('TIMESTAMP' , 16#46). --define('NUMBER' , 16#47). --define('DIFFICULTY' , 16#48). --define('GASLIMIT' , 16#49). --define('GAS' , 16#4a). --define('LOG0' , 16#4b). --define('LOG1' , 16#4c). --define('LOG2' , 16#4d). --define('LOG3' , 16#4e). --define('LOG4' , 16#4f). --define('ABORT' , 16#50). --define('EXIT' , 16#51). --define('DEACTIVATE' , 16#52). --define('INC' , 16#53). --define('DEC' , 16#54). --define('INT_TO_STR' , 16#55). --define('SPEND' , 16#56). --define('ORACLE_REGISTER', 16#57). --define('ORACLE_QUERY' , 16#58). --define('ORACLE_RESPOND' , 16#59). --define('ORACLE_EXTEND' , 16#5a). --define('ORACLE_GET_ANSWER', 16#5b). --define('ORACLE_GET_QUESTION', 16#5c). --define('ORACLE_QUERY_FEE', 16#5d). --define('AENS_RESOLVE' , 16#5e). --define('AENS_PRECLAIM' , 16#5f). --define('AENS_CLAIM' , 16#60). --define('AENS_UPDATE' , 16#61). --define('AENS_TRANSFER' , 16#62). --define('AENS_REVOKE' , 16#63). --define('ECVERIFY' , 16#64). --define('SHA3' , 16#65). --define('SHA256' , 16#66). --define('BLAKE2B' , 16#67). --define('RETURNR' , 16#68). --define('MAP_LOOKUPD' , 16#69). --define('SWITCH_V2' , 16#6a). --define('SWITCH_V3' , 16#6b). --define('SWITCH_VN' , 16#6c). --define('BITS_ALL_N' , 16#6d). --define('BITS_NONEA' , 16#6e). --define('BITS_ALLA' , 16#6f). --define('DUPA' , 16#70). --define('INCA' , 16#71). --define('DECA' , 16#72). --define('POPA' , 16#73). - - --define('FUNCTION' , 16#fe). --define('EXTEND' , 16#ff). - --define( COMMENT(X), {comment, X}). - diff --git a/src/aeb_fate_code.erl b/src/aeb_fate_code.erl deleted file mode 100644 index 68bd94a..0000000 --- a/src/aeb_fate_code.erl +++ /dev/null @@ -1,389 +0,0 @@ -%% Provide constructor functuions for Fate instructions. -%% Provide types and documentation for Fate instructions. - - --module(aeb_fate_code). - --include_lib("aebytecode/include/aeb_fate_data.hrl"). - --type fate_arg_immediate(T) :: {immediate, T}. --type fate_arg_var() :: {var, integer()}. --type fate_arg_arg() :: {arg, integer()}. --type fate_arg_stack() :: {stack, integer()}. --type fate_arg() :: fate_arg_immediate() - | fate_arg_var() - | fate_arg_arg() - | fate_arg_stack(). - --type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}. - --type fate_return() :: 'RETURN'. --type fate_returnr() :: {'RETURNR', fate_arg()}. --type fate_call() :: {'CALL', - fate_arg_immediate(aeb_fate_data:fate_string())}. --type fate_call_t() :: {'CALL_T', - fate_arg_immediate(aeb_fate_data:fate_string())}. --type fate_call_r() :: {'CALL_R', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_string())}. --type fate_call_tr() :: {'CALL_TR', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_string())}. --type fate_jump() :: {'JUMP', - fate_arg_immediate(aeb_fate_data:fate_integer())}. --type fate_jumpif() :: {'JUMPIF', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_integer())}. --type fate_switch_v2() :: {'SWITCH_V2', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_integer()), - fate_arg_immediate(aeb_fate_data:fate_integer())}. --type fate_switch_v3() :: {'SWITCH_V3', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_integer()), - fate_arg_immediate(aeb_fate_data:fate_integer()), - fate_arg_immediate(aeb_fate_data:fate_integer())}. --type fate_switch_vn() :: {'SWITCH_VN', fate_arg(), - fate_arg_immediate(aeb_fate_data:fate_integer()), - [fate_arg_immediate(aeb_fate_data:fate_integer())]}. --type fate_push() :: {'PUSH', fate_arg()}. --type fate_inca() :: 'INCA'. --type fate_inc() :: {'INC', fate_arg()}. --type fate_deca() :: 'DECA'. --type fate_dec() :: {'DEC', fate_arg()}. - - --type fate_code() :: fate_return() - | fate_returnr() - | fate_call() - | fate_call_t() - | fate_call_r() - | fate_call_tr() - | fate_jump() - | fate_jumpif() - | fate_switch_v2() - | fate_switch_v3() - | fate_switch_vn() - | fate_push() - | fate_inca() - | fate_inc() - | fate_deca() - | fate_dec() - . - --export_type([ fate_code/0 - - , fate_arg/0 - ]). - --export([ return/0 - , return/1 - , call/1 - , call_t/1 - , call_r/2 - , call_tr/2 - , jump/1 - , jumpif/2 - , switch/3 - , switch/4 - , switch_n/2 - , push/1 - , inc/0 - , inc/1 - , dec/0 - , dec/1 - , add/3 - , sub/3 - , mul/3 - , divide/3 - , modulo/3 - , pow/3 - , lt/3 - , gt/3 - , elt/3 - , egt/3 - , eq/3 - , neq/3 - , and_op/3 - , or_op/3 - , not_op/2 - , tuple/1 - , element_op/4 - , map_empty/1 - , map_lookup/3 - , map_lookup/4 - , map_update/4 - , map_member/3 - , map_from_list/2 - , nil/1 - , is_nil/2 - , cons/3 - , hd/2 - , tl/2 - , length/2 - , str_eq/3 - , str_join/3 - , int_to_str/2 - , addr_to_str/2 - , str_reverse/2 - , int_to_addr/2 - , variant_test/3 - , variant_element/3 - , variant/4 - , bits_none/0 - , bits_none/1 - , bits_all/0 - , bits_all/1 - , bits_all_n/2 - , bits_set/3 - , bits_clear/3 - , bits_test/3 - , bits_sum/2 - , bits_or/3 - , bits_and/3 - , bits_diff/3 - , dup/0 - , dup/1 - , pop/0 - , store/2 - , nop/0 - ]). - --define(i(__X__), {immediate, __X__ }). - --spec return() -> fate_return(). -return() -> - 'RETURN'. - --spec return(fate_arg()) -> fate_returnr(). -return(Arg) -> - {'RETURNR', Arg}. - --spec call(aeb_fate_data:fate_string()) -> fate_call(). -call(Function) when ?IS_FATE_STRING(Function)-> - {'CALL', ?i(Function) }. - --spec call_t(aeb_fate_data:fate_string()) -> fate_call_t(). -call_t(Function) when ?IS_FATE_STRING(Function) -> - {'CALL_T', ?i(Function)}. - --spec call_r(fate_arg(), aeb_fate_data:fate_string()) -> fate_call_r(). -call_r(Contract, Function) when ?IS_FATE_STRING(Function) -> - {'CALL_R', Contract, ?i(Function)}. - --spec call_tr(fate_arg(), aeb_fate_data:fate_string()) -> fate_call_tr(). -call_tr(Contract, Function) when ?IS_FATE_STRING(Function) -> - {'CALL_TR', Contract, ?i(Function)}. - --spec jump(aeb_fate_data:fate_integer()) -> fate_jump(). -jump(BB) when ?IS_FATE_INTEGER(BB) -> - {'JUMP', ?i(BB)}. - --spec jumpif(fate_arg(), aeb_fate_data:fate_integer()) -> fate_jumpif(). -jumpif(Arg, BB) when ?IS_FATE_INTEGER(BB) -> - {'JUMPIF', Arg, ?i(BB)}. - --spec switch(fate_arg(), - aeb_fate_data:fate_integer(), - aeb_fate_data:fate_integer()) - -> fate_switch_v2(). -switch(Arg, BB1, BB2) when ?IS_FATE_INTEGER(BB1), - ?IS_FATE_INTEGER(BB2) -> - {'SWITCH_V2', Arg, ?i(BB1), ?i(BB2)}. - --spec switch(fate_arg(), - aeb_fate_data:fate_integer(), - aeb_fate_data:fate_integer(), - aeb_fate_data:fate_integer()) - -> fate_switch_v3(). -switch(Arg, BB1, BB2, BB3) when ?IS_FATE_INTEGER(BB1), - ?IS_FATE_INTEGER(BB2), - ?IS_FATE_INTEGER(BB3) -> - {'SWITCH_V3', Arg, ?i(BB1), ?i(BB2), ?i(BB3)}. - --spec switch_n(fate_arg(), - [aeb_fate_data:fate_integer()]) - -> fate_switch_vn(). -switch_n(Arg, BBS) when is_list(BBS) -> - N = length(BBS), - {'SWITCH_VN', Arg, ?i(N), [?i(BB) || BB <- BBS]}. - --spec push(fate_arg()) -> fate_push(). -push(Arg) -> - {'PUSH', Arg}. - --spec inc() -> fate_inca(). -inc() -> - 'INCA'. - --spec inc(fate_arg()) -> fate_inc(). -inc(Arg) -> - {'INC', Arg}. - --spec dec() -> fate_deca(). -dec() -> - 'DECA'. - --spec dec(fate_arg()) -> fate_dec(). -dec(Arg) -> - {'DEC', Arg}. - -add(Dest, Left, Right) -> - {'ADD', Dest, Left, Right}. - -sub(Dest, Left, Right) -> - {'SUB', Dest, Left, Right}. - -mul(Dest, Left, Right) -> - {'MUL', Dest, Left, Right}. - -divide(Dest, Left, Right) -> - {'DIV', Dest, Left, Right}. - -modulo(Dest, Left, Right) -> - {'MOD', Dest, Left, Right}. - -pow(Dest, Left, Right) -> - {'POW', Dest, Left, Right}. - -lt(Dest, Left, Right) -> - {'LT', Dest, Left, Right}. - -gt(Dest, Left, Right) -> - {'GT', Dest, Left, Right}. - -elt(Dest, Left, Right) -> - {'ELT', Dest, Left, Right}. - -egt(Dest, Left, Right) -> - {'EGT', Dest, Left, Right}. - -eq(Dest, Left, Right) -> - {'EQ', Dest, Left, Right}. - -neq(Dest, Left, Right) -> - {'NEQ', Dest, Left, Right}. - -and_op(Dest, Left, Right) -> - {'AND', Dest, Left, Right}. - -or_op(Dest, Left, Right) -> - {'OR', Dest, Left, Right}. - -not_op(Dest, Arg) -> - {'NOT', Dest, Arg}. - -tuple(Size) when ?IS_FATE_INTEGER(Size) -> - {'TUPLE', ?i(Size)}. - -element_op(Type, Dest, N, T) -> - {'ELEMENT', Type, Dest, N, T}. - -map_empty(Dest) -> - {'MAP_EMPTY', Dest}. - -map_lookup(Dest, Map, Key) -> - {'MAP_LOOKUP', Dest, Map, Key}. - -map_lookup(Dest, Map, Key, Default) -> - {'MAP_LOOKUPD', Dest, Map, Key, Default}. - -map_update(Dest, Map, Key, Value) -> - {'MAP_UPDATE', Dest, Map, Key, Value}. - -map_member(Dest, Map, Key) -> - {'MAP_MEMBER', Dest, Map, Key}. - -map_from_list(Dest, List) -> - {'MAP_MEMBER', Dest, List}. - -nil(Dest) -> - {'NIL', Dest}. - -is_nil(Dest, List) -> - {'IS_NIL', Dest, List}. - -cons(Dest, Hd, Tl) -> - {'CONS', Dest, Hd, Tl}. - -hd(Dest, List) -> - {'HD', Dest, List}. - -tl(Dest, List) -> - {'TL', Dest, List}. - -length(Dest, List) -> - {'LENGTH', Dest, List}. - -str_eq(Dest, Str1, Str2) -> - {'STR_EQ', Dest, Str1, Str2}. - -str_join(Dest, Str1, Str2) -> - {'STR_JOIN', Dest, Str1, Str2}. - -int_to_str(Dest, Str) -> - {'INT_TO_STR', Dest, Str}. - -addr_to_str(Dest, Str) -> - {'ADDR_TO_STR', Dest, Str}. - -str_reverse(Dest, Str) -> - {'STR_REVERSE', Dest, Str}. - -int_to_addr(Dest, Str) -> - {'INT_TO_ADDR', Dest, Str}. - -variant_test(Dest, Variant, Tag) -> - {'VARIANT_TEST', Dest, Variant, Tag}. - -variant_element( Dest, Variant, Index) -> - {'VARIANT_ELEMENT', Dest, Variant, Index}. - -variant(Dest, SizeA, TagA, ElementsA) -> - {'VARIANT', Dest, SizeA, TagA, ElementsA}. - -bits_none() -> - 'BITS_NONEA'. - -bits_none(To) -> - {'BITS_NONE', To}. - -bits_all() -> - 'BITS_ALLA'. - -bits_all(To) -> - {'BITS_ALL', To}. - -bits_all_n(To, N) -> - {'BITS_ALL_N', To, N}. - -bits_set(To, Bits, Bit) -> - {'BITS_SET', To, Bits, Bit}. - -bits_clear(To, Bits, Bit) -> - {'BITS_CLEAR', To, Bits, Bit}. - -bits_test(To, Bits, Bit) -> - {'BITS_TEST', To, Bits, Bit}. - -bits_sum(To, Bits) -> - {'BITS_SUM', To, Bits}. - -bits_or(To, Bits, Bit) -> - {'BITS_OR', To, Bits, Bit}. - -bits_and(To, Bits, Bit) -> - {'BITS_AND', To, Bits, Bit}. - -bits_diff(To, Bits, Bit) -> - {'BITS_DIFF', To, Bits, Bit}. - -dup() -> - 'DUPA'. - -dup(N) when ?IS_FATE_INTEGER(N) -> - {'DUP', ?i(N)}. - -pop() -> - 'POP'. - -store(Var, What) -> - {'STORE', Var, What}. - -nop() -> - 'NOP'. diff --git a/src/aeb_fate_generate_ops.erl b/src/aeb_fate_generate_ops.erl index 259da48..0fc740c 100644 --- a/src/aeb_fate_generate_ops.erl +++ b/src/aeb_fate_generate_ops.erl @@ -1,34 +1,33 @@ - - -module(aeb_fate_generate_ops). --export([generate/0]). +-export([ gen_and_halt/1 + , generate/0]). --define(ati(__X__), {immediate, __X__}). --define(atv(__X__), {var, __X__}). --define(ata(__X__), {arg, __X__}). --define(ats(__X__), {stack, __X__}). - --define(ta(), "fate_arg()"). --define(ti(__X__), "fate_arg_immediate(" __X__ ")"). --define(ts, "aeb_fate_data:fate_string()"). +gen_and_halt([SrcDirArg, IncludeDirArg]) -> + generate(atom_to_list(SrcDirArg), + atom_to_list(IncludeDirArg)), + halt(). generate() -> + generate("src/", "include/"). + +generate(Src, Include) -> Ops = gen(ops_defs()), - io:format("ops: ~p\n", [Ops]), - HrlFile = "aeb_new_fate_opcodes.hrl", + %% io:format("ops: ~p\n", [Ops]), + HrlFile = Include ++ "aeb_fate_opcodes.hrl", generate_header_file(HrlFile, Ops), - generate_opcodes_ops(aeb_new_fate_opcodes, HrlFile, Ops), - generate_code_ops(aeb_new_fate_code, Ops). + generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops), + generate_code_ops(aeb_fate_code, Src, Ops). + ops_defs() -> %% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation - [ { 'NOP', 16#00, 0, false, 1, atomic, nop, "The no op. does nothing."} - , { 'RETURN', 16#01, 0, true, 2, atomic, return, "Return from function call pop stack to arg0."} - , { 'RETURNR', 16#68, 1, true, 2, [a], returnr, "Return from function call pop stack to arg0."} + [ { 'NOP', 16#f0, 0, false, 1, atomic, nop, "The no op. does nothing."} + , { 'RETURN', 16#00, 0, true, 2, atomic, return, "Return from function call pop stack to arg0."} + , { 'RETURNR', 16#01, 1, true, 2, [a], returnr, "Return from function call pop stack to arg0."} , { 'CALL', 16#02, 1, true, 4, [is], call, "Call given function with args on stack."} - , { 'CALL_T', 16#04, 1, true, 4, [is], call_t, "Tail call to given function."} , { 'CALL_R', 16#03, 2, true, 8, [a, is], call_r, "Remote call to given contract and function."} + , { 'CALL_T', 16#04, 1, true, 4, [is], call_t, "Tail call to given function."} , { 'CALL_TR', 16#05, 2, true, 8, [a, is], call_tr, "Remote tail call to given contract and function."} , { 'JUMP', 16#06, 1, true, 3, [ii], jump, "Jump to a basic block."} , { 'JUMPIF', 16#07, 2, true, 4, [a, ii], jumpif, "Conditional jump to a basic block."} @@ -56,20 +55,21 @@ ops_defs() -> , { 'OR', 16#1e, 3, false, 3, [a,a,a], or_op, "Arg0 := Arg1 or Arg2."} , { 'NOT', 16#1f, 2, false, 3, [a,a], not_op, "Arg0 := not Arg1."} , { 'TUPLE', 16#20, 1, false, 3, [ii], tuple, "Create a tuple of size = Arg0. Elements on stack."} - , { 'ELEMET', 16#21, 4, false, 3, [t,a,a,a], element_op, "Arg1 := element(Arg2, Arg3). The element should be of type Arg1"} + , { 'ELEMENT', 16#21, 4, false, 3, [t,a,a,a], element_op, "Arg1 := element(Arg2, Arg3). The element should be of type Arg1"} , { 'MAP_EMPTY',16#22, 1, false, 3, [a], map_empty, "Arg0 := #{}."} , { 'MAP_LOOKUP',16#23, 3, false, 3, [a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1."} , { 'MAP_LOOKUPD',16#69, 4, false, 3, [a, a, a, a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1 if key exists in map otherwise Arg0 := Arg3."} , { 'MAP_UPDATE',16#24, 4, false, 3, [a, a, a, a], map_update, "Arg0 := update key Arg2 in map Arg1 with value Arg3."} , { 'MAP_DELETE',16#25, 3, false, 3, [a, a, a], map_delete, "Arg0 := delete key Arg2 from map Arg1."} , { 'MAP_MEMBER',16#26, 3, false, 3, [a, a, a], map_member, "Arg0 := true if key Arg2 is in map Arg1."} + , { 'MAP_FROM_LIST',16#27, 2, false, 3, [a, a], map_from_list, "Arg0 := make a map from (key, value) list in Arg1."} , { 'NIL', 16#28, 1, false, 3, [a], nil, "Arg0 := []."} , { 'IS_NIL', 16#29, 2, false, 3, [a, a], is_nil, "Arg0 := true if Arg1 == []."} , {'CONS', 16#2a, 3, false, 3, [a, a, a], cons, "Arg0 := [Arg1|Arg2]."} , {'HD', 16#2b, 2, false, 3, [a, a], hd, "Arg0 := head of list Arg1."} , {'TL', 16#2c, 2, false, 3, [a, a], tl, "Arg0 := tail of list Arg1."} , {'LENGTH', 16#2d, 2, false, 3, [a, a], length, "Arg0 := length of list Arg1."} - + , {'STR_EQ', 16#2e, 3, false, 3, [a, a, a], str_eq, "Arg0 := true iff the strings Arg1 and Arg2 are the same."} , {'STR_JOIN', 16#2f, 3, false, 3, [a, a, a], str_join, "Arg0 := string Arg1 followed by string Arg2."} , {'INT_TO_STR', 16#55, 2, false, 3, [a, a], int_to_str, "Arg0 := turn integer Arg1 into a string."} @@ -78,7 +78,7 @@ ops_defs() -> , {'INT_TO_ADDR', 16#32, 2, false, 3, [a, a], int_to_addr, "Arg0 := turn integer Arg1 into an address."} , {'VARIANT', 16#33, 4, false, 3, [a, a, a, a], variant, "Arg0 := create a variant of size Arg1 with the tag Arg2 (Arg2 < Arg1) and take Arg3 elements from the stack."} , {'VARIANT_TEST', 16#34,3, false, 3, [a, a, a], variant_test,"Arg0 := true if variant Arg1 has the tag Arg2."} - , {'VARIANT_ELEMENT',16#35,3,false, 3, [a, a, a], variant_element,"Arg0 := element number Arg2 from variant Arg1."} + , {'VARIANT_ELEMNT',16#35,3,false, 3, [a, a, a], variant_element,"Arg0 := element number Arg2 from variant Arg1."} , {'BITS_NONEA', 16#6e, 0, false, 3, atomic, bits_none, "accumulator := empty bitmap."} , {'BITS_NONE', 16#36, 1, false, 3, [a], bits_none, "Arg0 := empty bitmap."} , {'BITS_ALLA', 16#6f, 0, false, 3, atomic, bits_all, "accumulator := full bitmap."} @@ -94,6 +94,21 @@ ops_defs() -> , {'DUP', 16#0a, 1, false, 3, [a], dup, "push Arg0 stack pos on top of stack."} , {'POP', 16#0b, 1, false, 3, [a], pop, "Arg0 := top of stack."} , {'STORE', 16#10, 2, false, 3, [a, a], store, "Arg0 := Arg1."} + %% TODO: Check the documentation and update it. + , {'ADDRESS', 16#3f, 1, false, 3, [a], address, "Arg0 := The current contract address."} + , {'BALANCE', 16#3f, 1, false, 3, [a], balance, "Arg0 := The current contract address."} + , {'ORIGIN', 16#40, 1, false, 3, [a], origin, "Arg0 := Address of contract called by the call transaction."} + , {'CALLER', 16#41, 1, false, 3, [a], caller, "Arg0 := The address that signed the call transaction."} + , {'GASPRICE', 16#42, 1, false, 3, [a], gasprice, "Arg0 := The current gas price."} + , {'BLOCKHASH', 16#43, 1, false, 3, [a], blockhash, "Arg0 := The current blockhash."} %% TODO: Do we support has at height? + , {'BENEFICIARY',16#44, 1, false, 3, [a], beneficiary, "Arg0 := The address of the current beneficiary."} + , {'TIMESTAMP', 16#45, 1, false, 3, [a], timestamp, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."} + , {'NUMBER', 16#46, 1, false, 3, [a], number, "Arg0 := The block height."} + , {'DIFFICULTY',16#47, 1, false, 3, [a], difficulty, "Arg0 := The current difficulty."} + , {'GASLIMIT', 16#48, 1, false, 3, [a], gaslimit, "Arg0 := The current gaslimit."} + , {'GAS', 16#49, 1, false, 3, [a], gas, "Arg0 := The amount of gas left."} + , {'ABORT', 16#4f, 1, false, 3, [a], abort, "Abort execution (dont use all gas) with error message in Arg0."} + , {'EXIT', 16#4e, 1, false, 3, [a], exit, "Abort execution (use upp all gas) with error message in Arg0."} ]. @@ -102,10 +117,13 @@ generate_header_file(Filename, Ops) -> Defines = lists:flatten([gen_defines(Op) || Op <- Ops]), io:format(File, "~s", [prelude("Provides opcode defines.\n")]), io:format(File, "%% FATE opcodes\n~s", [Defines]), + io:format(File, "~s", + ["-define('FUNCTION' , 16#fe).\n" + "-define('EXTEND' , 16#ff).\n\n"]), file:close(File). -generate_opcodes_ops(Modulename, HrlFile, Ops) -> - Filename = atom_to_list(Modulename) ++ ".erl", +generate_opcodes_ops(Modulename, HrlFile, SrcDir, Ops) -> + Filename = SrcDir ++ atom_to_list(Modulename) ++ ".erl", {ok, File} = file:open(Filename, [write]), Mnemonic = lists:flatten([gen_mnemonic(Op) || Op <- Ops]), @@ -135,8 +153,8 @@ generate_opcodes_ops(Modulename, HrlFile, Ops) -> file:close(File). -generate_code_ops(Modulename, Ops) -> - Filename = atom_to_list(Modulename) ++ ".erl", +generate_code_ops(Modulename, SrcDir, Ops) -> + Filename = SrcDir ++ atom_to_list(Modulename) ++ ".erl", {ok, File} = file:open(Filename, [write]), Types = lists:flatten([gen_type(Op) || Op <- Ops]), @@ -163,7 +181,6 @@ generate_code_ops(Modulename, Ops) -> " | fate_arg_stack().\n\n" "-type fate_arg_immediate() :: {immediate, aeb_fate_data:fate_type()}.\n" , []), - io:format(File, "~s", [Types]), io:format(File, "-type fate_code() :: ~s\n~s .\n\n", [FirstType, FateTypes]), @@ -172,7 +189,6 @@ generate_code_ops(Modulename, Ops) -> io:format(File, "~s\n", [Constructors]), io:format(File, "foo() -> \"A temp hack.\".\n", []), - file:close(File). @@ -222,7 +238,7 @@ gen_arg_type_specs([t | Args]) -> "aeb_fate_data:fate_type_type(), " ++ gen_arg_ gen_arg_names(_, []) -> []; gen_arg_names(N, [_]) -> io_lib:format("Arg~w", [N]); -gen_arg_names(N, [_|Args]) -> +gen_arg_names(N, [_|Args]) -> io_lib:format("Arg~w, ", [N]) ++ gen_arg_names(N+1, Args). gen_arg_uses(_, []) -> @@ -232,15 +248,15 @@ gen_arg_uses(N, [is]) -> io_lib:format("{immediate, Arg~w}", [N]); gen_arg_uses(N, [ii]) -> io_lib:format("{immediate, Arg~w}", [N]); gen_arg_uses(N, [li]) -> io_lib:format("[{immediate, I} || I <- Arg~w]", [N]); gen_arg_uses(N, [t]) -> io_lib:format("Arg~w", [N]); -gen_arg_uses(N, [a | Args]) -> +gen_arg_uses(N, [a | Args]) -> io_lib:format("Arg~w, ", [N]) ++ gen_arg_uses(N+1, Args); -gen_arg_uses(N, [is | Args]) -> +gen_arg_uses(N, [is | Args]) -> io_lib:format("{immediate, Arg~w}, ", [N]) ++ gen_arg_uses(N+1, Args); -gen_arg_uses(N, [ii | Args]) -> +gen_arg_uses(N, [ii | Args]) -> io_lib:format("{immediate, Arg~w}, ", [N]) ++ gen_arg_uses(N+1, Args); -gen_arg_uses(N, [li | Args]) -> +gen_arg_uses(N, [li | Args]) -> io_lib:format("[{immediate, I} || I <- Arg~w], ", [N]) ++ gen_arg_uses(N+1, Args); -gen_arg_uses(N, [t | Args]) -> +gen_arg_uses(N, [t | Args]) -> io_lib:format("Arg~w, ", [N]) ++ gen_arg_uses(N+1, Args). @@ -248,7 +264,7 @@ ops_exports(Module, HrlFile, Exports) -> lists:flatten(io_lib:format( "-module(~w).\n\n" "-export([ ~s ]).\n\n" - "-include_lib(\"aebytecode/include/" ++ HrlFile ++"\").\n\n" + "-include_lib(\"aebytecode/" ++ HrlFile ++"\").\n\n" "%%====================================================================\n" "%% API\n" "%%====================================================================\n", diff --git a/src/aeb_fate_opcodes.erl b/src/aeb_fate_opcodes.erl deleted file mode 100644 index 84d93f7..0000000 --- a/src/aeb_fate_opcodes.erl +++ /dev/null @@ -1,363 +0,0 @@ -%%%------------------------------------------------------------------- -%%% @copyright (C) 2019, Aeternity Anstalt -%%% @doc -%%% Opcodes -%%% @end -%%%------------------------------------------------------------------- - --module(aeb_fate_opcodes). - --export([ args/1 - , end_bb/1 - , mnemonic/1 - , m_to_op/1 - , opcode/1 - ]). - --include_lib("aebytecode/include/aeb_fate_opcodes.hrl"). - - -%%==================================================================== -%% API -%%==================================================================== - -opcode(X) when X >= 0, X =< 255 -> X; -opcode({comment,X}) -> ?COMMENT(X). - -mnemonic(?NOP) -> 'NOP' ; -mnemonic(?RETURN) -> 'RETURN' ; -mnemonic(?CALL) -> 'CALL' ; -mnemonic(?CALL_R) -> 'CALL_R' ; -mnemonic(?CALL_T) -> 'CALL_T' ; -mnemonic(?CALL_TR) -> 'CALL_TR' ; -mnemonic(?JUMP) -> 'JUMP' ; -mnemonic(?JUMPIF) -> 'JUMPIF' ; -mnemonic(?PUSH) -> 'PUSH' ; -mnemonic(?DUP) -> 'DUP' ; -mnemonic(?DUPA) -> 'DUPA' ; -mnemonic(?POP) -> 'POP' ; -mnemonic(?STORE) -> 'STORE' ; -mnemonic(?ADD) -> 'ADD' ; -mnemonic(?MUL) -> 'MUL' ; -mnemonic(?SUB) -> 'SUB' ; -mnemonic(?DIV) -> 'DIV' ; -mnemonic(?MOD) -> 'MOD' ; -mnemonic(?POW) -> 'POW' ; -mnemonic(?LT) -> 'LT' ; -mnemonic(?GT) -> 'GT' ; -mnemonic(?EQ) -> 'EQ' ; -mnemonic(?ELT) -> 'ELT' ; -mnemonic(?EGT) -> 'EGT' ; -mnemonic(?NEQ) -> 'NEQ' ; -mnemonic(?AND) -> 'AND' ; -mnemonic(?OR) -> 'OR' ; -mnemonic(?NOT) -> 'NOT' ; -mnemonic(?TUPLE) -> 'TUPLE' ; -mnemonic(?ELEMENT) -> 'ELEMENT' ; -mnemonic(?MAP_EMPTY) -> 'MAP_EMPTY' ; -mnemonic(?MAP_LOOKUP) -> 'MAP_LOOKUP' ; -mnemonic(?MAP_UPDATE) -> 'MAP_UPDATE' ; -mnemonic(?MAP_DELETE) -> 'MAP_DELETE' ; -mnemonic(?MAP_MEMBER) -> 'MAP_MEMBER' ; -mnemonic(?MAP_FROM_LIST) -> 'MAP_FROM_LIST' ; -mnemonic(?NIL) -> 'NIL' ; -mnemonic(?IS_NIL) -> 'IS_NIL' ; -mnemonic(?CONS) -> 'CONS' ; -mnemonic(?HD) -> 'HD' ; -mnemonic(?TL) -> 'TL' ; -mnemonic(?LENGTH) -> 'LENGTH' ; -mnemonic(?STR_EQ) -> 'STR_EQ' ; -mnemonic(?STR_JOIN) -> 'STR_JOIN' ; -mnemonic(?ADDR_TO_STR) -> 'ADDR_TO_STR' ; -mnemonic(?STR_REVERSE) -> 'STR_REVERSE' ; -mnemonic(?INT_TO_ADDR) -> 'INT_TO_ADDR' ; -mnemonic(?VARIANT) -> 'VARIANT' ; -mnemonic(?VARIANT_TEST) -> 'VARIANT_TEST' ; -mnemonic(?VARIANT_ELEMENT) -> 'VARIANT_ELEMENT' ; -mnemonic(?BITS_NONE) -> 'BITS_NONE' ; -mnemonic(?BITS_NONEA) -> 'BITS_NONEA' ; -mnemonic(?BITS_ALL) -> 'BITS_ALL' ; -mnemonic(?BITS_ALLA) -> 'BITS_ALLA' ; -mnemonic(?BITS_SET) -> 'BITS_SET' ; -mnemonic(?BITS_CLEAR) -> 'BITS_CLEAR' ; -mnemonic(?BITS_TEST) -> 'BITS_TEST' ; -mnemonic(?BITS_SUM) -> 'BITS_SUM' ; -mnemonic(?BITS_OR) -> 'BITS_OR' ; -mnemonic(?BITS_AND) -> 'BITS_AND' ; -mnemonic(?BITS_DIFF) -> 'BITS_DIFF' ; -mnemonic(?ADDRESS) -> 'ADDRESS' ; -mnemonic(?BALANCE) -> 'BALANCE' ; -mnemonic(?ORIGIN) -> 'ORIGIN' ; -mnemonic(?CALLER) -> 'CALLER' ; -mnemonic(?GASPRICE) -> 'GASPRICE' ; -mnemonic(?BLOCKHASH) -> 'BLOCKHASH' ; -mnemonic(?BENEFICIARY) -> 'BENEFICIARY' ; -mnemonic(?TIMESTAMP) -> 'TIMESTAMP' ; -mnemonic(?NUMBER) -> 'NUMBER' ; -mnemonic(?DIFFICULTY) -> 'DIFFICULTY' ; -mnemonic(?GASLIMIT) -> 'GASLIMIT' ; -mnemonic(?GAS) -> 'GAS' ; -mnemonic(?LOG0) -> 'LOG0' ; -mnemonic(?LOG1) -> 'LOG1' ; -mnemonic(?LOG2) -> 'LOG2' ; -mnemonic(?LOG3) -> 'LOG3' ; -mnemonic(?LOG4) -> 'LOG4' ; -mnemonic(?ABORT) -> 'ABORT' ; -mnemonic(?EXIT) -> 'EXIT' ; -mnemonic(?DEACTIVATE) -> 'DEACTIVATE' ; -mnemonic(?INC) -> 'INC' ; -mnemonic(?DEC) -> 'DEC' ; -mnemonic(?INCA) -> 'INCA' ; -mnemonic(?DECA) -> 'DECA' ; -mnemonic(?INT_TO_STR) -> 'INT_TO_STR' ; -mnemonic(?SPEND) -> 'SPEND' ; -mnemonic(?ORACLE_REGISTER) -> 'ORACLE_REGISTER' ; -mnemonic(?ORACLE_QUERY) -> 'ORACLE_QUERY' ; -mnemonic(?ORACLE_RESPOND) -> 'ORACLE_RESPOND' ; -mnemonic(?ORACLE_EXTEND) -> 'ORACLE_EXTEND' ; -mnemonic(?ORACLE_GET_ANSWER) -> 'ORACLE_GET_ANSWER' ; -mnemonic(?ORACLE_GET_QUESTION) -> 'ORACLE_GET_QUESTION' ; -mnemonic(?ORACLE_QUERY_FEE) -> 'ORACLE_QUERY_FEE' ; -mnemonic(?AENS_RESOLVE) -> 'AENS_RESOLVE' ; -mnemonic(?AENS_PRECLAIM) -> 'AENS_PRECLAIM' ; -mnemonic(?AENS_CLAIM) -> 'AENS_CLAIM' ; -mnemonic(?AENS_UPDATE) -> 'AENS_UPDATE' ; -mnemonic(?AENS_TRANSFER) -> 'AENS_TRANSFER' ; -mnemonic(?AENS_REVOKE) -> 'AENS_REVOKE' ; -mnemonic(?ECVERIFY) -> 'ECVERIFY' ; -mnemonic(?SHA3) -> 'SHA3' ; -mnemonic(?SHA256) -> 'SHA256' ; -mnemonic(?BLAKE2B) -> 'BLAKE2B' ; -mnemonic(?RETURNR) -> 'RETURNR' ; -mnemonic(?MAP_LOOKUPD) -> 'MAP_LOOKUPD' ; -mnemonic(?SWITCH_V2) -> 'SWITCH_V2' ; -mnemonic(?SWITCH_V3) -> 'SWITCH_V3' ; -mnemonic(?SWITCH_VN) -> 'SWITCH_VN' ; -mnemonic(?BITS_ALL_N) -> 'BITS_ALL_N' ; -mnemonic(?FUNCTION) -> 'FUNCTION' ; -mnemonic(?EXTEND) -> 'EXTEND'. - - -m_to_op('NOP') -> ?NOP ; -m_to_op('RETURN') -> ?RETURN ; -m_to_op('CALL') -> ?CALL ; -m_to_op('CALL_R') -> ?CALL_R ; -m_to_op('CALL_T') -> ?CALL_T ; -m_to_op('CALL_TR') -> ?CALL_TR ; -m_to_op('JUMP') -> ?JUMP ; -m_to_op('JUMPIF') -> ?JUMPIF ; -m_to_op('PUSH') -> ?PUSH ; -m_to_op('DUP') -> ?DUP ; -m_to_op('DUPA') -> ?DUPA ; -m_to_op('POP') -> ?POP ; -m_to_op('STORE') -> ?STORE ; -m_to_op('ADD') -> ?ADD ; -m_to_op('MUL') -> ?MUL ; -m_to_op('SUB') -> ?SUB ; -m_to_op('DIV') -> ?DIV ; -m_to_op('MOD') -> ?MOD ; -m_to_op('POW') -> ?POW ; -m_to_op('LT') -> ?LT ; -m_to_op('GT') -> ?GT ; -m_to_op('EQ') -> ?EQ ; -m_to_op('ELT') -> ?ELT ; -m_to_op('EGT') -> ?EGT ; -m_to_op('NEQ') -> ?NEQ ; -m_to_op('AND') -> ?AND ; -m_to_op('OR') -> ?OR ; -m_to_op('NOT') -> ?NOT ; -m_to_op('TUPLE') -> ?TUPLE ; -m_to_op('ELEMENT') -> ?ELEMENT ; -m_to_op('MAP_EMPTY') -> ?MAP_EMPTY ; -m_to_op('MAP_LOOKUP') -> ?MAP_LOOKUP ; -m_to_op('MAP_UPDATE') -> ?MAP_UPDATE ; -m_to_op('MAP_DELETE') -> ?MAP_DELETE ; -m_to_op('MAP_MEMBER') -> ?MAP_MEMBER ; -m_to_op('MAP_FROM_LIST') -> ?MAP_FROM_LIST ; -m_to_op('NIL') -> ?NIL ; -m_to_op('IS_NIL') -> ?IS_NIL ; -m_to_op('CONS') -> ?CONS ; -m_to_op('HD') -> ?HD ; -m_to_op('TL') -> ?TL ; -m_to_op('LENGTH') -> ?LENGTH ; -m_to_op('STR_EQ') -> ?STR_EQ ; -m_to_op('STR_JOIN') -> ?STR_JOIN ; -m_to_op('ADDR_TO_STR') -> ?ADDR_TO_STR ; -m_to_op('STR_REVERSE') -> ?STR_REVERSE ; -m_to_op('INT_TO_ADDR') -> ?INT_TO_ADDR ; -m_to_op('VARIANT') -> ?VARIANT ; -m_to_op('VARIANT_TEST') -> ?VARIANT_TEST ; -m_to_op('VARIANT_ELEMENT') -> ?VARIANT_ELEMENT ; -m_to_op('BITS_NONEA') -> ?BITS_NONEA ; -m_to_op('BITS_ALL') -> ?BITS_ALL ; -m_to_op('BITS_ALLA') -> ?BITS_ALLA ; -m_to_op('BITS_SET') -> ?BITS_SET ; -m_to_op('BITS_CLEAR') -> ?BITS_CLEAR ; -m_to_op('BITS_TEST') -> ?BITS_TEST ; -m_to_op('BITS_SUM') -> ?BITS_SUM ; -m_to_op('BITS_OR') -> ?BITS_OR ; -m_to_op('BITS_AND') -> ?BITS_AND ; -m_to_op('BITS_DIFF') -> ?BITS_DIFF ; -m_to_op('ADDRESS') -> ?ADDRESS ; -m_to_op('BALANCE') -> ?BALANCE ; -m_to_op('ORIGIN') -> ?ORIGIN ; -m_to_op('CALLER') -> ?CALLER ; -m_to_op('GASPRICE') -> ?GASPRICE ; -m_to_op('BLOCKHASH') -> ?BLOCKHASH ; -m_to_op('BENEFICIARY') -> ?BENEFICIARY ; -m_to_op('TIMESTAMP') -> ?TIMESTAMP ; -m_to_op('NUMBER') -> ?NUMBER ; -m_to_op('DIFFICULTY') -> ?DIFFICULTY ; -m_to_op('GASLIMIT') -> ?GASLIMIT ; -m_to_op('GAS') -> ?GAS ; -m_to_op('LOG0') -> ?LOG0 ; -m_to_op('LOG1') -> ?LOG1 ; -m_to_op('LOG2') -> ?LOG2 ; -m_to_op('LOG3') -> ?LOG3 ; -m_to_op('LOG4') -> ?LOG4 ; -m_to_op('ABORT') -> ?ABORT ; -m_to_op('EXIT') -> ?EXIT ; -m_to_op('DEACTIVATE') -> ?DEACTIVATE ; -m_to_op('INC') -> ?INC ; -m_to_op('DEC') -> ?DEC ; -m_to_op('INCA') -> ?INCA ; -m_to_op('DECA') -> ?DECA ; -m_to_op('INT_TO_STR') -> ?INT_TO_STR ; -m_to_op('SPEND') -> ?SPEND ; -m_to_op('ORACLE_REGISTER') -> ?ORACLE_REGISTER ; -m_to_op('ORACLE_QUERY') -> ?ORACLE_QUERY ; -m_to_op('ORACLE_RESPOND') -> ?ORACLE_RESPOND ; -m_to_op('ORACLE_EXTEND') -> ?ORACLE_EXTEND ; -m_to_op('ORACLE_GET_ANSWER') -> ?ORACLE_GET_ANSWER ; -m_to_op('ORACLE_GET_QUESTION') -> ?ORACLE_GET_QUESTION ; -m_to_op('ORACLE_QUERY_FEE') -> ?ORACLE_QUERY_FEE ; -m_to_op('AENS_RESOLVE') -> ?AENS_RESOLVE ; -m_to_op('AENS_PRECLAIM') -> ?AENS_PRECLAIM ; -m_to_op('AENS_CLAIM') -> ?AENS_CLAIM ; -m_to_op('AENS_UPDATE') -> ?AENS_UPDATE ; -m_to_op('AENS_TRANSFER') -> ?AENS_TRANSFER ; -m_to_op('AENS_REVOKE') -> ?AENS_REVOKE ; -m_to_op('ECVERIFY') -> ?ECVERIFY ; -m_to_op('SHA3') -> ?SHA3 ; -m_to_op('SHA256') -> ?SHA256 ; -m_to_op('BLAKE2B') -> ?BLAKE2B ; -m_to_op('RETURNR') -> ?RETURNR ; -m_to_op('MAP_LOOKUPD') -> ?MAP_LOOKUPD ; -m_to_op('SWITCH_V2') -> ?SWITCH_V2 ; -m_to_op('SWITCH_V3') -> ?SWITCH_V3 ; -m_to_op('SWITCH_VN') -> ?SWITCH_VN ; -m_to_op('FUNCTION') -> ?FUNCTION ; -m_to_op('EXTEND') -> ?EXTEND. - - - -args(?NOP) -> 0; -args(?RETURN) -> 0; -args(?INCA) -> 0; -args(?DECA) -> 0; -args(?DUPA) -> 0; -args(?BITS_NONEA) -> 0; -args(?BITS_ALLA) -> 0; - -args(?INC) -> 1; -args(?DEC) -> 1; -args(?RETURNR) -> 1; -args(?PUSH) -> 1; -args(?JUMP) -> 1; -args(?CALL) -> 1; -args(?CALL_T) -> 1; -args(?TUPLE) -> 1; -args(?MAP_EMPTY) -> 1; -args(?DUP) -> 1; -args(?POP) -> 1; -args(?NIL) -> 1; -args(?BITS_NONE) -> 1; -args(?BITS_ALL) -> 1; -args(?ADDRESS) -> 1; -args(?BALANCE) -> 1; -args(?ORIGIN) -> 1; -args(?CALLER) -> 1; -args(?GASPRICE) -> 1; -args(?BLOCKHASH) -> 1; -args(?BENEFICIARY) -> 1; -args(?TIMESTAMP) -> 1; -args(?NUMBER) -> 1; -args(?DIFFICULTY)-> 1; -args(?GASLIMIT) -> 1; -args(?GAS) -> 1; -args(?ABORT) -> 1; -args(?EXIT) -> 1; - -args(?JUMPIF) -> 2; -args(?CALL_R) -> 2; -args(?CALL_TR) -> 2; -args(?HD) -> 2; -args(?TL) -> 2; -args(?NOT) -> 2; -args(?STORE) -> 2; -args(?LENGTH) -> 2; -args(?IS_NIL) -> 2; -args(?BITS_SUM) -> 2; -args(?BITS_ALL_N) -> 2; -args(?ADDR_TO_STR) -> 2; -args(?STR_REVERSE) -> 2; -args(?INT_TO_ADDR) -> 2; -args(?MAP_FROM_LIST) -> 2; - - -args(?ADD) -> 3; -args(?SUB) -> 3; -args(?MUL) -> 3; -args(?DIV) -> 3; -args(?MOD) -> 3; -args(?POW) -> 3; -args(?AND) -> 3; -args(?OR) -> 3; -args(?LT) -> 3; -args(?GT) -> 3; -args(?EGT) -> 3; -args(?ELT) -> 3; -args(?EQ) -> 3; -args(?NEQ) -> 3; -args(?CONS) -> 3; -args(?STR_EQ) -> 3; -args(?STR_JOIN) -> 3; -args(?MAP_MEMBER) -> 3; -args(?MAP_LOOKUP) -> 3; -args(?MAP_DELETE) -> 3; -args(?BITS_OR) -> 3; -args(?BITS_AND) -> 3; -args(?BITS_SET) -> 3; -args(?BITS_DIFF) -> 3; -args(?BITS_TEST) -> 3; -args(?BITS_CLEAR) -> 3; -args(?VARIANT_TEST) -> 3; -args(?VARIANT_ELEMENT) -> 3; -args(?INT_TO_STR) -> 3; -args(?SWITCH_V2) -> 3; - -args(?SWITCH_V3) -> 4; -args(?ELEMENT) -> 4; -args(?VARIANT) -> 4; -args(?MAP_UPDATE) -> 4; -args(?MAP_LOOKUPD) -> 4; - -args(?SWITCH_VN) -> 2; - -args(_) -> 0. %% TODO do not allow this - -end_bb(?RETURN) -> true; -end_bb(?RETURNR) -> true; -end_bb(?JUMP) -> true; -end_bb(?JUMPIF) -> true; -end_bb(?CALL) -> true; -end_bb(?CALL_T) -> true; -end_bb(?CALL_R) -> true; -end_bb(?CALL_TR) -> true; -end_bb(?SWITCH_V2) -> true; -end_bb(?SWITCH_V3) -> true; -end_bb(?SWITCH_VN) -> true; -end_bb(?ABORT) -> true; -end_bb(?EXIT) -> true; - -end_bb(_) -> false.