From c624f4956c424987b9f588b8d9be7fb60563ab47 Mon Sep 17 00:00:00 2001 From: Erik Stenman Date: Wed, 27 Feb 2019 15:25:57 +0100 Subject: [PATCH] Test targets and cleanup. --- .circleci/config.yml | 6 +- Makefile | 9 ++ src/aeb_fate_asm.erl | 2 +- src/aeb_fate_generate_ops.erl | 176 +++++++++++++++++----------------- 4 files changed, 101 insertions(+), 92 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c1b8283..2d09292 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,13 +22,13 @@ jobs: command: make - run: name: Static Analysis - command: rebar3 dialyzer + command: make dialyzer - run: name: Eunit - command: rebar3 eunit + command: make eunit - run: name: Common Tests - command: rebar3 ct + command: make ct - save_cache: key: dialyzer-cache-v1-{{ .Branch }}-{{ .Revision }} paths: diff --git a/Makefile b/Makefile index f4e9034..fd94da3 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,21 @@ clean: rm -f src/aeb_fate_code.erl rm -f include/aeb_fate_opcodes.hrl +dialyzer: local + @$(REBAR) as local dialyzer + + + distclean: clean @rm -rf _build/ +euint: local + @$(REBAR) as local eunit + test: local @$(REBAR) as local eunit + ebin/aeb_fate_generate_ops.beam: src/aeb_fate_generate_ops.erl ebin erlc -o $(dir $@) $< diff --git a/src/aeb_fate_asm.erl b/src/aeb_fate_asm.erl index 3c163e4..5e320ef 100644 --- a/src/aeb_fate_asm.erl +++ b/src/aeb_fate_asm.erl @@ -820,7 +820,7 @@ to_list_of_types(Tokens) -> {[Type], Rest} end. --spec serialize_type(aeb_fate_date:fate_type_type()) -> [byte()]. +-spec serialize_type(aeb_fate_data:fate_type_type()) -> [byte()]. serialize_type(integer) -> [0]; serialize_type(boolean) -> [1]; serialize_type({list, T}) -> [2 | serialize_type(T)]; diff --git a/src/aeb_fate_generate_ops.erl b/src/aeb_fate_generate_ops.erl index 0fc740c..486fc54 100644 --- a/src/aeb_fate_generate_ops.erl +++ b/src/aeb_fate_generate_ops.erl @@ -19,96 +19,96 @@ generate(Src, Include) -> generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops), generate_code_ops(aeb_fate_code, Src, Ops). - +%% TODO: Some real gas numbers... ops_defs() -> - %% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation - [ { '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_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."} - , { 'SWITCH_V2',16#6a, 3, true, 4, [a, ii, ii], switch, "Conditional jump to a basic block on variant tag."} - , { 'SWITCH_V3',16#6b, 4, true, 4, [a, ii, ii, ii], switch,"Conditional jump to a basic block on variant tag."} - , { 'SWITCH_VN',16#6c, 2, true, 4, [a, li], switch,"Conditional jump to a basic block on variant tag."} - , { 'PUSH', 16#09, 1, false, 2, [a], push, "Push argument to stack."} - , { 'INCA', 16#71, 0, false, 2, atomic, inc, "Increment accumulator."} - , { 'INC', 16#53, 1, false, 2, [a], inc, "Increment argument."} - , { 'DECA', 16#72, 0, false, 2, atomic, dec, "Decrement accumulator."} - , { 'DEC', 16#54, 1, false, 2, [a], dec, "Decrement argument."} - , { 'ADD', 16#11, 3, false, 3, [a,a,a], add, "Arg0 := Arg1 + Arg2."} - , { 'SUB', 16#13, 3, false, 3, [a,a,a], sub, "Arg0 := Arg1 - Arg2."} - , { 'MUL', 16#12, 3, false, 3, [a,a,a], mul, "Arg0 := Arg1 * Arg2."} - , { 'DIV', 16#14, 3, false, 3, [a,a,a], divide, "Arg0 := Arg1 / Arg2."} - , { 'MOD', 16#15, 3, false, 3, [a,a,a], modulo, "Arg0 := Arg1 mod Arg2."} - , { 'POW', 16#16, 3, false, 3, [a,a,a], pow, "Arg0 := Arg1 ^ Arg2."} - , { 'LT', 16#17, 3, false, 3, [a,a,a], lt, "Arg0 := Arg1 < Arg2."} - , { 'GT', 16#18, 3, false, 3, [a,a,a], gt, "Arg0 := Arg1 > Arg2."} - , { 'EQ', 16#19, 3, false, 3, [a,a,a], eq, "Arg0 := Arg1 = Arg2."} - , { 'ELT', 16#1a, 3, false, 3, [a,a,a], elt, "Arg0 := Arg1 =< Arg2."} - , { 'EGT', 16#1b, 3, false, 3, [a,a,a], egt, "Arg0 := Arg1 >= Arg2."} - , { 'NEQ', 16#1c, 3, false, 3, [a,a,a], neq, "Arg0 := Arg1 /= Arg2."} - , { 'AND', 16#1d, 3, false, 3, [a,a,a], and_op, "Arg0 := Arg1 and Arg2."} - , { '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."} - , { '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."} + %% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation + [ { '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_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."} + , { 'SWITCH_V2', 16#6a, 3, true, 4, [a,ii,ii], switch, "Conditional jump to a basic block on variant tag."} + , { 'SWITCH_V3', 16#6b, 4, true, 4, [a,ii,ii,ii], switch, "Conditional jump to a basic block on variant tag."} + , { 'SWITCH_VN', 16#6c, 2, true, 4, [a,li], switch, "Conditional jump to a basic block on variant tag."} + , { 'PUSH', 16#09, 1, false, 2, [a], push, "Push argument to stack."} + , { 'INCA', 16#71, 0, false, 2, atomic, inc, "Increment accumulator."} + , { 'INC', 16#53, 1, false, 2, [a], inc, "Increment argument."} + , { 'DECA', 16#72, 0, false, 2, atomic, dec, "Decrement accumulator."} + , { 'DEC', 16#54, 1, false, 2, [a], dec, "Decrement argument."} + , { 'ADD', 16#11, 3, false, 3, [a,a,a], add, "Arg0 := Arg1 + Arg2."} + , { 'SUB', 16#13, 3, false, 3, [a,a,a], sub, "Arg0 := Arg1 - Arg2."} + , { 'MUL', 16#12, 3, false, 3, [a,a,a], mul, "Arg0 := Arg1 * Arg2."} + , { 'DIV', 16#14, 3, false, 3, [a,a,a], divide, "Arg0 := Arg1 / Arg2."} + , { 'MOD', 16#15, 3, false, 3, [a,a,a], modulo, "Arg0 := Arg1 mod Arg2."} + , { 'POW', 16#16, 3, false, 3, [a,a,a], pow, "Arg0 := Arg1 ^ Arg2."} + , { 'LT', 16#17, 3, false, 3, [a,a,a], lt, "Arg0 := Arg1 < Arg2."} + , { 'GT', 16#18, 3, false, 3, [a,a,a], gt, "Arg0 := Arg1 > Arg2."} + , { 'EQ', 16#19, 3, false, 3, [a,a,a], eq, "Arg0 := Arg1 = Arg2."} + , { 'ELT', 16#1a, 3, false, 3, [a,a,a], elt, "Arg0 := Arg1 =< Arg2."} + , { 'EGT', 16#1b, 3, false, 3, [a,a,a], egt, "Arg0 := Arg1 >= Arg2."} + , { 'NEQ', 16#1c, 3, false, 3, [a,a,a], neq, "Arg0 := Arg1 /= Arg2."} + , { 'AND', 16#1d, 3, false, 3, [a,a,a], and_op, "Arg0 := Arg1 and Arg2."} + , { '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."} + , { '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."} + , {'ADDR_TO_STR', 16#30, 2, false, 3, [a,a], addr_to_str, "Arg0 := turn address Arg1 into a string."} + , {'STR_REVERSE', 16#31, 2, false, 3, [a,a], str_reverse, "Arg0 := the reverse of string Arg1."} + , {'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."} + , {'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."} + , {'BITS_ALL', 16#37, 1, false, 3, [a], bits_all, "Arg0 := full bitmap."} + , {'BITS_ALL_N', 16#6d, 2, false, 3, [a,a], bits_all_n, "Arg0 := bitmap with Arg1 bits set."} + , {'BITS_SET', 16#38, 3, false, 3, [a,a,a], bits_set, "Arg0 := set bit Arg2 of bitmap Arg1."} + , {'BITS_CLEAR', 16#39, 3, false, 3, [a,a,a], bits_clear, "Arg0 := clear bit Arg2 of bitmap Arg1."} + , {'BITS_TEST', 16#3a, 3, false, 3, [a,a,a], bits_test, "Arg0 := true if bit Arg2 of bitmap Arg1 is set."} + , {'BITS_SUM', 16#3b, 2, false, 3, [a,a], bits_sum, "Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap."} + , {'BITS_OR', 16#3c, 3, false, 3, [a,a,a], bits_or, "Arg0 := Arg1 v Arg2."} + , {'BITS_AND', 16#3d, 3, false, 3, [a,a,a], bits_and, "Arg0 := Arg1 ^ Arg2."} + , {'BITS_DIFF', 16#3e, 3, false, 3, [a,a,a], bits_diff, "Arg0 := Arg1 - Arg2."} + , {'DUPA', 16#70, 0, false, 3, atomic, dup, "push copy of accumulator on stack."} + , {'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."} + , {'ADDRESS', 16#3f, 1, false, 3, [a], address, "Arg0 := The current contract address."} + , {'BALANCE', 16#40, 1, false, 3, [a], balance, "Arg0 := The current contract address."} + , {'ORIGIN', 16#41, 1, false, 3, [a], origin, "Arg0 := Address of contract called by the call transaction."} + , {'CALLER', 16#42, 1, false, 3, [a], caller, "Arg0 := The address that signed the call transaction."} + , {'GASPRICE', 16#43, 1, false, 3, [a], gasprice, "Arg0 := The current gas price."} + , {'BLOCKHASH', 16#44, 1, false, 3, [a], blockhash, "Arg0 := The current blockhash."} %% TODO: Do we support has at height? + , {'BENEFICIARY', 16#45, 1, false, 3, [a], beneficiary, "Arg0 := The address of the current beneficiary."} + , {'TIMESTAMP', 16#46, 1, false, 3, [a], timestamp, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."} + , {'NUMBER', 16#47, 1, false, 3, [a], number, "Arg0 := The block height."} + , {'DIFFICULTY', 16#48, 1, false, 3, [a], difficulty, "Arg0 := The current difficulty."} + , {'GASLIMIT', 16#49, 1, false, 3, [a], gaslimit, "Arg0 := The current gaslimit."} + , {'GAS', 16#4a, 1, false, 3, [a], gas, "Arg0 := The amount of gas left."} + , {'ABORT', 16#50, 1, false, 3, [a], abort, "Abort execution (dont use all gas) with error message in Arg0."} + , {'EXIT', 16#51, 1, false, 3, [a], exit, "Abort execution (use upp all gas) with error message in Arg0."} - , {'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."} - , {'ADDR_TO_STR', 16#30, 2, false, 3, [a, a], addr_to_str, "Arg0 := turn address Arg1 into a string."} - , {'STR_REVERSE', 16#31, 2, false, 3, [a, a], str_reverse, "Arg0 := the reverse of string Arg1."} - , {'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_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."} - , {'BITS_ALL', 16#37, 1, false, 3, [a], bits_all, "Arg0 := full bitmap."} - , {'BITS_ALL_N', 16#6d, 2, false, 3, [a, a], bits_all_n, "Arg0 := bitmap with Arg1 bits set."} - , {'BITS_SET', 16#38, 3, false, 3, [a, a, a], bits_set, "Arg0 := set bit Arg2 of bitmap Arg1."} - , {'BITS_CLEAR',16#39, 3, false, 3, [a, a, a], bits_clear, "Arg0 := clear bit Arg2 of bitmap Arg1."} - , {'BITS_TEST', 16#3a, 3, false, 3, [a, a, a], bits_test, "Arg0 := true if bit Arg2 of bitmap Arg1 is set."} , {'BITS_SUM', 16#3b, 2, false, 3, [a, a], bits_sum, "Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap."} - , {'BITS_OR', 16#3c, 3, false, 3, [a, a, a], bits_or, "Arg0 := Arg1 v Arg2."} - , {'BITS_AND', 16#3d, 3, false, 3, [a, a, a], bits_and, "Arg0 := Arg1 ^ Arg2."} - , {'BITS_DIFF', 16#3e, 3, false, 3, [a, a, a], bits_diff, "Arg0 := Arg1 - Arg2."} - , {'DUPA', 16#70, 0, false, 3, atomic, dup, "push copy of accumulator on stack."} - , {'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."} ].