Compare commits
12 Commits
master
...
quickcheck
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9d056dc620 | ||
![]() |
a51a864059 | ||
![]() |
899bff9111 | ||
![]() |
b5daedaf95 | ||
![]() |
8dd8e89c1e | ||
![]() |
dd1a6a9c3d | ||
![]() |
161b5a6106 | ||
![]() |
268208ec98 | ||
![]() |
9411a131fc | ||
![]() |
c624f4956c | ||
![]() |
ab150ce7f8 | ||
![]() |
c85af9e7f3 |
@ -19,16 +19,16 @@ jobs:
|
||||
- dialyzer-cache-v1-
|
||||
- run:
|
||||
name: Build
|
||||
command: rebar3 compile
|
||||
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 test
|
||||
- save_cache:
|
||||
key: dialyzer-cache-v1-{{ .Branch }}-{{ .Revision }}
|
||||
paths:
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -10,5 +10,9 @@ rel/example_project
|
||||
.rebar
|
||||
aeb_asm_scan.erl
|
||||
aeb_fate_asm_scan.erl
|
||||
aeb_fate_asm_scan.xrl
|
||||
_build/
|
||||
aefateasm
|
||||
include/aeb_fate_opcodes.hrl
|
||||
src/aeb_fate_code.erl
|
||||
src/aeb_fate_opcodes.erl
|
||||
|
25
Makefile
25
Makefile
@ -4,17 +4,38 @@ REBAR ?= rebar3
|
||||
|
||||
all: local
|
||||
|
||||
local:
|
||||
local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl
|
||||
@$(REBAR) as local release
|
||||
|
||||
console:
|
||||
console: local
|
||||
@$(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
|
||||
|
||||
dialyzer: local
|
||||
@$(REBAR) as local dialyzer
|
||||
|
||||
|
||||
|
||||
distclean: clean
|
||||
@rm -rf _build/
|
||||
|
||||
eunit: 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 $@) $<
|
||||
|
||||
src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl: ebin/aeb_fate_generate_ops.beam
|
||||
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
|
||||
|
||||
ebin:
|
||||
mkdir ebin
|
||||
|
@ -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}).
|
||||
|
@ -45,5 +45,8 @@
|
||||
"robocopy \"%REBAR_BUILD_DIR%/bin/\" ./ aefateasm* "
|
||||
"/njs /njh /nfl /ndl & exit /b 0"} % silence things
|
||||
]}
|
||||
]}]}.
|
||||
|
||||
]},
|
||||
{eqc, [{erl_opts, [{parse_transform, eqc_cover}]},
|
||||
{extra_src_dirs, ["quickcheck"]} %% May not be called eqc!
|
||||
]}
|
||||
]}.
|
||||
|
@ -10,10 +10,15 @@
|
||||
%%% DUP
|
||||
%%% Identifiers start with a lower case letter
|
||||
%%% an_identifier
|
||||
%%% References to function arguments start with arg
|
||||
%%% References to function arguments start with arg followed by an integer
|
||||
%%% arg0
|
||||
%%% References to variables/registers start with var
|
||||
%%% References to variables/registers start with var followed by an integer
|
||||
%%% var0
|
||||
%%% References to stack postions is either a (for stack 0)
|
||||
%%% or start with stack followed by an integer
|
||||
%%% stack1
|
||||
%%% a
|
||||
%%%
|
||||
%%% Immediates can be of 9 types:
|
||||
%%% 1. Integers
|
||||
%%% 42
|
||||
@ -815,7 +820,7 @@ to_list_of_types(Tokens) ->
|
||||
{[Type], Rest}
|
||||
end.
|
||||
|
||||
|
||||
-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)];
|
||||
|
99
src/aeb_fate_asm_scan.template
Normal file
99
src/aeb_fate_asm_scan.template
Normal file
@ -0,0 +1,99 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2019, aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Handling FATE code.
|
||||
%%% @end
|
||||
###REPLACEWITHNOTE###
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
Definitions.
|
||||
DIGIT = [0-9]
|
||||
HEXDIGIT = [0-9a-fA-F]
|
||||
LOWER = [a-z_]
|
||||
UPPER = [A-Z]
|
||||
INT = {DIGIT}+
|
||||
HEX = 0x{HEXDIGIT}+
|
||||
HASH = #{HEXDIGIT}+
|
||||
WS = [\000-\s]
|
||||
ID = {LOWER}[a-zA-Z0-9_]*
|
||||
|
||||
|
||||
Rules.
|
||||
arg{INT} : {token, {arg, TokenLine, parse_arg(TokenChars)}}.
|
||||
var{INT} : {token, {var, TokenLine, parse_var(TokenChars)}}.
|
||||
a : {token, {stack, TokenLine, 0}}.
|
||||
a{INT} : {token, {stack, TokenLine, parse_acc(TokenChars)}}.
|
||||
|
||||
true : {token, {boolean, TokenLine, true}}.
|
||||
false : {token, {boolean, TokenLine, false}}.
|
||||
|
||||
###REPLACEWITHOPTOKENS###
|
||||
|
||||
FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
||||
|
||||
{ID} :
|
||||
{token, {id, TokenLine, TokenChars}}.
|
||||
{HEX} :
|
||||
{token, {int, TokenLine, parse_hex(TokenChars)}}.
|
||||
{INT} :
|
||||
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
||||
{HASH} :
|
||||
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
|
||||
|
||||
|
||||
%% Symbols
|
||||
\-\> : {token, {'to', TokenLine}}.
|
||||
\: : {token, {'to', TokenLine}}.
|
||||
, : {token, {',', TokenLine}}.
|
||||
\( : {token, {'(', TokenLine}}.
|
||||
\) : {token, {')', TokenLine}}.
|
||||
\[ : {token, {'[', TokenLine}}.
|
||||
\] : {token, {']', TokenLine}}.
|
||||
\{ : {token, {'{', TokenLine}}.
|
||||
\} : {token, {'}', TokenLine}}.
|
||||
|
||||
;;.* :
|
||||
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
|
||||
|
||||
\. : skip_token.
|
||||
|
||||
|
||||
%% Whitespace ignore
|
||||
{WS} : skip_token.
|
||||
|
||||
%% Comments (TODO: nested comments)
|
||||
|
||||
|
||||
. : {error, "Unexpected token: " ++ TokenChars}.
|
||||
|
||||
Erlang code.
|
||||
|
||||
-export([scan/1]).
|
||||
|
||||
-dialyzer({nowarn_function, yyrev/2}).
|
||||
|
||||
-ignore_xref([format_error/1, string/2, token/2, token/3, tokens/2, tokens/3]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_fate_opcodes.hrl").
|
||||
|
||||
|
||||
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16).
|
||||
|
||||
parse_int(Chars) -> list_to_integer(Chars).
|
||||
|
||||
parse_arg("arg" ++ N) -> list_to_integer(N).
|
||||
parse_var("var" ++ N) -> list_to_integer(N).
|
||||
parse_acc("a" ++ N) -> list_to_integer(N).
|
||||
|
||||
|
||||
parse_hash("#" ++ Chars) ->
|
||||
N = list_to_integer(Chars, 16),
|
||||
<<N:256>>.
|
||||
|
||||
scan(S) ->
|
||||
string(S).
|
||||
|
||||
drop_prefix(C, [C|Rest]) ->
|
||||
drop_prefix(C, Rest);
|
||||
drop_prefix(_, Tail) -> Tail.
|
@ -1,207 +0,0 @@
|
||||
%%% -*- erlang-indent-level:4; indent-tabs-mode: nil -*-
|
||||
%%%-------------------------------------------------------------------
|
||||
%%% @copyright (C) 2019, aeternity Anstalt
|
||||
%%% @doc
|
||||
%%% Handling FATE code.
|
||||
%%% @end
|
||||
%%% Created : 9 Jan 2019
|
||||
%%%-------------------------------------------------------------------
|
||||
|
||||
Definitions.
|
||||
DIGIT = [0-9]
|
||||
HEXDIGIT = [0-9a-fA-F]
|
||||
LOWER = [a-z_]
|
||||
UPPER = [A-Z]
|
||||
INT = {DIGIT}+
|
||||
HEX = 0x{HEXDIGIT}+
|
||||
HASH = #{HEXDIGIT}+
|
||||
WS = [\000-\s]
|
||||
ID = {LOWER}[a-zA-Z0-9_]*
|
||||
|
||||
|
||||
Rules.
|
||||
arg{INT} : {token, {arg, TokenLine, parse_arg(TokenChars)}}.
|
||||
var{INT} : {token, {var, TokenLine, parse_var(TokenChars)}}.
|
||||
a : {token, {stack, TokenLine, 0}}.
|
||||
a{INT} : {token, {stack, TokenLine, parse_acc(TokenChars)}}.
|
||||
|
||||
true : {token, {boolean, TokenLine, true}}.
|
||||
false : {token, {boolean, TokenLine, false}}.
|
||||
|
||||
RETURN : {token, {mnemonic, TokenLine, 'RETURN'}}.
|
||||
RETURNR : {token, {mnemonic, TokenLine, 'RETURNR'}}.
|
||||
CALL : {token, {mnemonic, TokenLine, 'CALL'}}.
|
||||
NOP : {token, {mnemonic, TokenLine, 'NOP'}}.
|
||||
|
||||
CALL_R : {token, {mnemonic, TokenLine, 'CALL_R'}}.
|
||||
CALL_T : {token, {mnemonic, TokenLine, 'CALL_T'}}.
|
||||
CALL_TR : {token, {mnemonic, TokenLine, 'CALL_TR'}}.
|
||||
JUMP : {token, {mnemonic, TokenLine, 'JUMP'}}.
|
||||
JUMPIF : {token, {mnemonic, TokenLine, 'JUMPIF'}}.
|
||||
SWITCH_V2 : {token, {mnemonic, TokenLine, 'SWITCH_V2'}}.
|
||||
SWITCH_V3 : {token, {mnemonic, TokenLine, 'SWITCH_V3'}}.
|
||||
SWITCH_VN : {token, {mnemonic, TokenLine, 'SWITCH_VN'}}.
|
||||
|
||||
PUSH : {token, {mnemonic, TokenLine, 'PUSH'}}.
|
||||
DUP : {token, {mnemonic, TokenLine, 'DUP'}}.
|
||||
DUPA : {token, {mnemonic, TokenLine, 'DUPA'}}.
|
||||
POP : {token, {mnemonic, TokenLine, 'POP'}}.
|
||||
|
||||
STORE : {token, {mnemonic, TokenLine, 'STORE'}}.
|
||||
|
||||
ADD : {token, {mnemonic, TokenLine, 'ADD'}}.
|
||||
MUL : {token, {mnemonic, TokenLine, 'MUL'}}.
|
||||
SUB : {token, {mnemonic, TokenLine, 'SUB'}}.
|
||||
DIV : {token, {mnemonic, TokenLine, 'DIV'}}.
|
||||
MOD : {token, {mnemonic, TokenLine, 'MOD'}}.
|
||||
POW : {token, {mnemonic, TokenLine, 'POW'}}.
|
||||
|
||||
INC : {token, {mnemonic, TokenLine, 'INC'}}.
|
||||
DEC : {token, {mnemonic, TokenLine, 'DEC'}}.
|
||||
INCA : {token, {mnemonic, TokenLine, 'INCA'}}.
|
||||
DECA : {token, {mnemonic, TokenLine, 'DECA'}}.
|
||||
|
||||
LT : {token, {mnemonic, TokenLine, 'LT'}}.
|
||||
GT : {token, {mnemonic, TokenLine, 'GT'}}.
|
||||
EQ : {token, {mnemonic, TokenLine, 'EQ'}}.
|
||||
ELT : {token, {mnemonic, TokenLine, 'ELT'}}.
|
||||
EGT : {token, {mnemonic, TokenLine, 'EGT'}}.
|
||||
NEQ : {token, {mnemonic, TokenLine, 'NEQ'}}.
|
||||
|
||||
AND : {token, {mnemonic, TokenLine, 'AND'}}.
|
||||
OR : {token, {mnemonic, TokenLine, 'OR'}}.
|
||||
NOT : {token, {mnemonic, TokenLine, 'NOT'}}.
|
||||
|
||||
TUPLE : {token, {mnemonic, TokenLine, 'TUPLE'}}.
|
||||
ELEMENT : {token, {mnemonic, TokenLine, 'ELEMENT'}}.
|
||||
|
||||
MAP_EMPTY : {token, {mnemonic, TokenLine, 'MAP_EMPTY'}}.
|
||||
MAP_LOOKUP : {token, {mnemonic, TokenLine, 'MAP_LOOKUP'}}.
|
||||
MAP_LOOKUPD : {token, {mnemonic, TokenLine, 'MAP_LOOKUPD'}}.
|
||||
MAP_UPDATE : {token, {mnemonic, TokenLine, 'MAP_UPDATE'}}.
|
||||
MAP_MEMBER : {token, {mnemonic, TokenLine, 'MAP_MEMBER'}}.
|
||||
MAP_DELETE : {token, {mnemonic, TokenLine, 'MAP_DELETE'}}.
|
||||
MAP_FROM_LIST : {token, {mnemonic, TokenLine, 'MAP_FROM_LIST'}}.
|
||||
|
||||
NIL : {token, {mnemonic, TokenLine, 'NIL'}}.
|
||||
IS_NIL : {token, {mnemonic, TokenLine, 'IS_NIL'}}.
|
||||
CONS : {token, {mnemonic, TokenLine, 'CONS'}}.
|
||||
HD : {token, {mnemonic, TokenLine, 'HD'}}.
|
||||
TL : {token, {mnemonic, TokenLine, 'TL'}}.
|
||||
LENGTH : {token, {mnemonic, TokenLine, 'LENGTH'}}.
|
||||
|
||||
STR_EQ : {token, {mnemonic, TokenLine, 'STR_EQ'}}.
|
||||
STR_JOIN : {token, {mnemonic, TokenLine, 'STR_JOIN'}}.
|
||||
INT_TO_STR : {token, {mnemonic, TokenLine, 'INT_TO_STR'}}.
|
||||
ADDR_TO_STR : {token, {mnemonic, TokenLine, 'ADDR_TO_STR'}}.
|
||||
STR_REVERSE : {token, {mnemonic, TokenLine, 'STR_REVERSE'}}.
|
||||
|
||||
INT_TO_ADDR : {token, {mnemonic, TokenLine, 'INT_TO_ADDR'}}.
|
||||
|
||||
VARIANT : {token, {mnemonic, TokenLine, 'VARIANT'}}.
|
||||
VARIANT_TEST : {token, {mnemonic, TokenLine, 'VARIANT_TEST'}}.
|
||||
VARIANT_ELEMENT : {token, {mnemonic, TokenLine, 'VARIANT_ELEMENT'}}.
|
||||
|
||||
BITS_NONE : {token, {mnemonic, TokenLine, 'BITS_NONE'}}.
|
||||
BITS_NONEA : {token, {mnemonic, TokenLine, 'BITS_NONEA'}}.
|
||||
BITS_ALL : {token, {mnemonic, TokenLine, 'BITS_ALL'}}.
|
||||
BITS_ALLA : {token, {mnemonic, TokenLine, 'BITS_ALLA'}}.
|
||||
BITS_ALL_N : {token, {mnemonic, TokenLine, 'BITS_ALL_N'}}.
|
||||
BITS_SET : {token, {mnemonic, TokenLine, 'BITS_SET'}}.
|
||||
BITS_CLEAR : {token, {mnemonic, TokenLine, 'BITS_CLEAR'}}.
|
||||
BITS_TEST : {token, {mnemonic, TokenLine, 'BITS_TEST'}}.
|
||||
BITS_SUM : {token, {mnemonic, TokenLine, 'BITS_SUM'}}.
|
||||
BITS_OR : {token, {mnemonic, TokenLine, 'BITS_OR'}}.
|
||||
BITS_AND : {token, {mnemonic, TokenLine, 'BITS_AND'}}.
|
||||
BITS_DIFF : {token, {mnemonic, TokenLine, 'BITS_DIFF'}}.
|
||||
|
||||
|
||||
ADDRESS : {token, {mnemonic, TokenLine, 'ADDRESS'}}.
|
||||
BALANCE : {token, {mnemonic, TokenLine, 'BALANCE'}}.
|
||||
ORIGIN : {token, {mnemonic, TokenLine, 'ORIGIN'}}.
|
||||
CALLER : {token, {mnemonic, TokenLine, 'CALLER'}}.
|
||||
GASPRICE : {token, {mnemonic, TokenLine, 'GASPRICE'}}.
|
||||
BLOCKHASH : {token, {mnemonic, TokenLine, 'BLOCKHASH'}}.
|
||||
BENEFICIARY : {token, {mnemonic, TokenLine, 'BENEFICIARY'}}.
|
||||
TIMESTAMP : {token, {mnemonic, TokenLine, 'TIMESTAMP'}}.
|
||||
NUMBER : {token, {mnemonic, TokenLine, 'NUMBER'}}.
|
||||
DIFFICULTY : {token, {mnemonic, TokenLine, 'DIFFICULTY'}}.
|
||||
GASLIMIT : {token, {mnemonic, TokenLine, 'GASLIMIT'}}.
|
||||
GAS : {token, {mnemonic, TokenLine, 'GAS'}}.
|
||||
LOG0 : {token, {mnemonic, TokenLine, 'LOG0'}}.
|
||||
LOG1 : {token, {mnemonic, TokenLine, 'LOG1'}}.
|
||||
LOG2 : {token, {mnemonic, TokenLine, 'LOG2'}}.
|
||||
LOG3 : {token, {mnemonic, TokenLine, 'LOG3'}}.
|
||||
LOG4 : {token, {mnemonic, TokenLine, 'LOG4'}}.
|
||||
ABORT : {token, {mnemonic, TokenLine, 'ABORT'}}.
|
||||
EXIT : {token, {mnemonic, TokenLine, 'EXIT'}}.
|
||||
DEACTIVATE : {token, {mnemonic, TokenLine, 'DEACTIVATE'}}.
|
||||
COMMENT : {token, {mnemonic, TokenLine, 'COMMENT'}}.
|
||||
|
||||
FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
||||
|
||||
{ID} :
|
||||
{token, {id, TokenLine, TokenChars}}.
|
||||
{HEX} :
|
||||
{token, {int, TokenLine, parse_hex(TokenChars)}}.
|
||||
{INT} :
|
||||
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
||||
{HASH} :
|
||||
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
|
||||
|
||||
|
||||
%% Symbols
|
||||
\-\> : {token, {'to', TokenLine}}.
|
||||
\: : {token, {'to', TokenLine}}.
|
||||
, : {token, {',', TokenLine}}.
|
||||
\( : {token, {'(', TokenLine}}.
|
||||
\) : {token, {')', TokenLine}}.
|
||||
\[ : {token, {'[', TokenLine}}.
|
||||
\] : {token, {']', TokenLine}}.
|
||||
\{ : {token, {'{', TokenLine}}.
|
||||
\} : {token, {'}', TokenLine}}.
|
||||
|
||||
;;.* :
|
||||
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
|
||||
|
||||
\. : skip_token.
|
||||
|
||||
|
||||
%% Whitespace ignore
|
||||
{WS} : skip_token.
|
||||
|
||||
%% Comments (TODO: nested comments)
|
||||
|
||||
|
||||
. : {error, "Unexpected token: " ++ TokenChars}.
|
||||
|
||||
Erlang code.
|
||||
|
||||
-export([scan/1]).
|
||||
|
||||
-dialyzer({nowarn_function, yyrev/2}).
|
||||
|
||||
-ignore_xref([format_error/1, string/2, token/2, token/3, tokens/2, tokens/3]).
|
||||
|
||||
-include_lib("aebytecode/include/aeb_fate_opcodes.hrl").
|
||||
|
||||
|
||||
parse_hex("0x" ++ Chars) -> list_to_integer(Chars, 16).
|
||||
|
||||
parse_int(Chars) -> list_to_integer(Chars).
|
||||
|
||||
parse_arg("arg" ++ N) -> list_to_integer(N).
|
||||
parse_var("var" ++ N) -> list_to_integer(N).
|
||||
parse_acc("a" ++ N) -> list_to_integer(N).
|
||||
|
||||
|
||||
parse_hash("#" ++ Chars) ->
|
||||
N = list_to_integer(Chars, 16),
|
||||
<<N:256>>.
|
||||
|
||||
scan(S) ->
|
||||
string(S).
|
||||
|
||||
drop_prefix(C, [C|Rest]) ->
|
||||
drop_prefix(C, Rest);
|
||||
drop_prefix(_, Tail) -> Tail.
|
@ -1,303 +0,0 @@
|
||||
-module(aeb_fate_code).
|
||||
|
||||
-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/5
|
||||
, switch/6
|
||||
, 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__ }).
|
||||
|
||||
return() ->
|
||||
'RETURN'.
|
||||
|
||||
return(Arg) ->
|
||||
{'RETURNR', Arg}.
|
||||
|
||||
call(Function) when is_binary(Function)->
|
||||
{'CALL', ?i(Function) }.
|
||||
|
||||
call_t(Function) when is_binary(Function) ->
|
||||
{'CALL_T', ?i(Function)}.
|
||||
|
||||
call_r(Contract, Function) when is_binary(Function) ->
|
||||
{'CALL_R', Contract, ?i(Function)}.
|
||||
|
||||
call_tr(Contract, Function) when is_binary(Function) ->
|
||||
{'CALL_TR', Contract, ?i(Function)}.
|
||||
|
||||
jump(BB) when is_integer(BB) ->
|
||||
{'JUMP', ?i(BB)}.
|
||||
|
||||
jumpif(Arg, BB) when is_integer(BB) ->
|
||||
{'JUMPIF', Arg, ?i(BB)}.
|
||||
|
||||
switch(Arg, BB1, BB2) when is_integer(BB1),
|
||||
is_integer(BB2) ->
|
||||
{'SWITCH_V2', Arg, ?i(BB1), ?i(BB2)}.
|
||||
|
||||
switch(Arg, BB1, BB2, BB3) when is_integer(BB1),
|
||||
is_integer(BB2),
|
||||
is_integer(BB3) ->
|
||||
{'SWITCH_V3', Arg, ?i(BB1), ?i(BB2), ?i(BB3)}.
|
||||
|
||||
switch(Arg, BB1, BB2, BB3, BB4) when is_integer(BB1),
|
||||
is_integer(BB2),
|
||||
is_integer(BB3),
|
||||
is_integer(BB4) ->
|
||||
{'SWITCH_V4', Arg, ?i(BB1), ?i(BB2), ?i(BB3), ?i(BB4)}.
|
||||
|
||||
switch(Arg, BB1, BB2, BB3, BB4, BB5) when is_integer(BB1),
|
||||
is_integer(BB2),
|
||||
is_integer(BB3),
|
||||
is_integer(BB4),
|
||||
is_integer(BB5) ->
|
||||
{'SWITCH_V5', Arg, ?i(BB1), ?i(BB2), ?i(BB3), ?i(BB4), ?i(BB5)}.
|
||||
|
||||
push(Arg) ->
|
||||
{'PUSH', Arg}.
|
||||
|
||||
inc() ->
|
||||
'INCA'.
|
||||
|
||||
inc(Arg) ->
|
||||
{'INC', Arg}.
|
||||
|
||||
dec() ->
|
||||
'DECA'.
|
||||
|
||||
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_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_integer(N) ->
|
||||
{'DUP', ?i(N)}.
|
||||
|
||||
pop() ->
|
||||
'POP'.
|
||||
|
||||
store(Var, What) ->
|
||||
{'STORE', Var, What}.
|
||||
|
||||
nop() ->
|
||||
'NOP'.
|
@ -15,10 +15,18 @@
|
||||
|
||||
-type fate_variant() :: ?FATE_VARIANT_T.
|
||||
|
||||
-type fate_void() :: ?FATE_VOID_T.
|
||||
|
||||
-type fate_tuple() :: ?FATE_TUPLE_T.
|
||||
|
||||
-type fate_type_type() :: integer
|
||||
| boolean
|
||||
| {list, fate_type()}
|
||||
| {map, fate_type(), fate_type()}
|
||||
| {tuple, [fate_type()]}
|
||||
| address
|
||||
| bits
|
||||
| {variant, integer()}.
|
||||
|
||||
|
||||
-type fate_type() ::
|
||||
fate_boolean()
|
||||
| fate_integer()
|
||||
@ -30,11 +38,21 @@
|
||||
| fate_address()
|
||||
| fate_variant()
|
||||
| fate_map()
|
||||
| fate_list()
|
||||
| fate_tuple()
|
||||
| fate_void(). %% Not sure we need this.
|
||||
| fate_type_type().
|
||||
|
||||
-export_type([fate_type/0]).
|
||||
-export_type([fate_type/0
|
||||
, fate_boolean/0
|
||||
, fate_integer/0
|
||||
, fate_nil/0
|
||||
, fate_list/0
|
||||
, fate_unit/0
|
||||
, fate_tuple/0
|
||||
, fate_string/0
|
||||
, fate_address/0
|
||||
, fate_variant/0
|
||||
, fate_map/0
|
||||
, fate_type_type/0
|
||||
]).
|
||||
|
||||
-export([ make_integer/1
|
||||
, make_boolean/1
|
||||
@ -111,35 +129,29 @@ decode(M) when ?IS_FATE_MAP(M) ->
|
||||
|
||||
-spec format(fate_type()) -> iolist().
|
||||
format(I) when ?IS_FATE_INTEGER(I) -> integer_to_list(?MAKE_FATE_INTEGER(I));
|
||||
format(?FATE_VOID) -> "void";
|
||||
format(?FATE_TRUE) -> "true";
|
||||
format(?FATE_FALSE) -> "false";
|
||||
format(?FATE_NIL) -> "[]";
|
||||
format(L) when ?IS_FATE_LIST(L) -> format_list(?FATE_LIST_VALUE(L));
|
||||
format(?FATE_UNIT) -> "unit";
|
||||
format(?FATE_UNIT) -> "()";
|
||||
format(?FATE_TUPLE(T)) ->
|
||||
"{ " ++ [format(E) ++ " " || E <- erlang:tuple_to_list(T)] ++ "}";
|
||||
["( ", lists:join(", ", [ format(E) || E <- erlang:tuple_to_list(T)]), " )"];
|
||||
format(S) when ?IS_FATE_STRING(S) -> [S];
|
||||
format(?FATE_VARIANT(Size, Tag, T)) ->
|
||||
"( " ++ integer_to_list(Size) ++ ", "
|
||||
++ integer_to_list(Tag) ++ ", "
|
||||
++ [format(E) ++ " " || E <- erlang:tuple_to_list(T)]
|
||||
++ " )";
|
||||
["(| ",
|
||||
lists:join("| ", [integer_to_list(Size), integer_to_list(Tag) |
|
||||
[format(E) || E <- erlang:tuple_to_list(T)]]),
|
||||
" |)"];
|
||||
format(M) when ?IS_FATE_MAP(M) ->
|
||||
"#{ "
|
||||
++ format_kvs(maps:to_list(?FATE_MAP_VALUE(M)))
|
||||
++" }";
|
||||
format(?FATE_ADDRESS(Address)) -> address_to_base58(Address);
|
||||
["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"];
|
||||
format(?FATE_ADDRESS(Address)) -> ["#", address_to_base58(Address)];
|
||||
format(V) -> exit({not_a_fate_type, V}).
|
||||
|
||||
format_list([]) -> " ]";
|
||||
format_list([E]) -> format(E) ++ " ]";
|
||||
format_list([H|T]) -> format(H) ++ ", " ++ format_list(T).
|
||||
format_list(List) ->
|
||||
["[ ", lists:join(", ", [format(E) || E <- List]), " ]"].
|
||||
|
||||
format_kvs([]) -> "";
|
||||
format_kvs([{K,V}]) -> "( " ++ format(K) ++ " => " ++ format(V) ++ " )";
|
||||
format_kvs([{K,V} | Rest]) ->
|
||||
"( " ++ format(K) ++ " => " ++ format(V) ++ " ), " ++ format_kvs(Rest).
|
||||
format_kvs(List) ->
|
||||
lists:join(", ", [ [format(K), " => ", format(V)] || {K, V} <- List]).
|
||||
|
||||
|
||||
%% -- Local base 58 library
|
||||
|
@ -136,10 +136,8 @@ serialize(Map) when ?IS_FATE_MAP(Map) ->
|
||||
<<?MAP,
|
||||
(rlp_integer(Size))/binary,
|
||||
(Elements)/binary>>;
|
||||
serialize(?FATE_VARIANT(Size, Tag, Values)) when 0 =< Size
|
||||
, Size < 256
|
||||
, 0 =< Tag
|
||||
, Tag < Size ->
|
||||
serialize(?FATE_VARIANT(Size, Tag, Values)) when 0 < Size, Size < 256,
|
||||
0 =< Tag, Tag < Size ->
|
||||
<<?VARIANT, Size:8, Tag:8,
|
||||
(serialize(?FATE_TUPLE(Values)))/binary
|
||||
>>.
|
||||
|
402
src/aeb_fate_generate_ops.erl
Normal file
402
src/aeb_fate_generate_ops.erl
Normal file
@ -0,0 +1,402 @@
|
||||
-module(aeb_fate_generate_ops).
|
||||
|
||||
-export([ gen_and_halt/1
|
||||
, generate/0]).
|
||||
|
||||
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 = Include ++ "aeb_fate_opcodes.hrl",
|
||||
generate_header_file(HrlFile, Ops),
|
||||
generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops),
|
||||
generate_code_ops(aeb_fate_code, Src, Ops),
|
||||
generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops).
|
||||
|
||||
%% TODO: Some real gas numbers...
|
||||
ops_defs() ->
|
||||
%% Opname, Opcode, args, end_bb, gas, format, Constructor, Documentation
|
||||
[ { 'RETURN', 16#00, 0, true, 2, atomic, return, "Return from function call pop stack to arg0. The type of the retun value has to match the return type of the function."}
|
||||
, { 'RETURNR', 16#01, 1, true, 2, [a], returnr, "Return from function call copy Arg0 to arg0. The type of the retun value has to match the return type of the function."}
|
||||
, { 'CALL', 16#02, 1, true, 4, [is], call, "Call given function with args on stack. The types of the arguments has to match the argument typs of the function."}
|
||||
, { 'CALL_R', 16#03, 2, true, 8, [a,is], call_r, "Remote call to given contract and function. The types of the arguments has to match the argument typs of the function."}
|
||||
, { 'CALL_T', 16#04, 1, true, 4, [is], call_t, "Tail call to given function. The types of the arguments has to match the argument typs of the function. And the return type of the called function has to match the type of the current function."}
|
||||
, { 'CALL_TR', 16#05, 2, true, 8, [a,is], call_tr, "Remote tail call to given contract and function. The types of the arguments has to match the argument typs of the function. And the return type of the called function has to match the type of the current function."}
|
||||
, { 'JUMP', 16#06, 1, true, 3, [ii], jump, "Jump to a basic block. The basic block has to exist in the current function."}
|
||||
, { 'JUMPIF', 16#07, 2, true, 4, [a,ii], jumpif, "Conditional jump to a basic block. If Arg0 then jump to Arg1."}
|
||||
, { 'SWITCH_V2', 16#08, 3, true, 4, [a,ii,ii], switch, "Conditional jump to a basic block on variant tag."}
|
||||
, { 'SWITCH_V3', 16#09, 4, true, 4, [a,ii,ii,ii], switch, "Conditional jump to a basic block on variant tag."}
|
||||
, { 'SWITCH_VN', 16#0a, 2, true, 4, [a,li], switch, "Conditional jump to a basic block on variant tag."}
|
||||
, { 'PUSH', 16#0b, 1, false, 2, [a], push, "Push argument to stack."}
|
||||
, { 'DUPA', 16#0c, 0, false, 3, atomic, dup, "push copy of accumulator on stack."}
|
||||
, { 'DUP', 16#0d, 1, false, 3, [a], dup, "push Arg0 stack pos on top of stack."}
|
||||
, { 'POP', 16#0e, 1, false, 3, [a], pop, "Arg0 := top of stack."}
|
||||
, { 'STORE', 16#0f, 2, false, 3, [a,a], store, "Arg0 := Arg1."}
|
||||
, { 'INCA', 16#10, 0, false, 2, atomic, inc, "Increment accumulator."}
|
||||
, { 'INC', 16#11, 1, false, 2, [a], inc, "Increment argument."}
|
||||
, { 'DECA', 16#12, 0, false, 2, atomic, dec, "Decrement accumulator."}
|
||||
, { 'DEC', 16#13, 1, false, 2, [a], dec, "Decrement argument."}
|
||||
, { 'ADD', 16#14, 3, false, 3, [a,a,a], add, "Arg0 := Arg1 + Arg2."}
|
||||
, { 'SUB', 16#15, 3, false, 3, [a,a,a], sub, "Arg0 := Arg1 - Arg2."}
|
||||
, { 'MUL', 16#16, 3, false, 3, [a,a,a], mul, "Arg0 := Arg1 * Arg2."}
|
||||
, { 'DIV', 16#17, 3, false, 3, [a,a,a], divide, "Arg0 := Arg1 / Arg2."}
|
||||
, { 'MOD', 16#18, 3, false, 3, [a,a,a], modulo, "Arg0 := Arg1 mod Arg2."}
|
||||
, { 'POW', 16#19, 3, false, 3, [a,a,a], pow, "Arg0 := Arg1 ^ Arg2."}
|
||||
, { 'LT', 16#20, 3, false, 3, [a,a,a], lt, "Arg0 := Arg1 < Arg2."}
|
||||
, { 'GT', 16#21, 3, false, 3, [a,a,a], gt, "Arg0 := Arg1 > Arg2."}
|
||||
, { 'EQ', 16#22, 3, false, 3, [a,a,a], eq, "Arg0 := Arg1 = Arg2."}
|
||||
, { 'ELT', 16#23, 3, false, 3, [a,a,a], elt, "Arg0 := Arg1 =< Arg2."}
|
||||
, { 'EGT', 16#24, 3, false, 3, [a,a,a], egt, "Arg0 := Arg1 >= Arg2."}
|
||||
, { 'NEQ', 16#25, 3, false, 3, [a,a,a], neq, "Arg0 := Arg1 /= Arg2."}
|
||||
, { 'AND', 16#26, 3, false, 3, [a,a,a], and_op, "Arg0 := Arg1 and Arg2."}
|
||||
, { 'OR', 16#27, 3, false, 3, [a,a,a], or_op, "Arg0 := Arg1 or Arg2."}
|
||||
, { 'NOT', 16#28, 2, false, 3, [a,a], not_op, "Arg0 := not Arg1."}
|
||||
, { 'TUPLE', 16#29, 1, false, 3, [ii], tuple, "Create a tuple of size = Arg0. Elements on stack."}
|
||||
, { 'ELEMENT', 16#2a, 4, false, 3, [t,a,a,a], element_op, "Arg1 := element(Arg2, Arg3). The element should be of type Arg1"}
|
||||
, { 'MAP_EMPTY', 16#2b, 1, false, 3, [a], map_empty, "Arg0 := #{}."}
|
||||
, { 'MAP_LOOKUP', 16#2c, 3, false, 3, [a,a,a], map_lookup, "Arg0 := lookup key Arg2 in map Arg1."}
|
||||
, { 'MAP_LOOKUPD', 16#2d, 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#2e, 4, false, 3, [a,a,a,a], map_update, "Arg0 := update key Arg2 in map Arg1 with value Arg3."}
|
||||
, { 'MAP_DELETE', 16#2f, 3, false, 3, [a,a,a], map_delete, "Arg0 := delete key Arg2 from map Arg1."}
|
||||
, { 'MAP_MEMBER', 16#30, 3, false, 3, [a,a,a], map_member, "Arg0 := true if key Arg2 is in map Arg1."}
|
||||
, { 'MAP_FROM_LIST',16#31, 2, false, 3, [a,a], map_from_list, "Arg0 := make a map from (key, value) list in Arg1."}
|
||||
, { 'NIL', 16#32, 1, false, 3, [a], nil, "Arg0 := []."}
|
||||
, { 'IS_NIL', 16#33, 2, false, 3, [a,a], is_nil, "Arg0 := true if Arg1 == []."}
|
||||
, { 'CONS', 16#34, 3, false, 3, [a,a,a], cons, "Arg0 := [Arg1|Arg2]."}
|
||||
, { 'HD', 16#35, 2, false, 3, [a,a], hd, "Arg0 := head of list Arg1."}
|
||||
, { 'TL', 16#36, 2, false, 3, [a,a], tl, "Arg0 := tail of list Arg1."}
|
||||
, { 'LENGTH', 16#37, 2, false, 3, [a,a], length, "Arg0 := length of list Arg1."}
|
||||
, { 'STR_EQ', 16#38, 3, false, 3, [a,a,a], str_eq, "Arg0 := true iff the strings Arg1 and Arg2 are the same."}
|
||||
, { 'STR_JOIN', 16#39, 3, false, 3, [a,a,a], str_join, "Arg0 := string Arg1 followed by string Arg2."}
|
||||
, { 'INT_TO_STR', 16#40, 2, false, 3, [a,a], int_to_str, "Arg0 := turn integer Arg1 into a string."}
|
||||
, { 'ADDR_TO_STR', 16#41, 2, false, 3, [a,a], addr_to_str, "Arg0 := turn address Arg1 into a string."}
|
||||
, { 'STR_REVERSE', 16#42, 2, false, 3, [a,a], str_reverse, "Arg0 := the reverse of string Arg1."}
|
||||
, { 'INT_TO_ADDR', 16#43, 2, false, 3, [a,a], int_to_addr, "Arg0 := turn integer Arg1 into an address."}
|
||||
, { 'VARIANT', 16#44, 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#45, 3, false, 3, [a,a,a], variant_test, "Arg0 := true if variant Arg1 has the tag Arg2."}
|
||||
, { 'VARIANT_ELEMENT',16#46, 3, false, 3, [a,a,a], variant_element, "Arg0 := element number Arg2 from variant Arg1."}
|
||||
, { 'BITS_NONEA', 16#47, 0, false, 3, atomic, bits_none, "accumulator := empty bitmap."}
|
||||
, { 'BITS_NONE', 16#48, 1, false, 3, [a], bits_none, "Arg0 := empty bitmap."}
|
||||
, { 'BITS_ALLA', 16#49, 0, false, 3, atomic, bits_all, "accumulator := full bitmap."}
|
||||
, { 'BITS_ALL', 16#50, 1, false, 3, [a], bits_all, "Arg0 := full bitmap."}
|
||||
, { 'BITS_ALL_N', 16#51, 2, false, 3, [a,a], bits_all_n, "Arg0 := bitmap with Arg1 bits set."}
|
||||
, { 'BITS_SET', 16#52, 3, false, 3, [a,a,a], bits_set, "Arg0 := set bit Arg2 of bitmap Arg1."}
|
||||
, { 'BITS_CLEAR', 16#53, 3, false, 3, [a,a,a], bits_clear, "Arg0 := clear bit Arg2 of bitmap Arg1."}
|
||||
, { 'BITS_TEST', 16#54, 3, false, 3, [a,a,a], bits_test, "Arg0 := true if bit Arg2 of bitmap Arg1 is set."}
|
||||
, { 'BITS_SUM', 16#55, 2, false, 3, [a,a], bits_sum, "Arg0 := sum of set bits in bitmap Arg1. Exception if infinit bitmap."}
|
||||
, { 'BITS_OR', 16#56, 3, false, 3, [a,a,a], bits_or, "Arg0 := Arg1 v Arg2."}
|
||||
, { 'BITS_AND', 16#57, 3, false, 3, [a,a,a], bits_and, "Arg0 := Arg1 ^ Arg2."}
|
||||
, { 'BITS_DIFF', 16#58, 3, false, 3, [a,a,a], bits_diff, "Arg0 := Arg1 - Arg2."}
|
||||
, { 'ADDRESS', 16#59, 1, false, 3, [a], address, "Arg0 := The current contract address."}
|
||||
, { 'BALANCE', 16#5a, 1, false, 3, [a], balance, "Arg0 := The current contract address."}
|
||||
, { 'ORIGIN', 16#5b, 1, false, 3, [a], origin, "Arg0 := Address of contract called by the call transaction."}
|
||||
, { 'CALLER', 16#5c, 1, false, 3, [a], caller, "Arg0 := The address that signed the call transaction."}
|
||||
, { 'GASPRICE', 16#5d, 1, false, 3, [a], gasprice, "Arg0 := The current gas price."}
|
||||
, { 'BLOCKHASH', 16#5e, 1, false, 3, [a], blockhash, "Arg0 := The current blockhash."} %% TODO: Do we support has at height?
|
||||
, { 'BENEFICIARY', 16#5f, 1, false, 3, [a], beneficiary, "Arg0 := The address of the current beneficiary."}
|
||||
, { 'TIMESTAMP', 16#60, 1, false, 3, [a], timestamp, "Arg0 := The current timestamp. Unrelaiable, don't use for anything."}
|
||||
, { 'GENERATION', 16#61, 1, false, 3, [a], generation, "Arg0 := The block height of the cureent generation."}
|
||||
, { 'MICROBLOCK', 16#62, 1, false, 3, [a], microblock, "Arg0 := The current micro block number."}
|
||||
, { 'DIFFICULTY', 16#63, 1, false, 3, [a], difficulty, "Arg0 := The current difficulty."}
|
||||
, { 'GASLIMIT', 16#64, 1, false, 3, [a], gaslimit, "Arg0 := The current gaslimit."}
|
||||
, { 'GAS', 16#65, 1, false, 3, [a], gas, "Arg0 := The amount of gas left."}
|
||||
|
||||
, { 'LOG0', 16#66, 2, false, 3, [a,a], log, "Create a log message in the call object."}
|
||||
, { 'LOG1', 16#67, 3, false, 3, [a,a,a], log, "Create a log message with one topic in the call object."}
|
||||
, { 'LOG2', 16#68, 4, false, 3, [a,a,a,a], log, "Create a log message with two topics in the call object."}
|
||||
, { 'LOG3', 16#69, 5, false, 3, [a,a,a,a,a], log, "Create a log message with three topics in the call object."}
|
||||
, { 'LOG4', 16#6a, 6, false, 3, [a,a,a,a,a,a], log, "Create a log message with four topics in the call object."}
|
||||
, { 'DEACTIVATE', 16#6b, 0, false, 3, atomic, deactivate, "Mark the current contract for deactication."}
|
||||
%% Transaction ops
|
||||
, { 'SPEND', 16#6c, 2, false,3, [a,a], spend, "Transfer Arg0 tokens to account Arg1. (If the contract account has at least that many tokens."}
|
||||
, { 'ORACLE_REGISTER', 16#6d, 6, false,3, [a,a,a,a,a,a], oracle_register, "Mark the current contract for deactication."}
|
||||
%% TODO:
|
||||
, { 'ORACLE_QUERY', 16#6e, 0, false,3, atomic, oracle_query, ""}
|
||||
, { 'ORACLE_RESPOND', 16#6f, 0, false,3, atomic, oracle_respond, ""}
|
||||
, { 'ORACLE_EXTEND', 16#70, 0, false,3, atomic, oracle_extend, ""}
|
||||
, { 'ORACLE_GET_ANSWER', 16#71, 0, false,3, atomic, oracle_get_answer, ""}
|
||||
, { 'ORACLE_GET_QUESTION', 16#72, 0, false,3, atomic,oracle_get_question, ""}
|
||||
, { 'ORACLE_QUERY_FEE', 16#73, 0, false,3, atomic, oracle_query_fee, ""}
|
||||
, { 'AENS_RESOLVE', 16#74, 0, false,3, atomic, aens_resolve, ""}
|
||||
, { 'AENS_PRECLAIM', 16#75, 0, false,3, atomic, aens_preclaim, ""}
|
||||
, { 'AENS_CLAIM', 16#76, 0, false,3, atomic, aens_claim, ""}
|
||||
, { 'AENS_UPDATE', 16#77, 0, false,3, atomic, aend_update, ""}
|
||||
, { 'AENS_TRANSFER', 16#78, 0, false,3, atomic, aens_transfer, ""}
|
||||
, { 'AENS_REVOKE', 16#79, 0, false,3, atomic, aens_revoke, ""}
|
||||
, { 'ECVERIFY', 16#7a, 0, false,3, atomic, ecverify, ""}
|
||||
, { 'SHA3', 16#7b, 0, false,3, atomic, sha3, ""}
|
||||
, { 'SHA256', 16#7c, 0, false,3, atomic, sha256, ""}
|
||||
, { 'BLAKE2B', 16#7d, 0, false,3, atomic, blake2b, ""}
|
||||
|
||||
, {'ABORT', 16#fb, 1, false, 3, [a], abort, "Abort execution (dont use all gas) with error message in Arg0."}
|
||||
, {'EXIT', 16#fc, 1, false, 3, [a], exit, "Abort execution (use upp all gas) with error message in Arg0."}
|
||||
, { 'NOP', 16#fd, 0, false, 1, atomic, nop, "The no op. does nothing."}
|
||||
%% FUNCTION 16#fe "Function declaration and entrypoint."
|
||||
%% EXTEND 16#ff "Reserved for future extensions beyond one byte opcodes."
|
||||
].
|
||||
|
||||
|
||||
generate_header_file(Filename, Ops) ->
|
||||
{ok, File} = file:open(Filename, [write]),
|
||||
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, SrcDir, Ops) ->
|
||||
Filename = SrcDir ++ atom_to_list(Modulename) ++ ".erl",
|
||||
|
||||
{ok, File} = file:open(Filename, [write]),
|
||||
Mnemonic = lists:flatten([gen_mnemonic(Op) || Op <- Ops]),
|
||||
ToOp = lists:flatten([gen_m_to_op(Op) || Op <- Ops]),
|
||||
Args = lists:flatten([gen_args(Op) || Op <- Ops]),
|
||||
EndBB = lists:flatten([gen_bb(Op) || Op <- Ops]),
|
||||
|
||||
io:format(File, "~s", [prelude("Provides opcode primitives.\n")]),
|
||||
io:format(File, "~s", [ops_exports(Modulename, HrlFile,
|
||||
["args/1\n"
|
||||
" , end_bb/1\n"
|
||||
" , mnemonic/1\n"
|
||||
" , m_to_op/1\n"
|
||||
])]),
|
||||
|
||||
io:format(File, "%% FATE mnemonics\n~s", [Mnemonic]),
|
||||
io:format(File, "mnemonic(Op) -> exit({bad_opcode, Op}).\n\n", []),
|
||||
|
||||
io:format(File, "%% FATE opcodes\n~s", [ToOp]),
|
||||
io:format(File, "m_to_op(M) -> exit({bad_mnemonic, M}).\n\n", []),
|
||||
|
||||
io:format(File, "%% FATE numbers of args to op.\n~s", [Args]),
|
||||
io:format(File, "args(Op) -> exit({bad_opcode, Op}).\n\n", []),
|
||||
|
||||
io:format(File, "%% Does FATE Op end a Basic Block?\n~s", [EndBB]),
|
||||
io:format(File, "end_bb(_) -> false.\n\n", []),
|
||||
|
||||
file:close(File).
|
||||
|
||||
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]),
|
||||
TypeExports = lists:flatten([gen_type_exports(Op) || Op <- Ops]),
|
||||
[#{type_name := FirstType} | RestOfOps] = Ops,
|
||||
FateTypes = lists:flatten([gen_fate_code_type(Op) || Op <- RestOfOps]),
|
||||
ConstructorExports = lists:flatten([gen_constructor_exports(Op) || Op <- Ops]),
|
||||
Constructors = lists:flatten([gen_constructors(Op) || Op <- Ops]),
|
||||
|
||||
io:format(File, "~s", [prelude(" Provide constructor functuions for "
|
||||
"Fate instructions.\n%%% Provide types"
|
||||
" and documentation for Fate "
|
||||
"instructions.\n")]),
|
||||
io:format(File, "-module(~w).\n\n", [Modulename]),
|
||||
io:format(File, "-include_lib(\"aebytecode/include/aeb_fate_data.hrl\").\n\n"
|
||||
"-define(i(__X__), {immediate, __X__ }).\n\n"
|
||||
"-type fate_arg_immediate(T) :: {immediate, T}.\n"
|
||||
"-type fate_arg_var() :: {var, integer()}.\n"
|
||||
"-type fate_arg_arg() :: {arg, integer()}.\n"
|
||||
"-type fate_arg_stack() :: {stack, integer()}.\n"
|
||||
"-type fate_arg() :: fate_arg_immediate()\n"
|
||||
" | fate_arg_var()\n"
|
||||
" | fate_arg_arg()\n"
|
||||
" | 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]),
|
||||
io:format(File, "-export_type([ fate_code/0\n~s ]).\n\n", [TypeExports]),
|
||||
io:format(File, "-export([ foo/0\n~s ]).\n\n", [ConstructorExports]),
|
||||
io:format(File, "~s\n", [Constructors]),
|
||||
|
||||
io:format(File, "foo() -> \"A temp hack.\".\n", []),
|
||||
|
||||
file:close(File).
|
||||
|
||||
gen_type(#{type_name := TypeName, type := Type}) ->
|
||||
lists:flatten(io_lib:format("-type ~-26s :: ~s.\n",
|
||||
[TypeName, Type])).
|
||||
|
||||
gen_fate_code_type(#{type_name := TypeName}) ->
|
||||
lists:flatten(io_lib:format(" | ~s\n", [TypeName])).
|
||||
|
||||
gen_type_exports(#{type_name := TypeName}) ->
|
||||
lists:flatten(io_lib:format(" , ~s/0\n", [TypeName--"()"])).
|
||||
|
||||
gen_constructor_exports(#{constructor_type := Function}) ->
|
||||
lists:flatten(io_lib:format(" , ~s\n", [Function])).
|
||||
|
||||
gen_constructors(#{constructor := Function, format := atomic,
|
||||
type_name := Type, opname := Name}) ->
|
||||
lists:flatten(io_lib:format("-spec ~s() -> ~s.\n"
|
||||
"~s() ->\n"
|
||||
" ~w.\n\n",
|
||||
[Function, Type, Function, Name]));
|
||||
gen_constructors(#{constructor := Function, format := ArgSpec,
|
||||
type_name := Type, opname := Name}) ->
|
||||
ArgTypeSpecs = gen_arg_type_specs(ArgSpec),
|
||||
Args = gen_arg_names(0, ArgSpec),
|
||||
UseArgs = gen_arg_uses(0, ArgSpec),
|
||||
lists:flatten(io_lib:format("-spec ~s(~s) -> ~s.\n"
|
||||
"~s(~s) ->\n"
|
||||
" {~w, ~s}.\n\n",
|
||||
[Function, ArgTypeSpecs, Type,
|
||||
Function, Args, Name, UseArgs])).
|
||||
|
||||
gen_arg_type_specs([]) -> [];
|
||||
gen_arg_type_specs([a]) -> "fate_arg()";
|
||||
gen_arg_type_specs([is]) -> "aeb_fate_data:fate_string()";
|
||||
gen_arg_type_specs([ii]) -> "aeb_fate_data:fate_integer()";
|
||||
gen_arg_type_specs([li]) -> "[aeb_fate_data:fate_integer()]";
|
||||
gen_arg_type_specs([t]) -> "aeb_fate_data:fate_type_type()";
|
||||
gen_arg_type_specs([a | Args]) -> "fate_arg(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([is | Args]) -> "aeb_fate_data:fate_string(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([ii | Args]) -> "aeb_fate_data:fate_integer(), " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([li | Args]) -> "[aeb_fate_data:fate_integer()], " ++ gen_arg_type_specs(Args);
|
||||
gen_arg_type_specs([t | Args]) -> "aeb_fate_data:fate_type_type(), " ++ gen_arg_type_specs(Args).
|
||||
|
||||
|
||||
gen_arg_names(_, []) ->
|
||||
[];
|
||||
gen_arg_names(N, [_]) -> io_lib:format("Arg~w", [N]);
|
||||
gen_arg_names(N, [_|Args]) ->
|
||||
io_lib:format("Arg~w, ", [N]) ++ gen_arg_names(N+1, Args).
|
||||
|
||||
gen_arg_uses(_, []) ->
|
||||
[];
|
||||
gen_arg_uses(N, [a]) -> io_lib:format("Arg~w", [N]);
|
||||
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]) ->
|
||||
io_lib:format("Arg~w, ", [N]) ++ gen_arg_uses(N+1, 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]) ->
|
||||
io_lib:format("{immediate, Arg~w}, ", [N]) ++ gen_arg_uses(N+1, 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]) ->
|
||||
io_lib:format("Arg~w, ", [N]) ++ gen_arg_uses(N+1, Args).
|
||||
|
||||
|
||||
ops_exports(Module, HrlFile, Exports) ->
|
||||
lists:flatten(io_lib:format(
|
||||
"-module(~w).\n\n"
|
||||
"-export([ ~s ]).\n\n"
|
||||
"-include_lib(\"aebytecode/" ++ HrlFile ++"\").\n\n"
|
||||
"%%====================================================================\n"
|
||||
"%% API\n"
|
||||
"%%====================================================================\n",
|
||||
[Module, Exports])).
|
||||
|
||||
gen_mnemonic(#{opname := Name, macro := Macro}) ->
|
||||
lists:flatten(io_lib:format("mnemonic(~21s) -> ~21w ;\n",
|
||||
[Macro, Name])).
|
||||
|
||||
|
||||
gen_m_to_op(#{opname := Name, macro := Macro}) ->
|
||||
lists:flatten(io_lib:format("m_to_op(~21w) -> ~21s ;\n",
|
||||
[Name, Macro])).
|
||||
|
||||
gen_args(#{macro := Macro, args := Args}) ->
|
||||
lists:flatten(io_lib:format("args(~21s) -> ~2w ;\n",
|
||||
[Macro, Args])).
|
||||
|
||||
gen_bb(#{macro := Macro, end_bb := EndBB}) ->
|
||||
lists:flatten(io_lib:format("end_bb(~21s) -> ~w ;\n",
|
||||
[Macro, EndBB])).
|
||||
|
||||
|
||||
prelude(Doc) ->
|
||||
"%%%-------------------------------------------------------------------\n"
|
||||
"%%% @copyright (C) 2019, Aeternity Anstalt\n"
|
||||
"%%%\n"
|
||||
"%%% === === N O T E : This file is generated do not edit. === ===\n"
|
||||
"%%%\n"
|
||||
"%%% Source is in aeb_fate_generate_ops.erl\n"
|
||||
"%%% @doc\n"
|
||||
"%%% "++Doc++
|
||||
"%%% @end\n"
|
||||
"%%%-------------------------------------------------------------------\n\n".
|
||||
|
||||
|
||||
gen_defines(#{opname := Name, opcode := OpCode}) ->
|
||||
lists:flatten(io_lib:format("-define(~-26w, 16#~2.16.0b).\n", [Name, OpCode])).
|
||||
|
||||
gen([]) ->
|
||||
[];
|
||||
gen([{OpName, OpCode, Args, EndBB, Gas, FateFormat, Constructor, Doc} | Rest]) ->
|
||||
Name = atom_to_list(OpName),
|
||||
LowerName = string:to_lower(Name),
|
||||
TypeName = "fate_" ++ LowerName ++ "()",
|
||||
Macro = "?" ++ Name,
|
||||
Type = case FateFormat of
|
||||
atomic -> io_lib:format("~w", [OpName]);
|
||||
ArgTypes ->
|
||||
io_lib:format("{~w, ~s}", [OpName, expand_types(ArgTypes)])
|
||||
end,
|
||||
ConstructorType = atom_to_list(Constructor) ++ "/" ++ io_lib:format("~w", [Args]),
|
||||
|
||||
[#{ opname => OpName
|
||||
, opcode => OpCode
|
||||
, args => Args
|
||||
, end_bb => EndBB
|
||||
, format => FateFormat
|
||||
, macro => Macro
|
||||
, type_name => TypeName
|
||||
, doc => Doc
|
||||
, gas => Gas
|
||||
, type => Type
|
||||
, constructor => Constructor
|
||||
, constructor_type => ConstructorType
|
||||
}| gen(Rest)].
|
||||
|
||||
|
||||
expand_types([]) -> "";
|
||||
expand_types([T]) -> expand_type(T);
|
||||
expand_types([T|Ts]) ->expand_type(T) ++ ", " ++ expand_types(Ts).
|
||||
|
||||
expand_type(a) -> "fate_arg()";
|
||||
expand_type(is) -> "fate_arg_immediate(aeb_fate_data:fate_string())";
|
||||
expand_type(ii) -> "fate_arg_immediate(aeb_fate_data:fate_integer())";
|
||||
expand_type(li) -> "[fate_arg_immediate(aeb_fate_data:fate_integer())]";
|
||||
expand_type(t) -> "aeb_fate_data:fate_type_type()".
|
||||
|
||||
generate_scanner(TemplateFile, Outfile, Path, Ops) ->
|
||||
{ok, Template} = file:read_file(filename:join(Path,TemplateFile)),
|
||||
Tokens = lists:flatten([gen_token(Op) || Op <- Ops]),
|
||||
NewFile = insert_tokens_in_template(Template, Tokens),
|
||||
file:write_file(filename:join(Path, Outfile), NewFile).
|
||||
|
||||
gen_token(#{opname := OpName}) ->
|
||||
Name = atom_to_list(OpName),
|
||||
io_lib:format("~-28s: {token, {mnemonic, TokenLine, ~w}}.\n",
|
||||
[Name, OpName]).
|
||||
|
||||
insert_tokens_in_template(<<"###REPLACEWITHOPTOKENS###", Rest/binary >>, Tokens) ->
|
||||
[Tokens, Rest];
|
||||
insert_tokens_in_template(<<"###REPLACEWITHNOTE###", Rest/binary >>, Tokens) ->
|
||||
[
|
||||
"%%%\n"
|
||||
"%%% === === N O T E : This file is generated do not edit. === ===\n"
|
||||
"%%%\n"
|
||||
"%%% Source is in aeb_fate_generate_ops.erl\n"
|
||||
"%%% and aeb_fate_asm_scan.template"
|
||||
| insert_tokens_in_template(Rest, Tokens)];
|
||||
insert_tokens_in_template(<<B,Rest/binary>>, Tokens) ->
|
||||
[B|insert_tokens_in_template(Rest, Tokens)].
|
||||
|
||||
|
||||
|
@ -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.
|
Loading…
x
Reference in New Issue
Block a user