Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d056dc620 | |||
| a51a864059 | |||
| 899bff9111 | |||
| b5daedaf95 | |||
| 8dd8e89c1e | |||
| dd1a6a9c3d | |||
| 161b5a6106 | |||
| 268208ec98 | |||
| 9411a131fc | |||
| c624f4956c | |||
| ab150ce7f8 | |||
| c85af9e7f3 |
@@ -19,7 +19,7 @@ jobs:
|
|||||||
- dialyzer-cache-v1-
|
- dialyzer-cache-v1-
|
||||||
- run:
|
- run:
|
||||||
name: Build
|
name: Build
|
||||||
command: rebar3 compile
|
command: make
|
||||||
- run:
|
- run:
|
||||||
name: Static Analysis
|
name: Static Analysis
|
||||||
command: make dialyzer
|
command: make dialyzer
|
||||||
|
|||||||
@@ -16,4 +16,3 @@ aefateasm
|
|||||||
include/aeb_fate_opcodes.hrl
|
include/aeb_fate_opcodes.hrl
|
||||||
src/aeb_fate_code.erl
|
src/aeb_fate_code.erl
|
||||||
src/aeb_fate_opcodes.erl
|
src/aeb_fate_opcodes.erl
|
||||||
src/aeb_fate_pp.erl
|
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
GENERATED_SRC = src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl src/aeb_fate_pp.erl
|
|
||||||
GENERATOR_DEPS = ebin/aeb_fate_generate_ops.beam src/aeb_fate_asm_scan.template
|
|
||||||
REBAR ?= rebar3
|
REBAR ?= rebar3
|
||||||
|
|
||||||
all: local
|
all: local
|
||||||
|
|
||||||
sources: $(GENERATED_SRC)
|
local: src/aeb_fate_opcodes.erl src/aeb_fate_code.erl include/aeb_fate_opcodes.hrl src/aeb_fate_asm_scan.xrl
|
||||||
|
|
||||||
local: $(GENERATED_SRC)
|
|
||||||
@$(REBAR) as local release
|
@$(REBAR) as local release
|
||||||
|
|
||||||
console: local
|
console: local
|
||||||
@@ -14,12 +12,15 @@ console: local
|
|||||||
|
|
||||||
clean:
|
clean:
|
||||||
@$(REBAR) clean
|
@$(REBAR) clean
|
||||||
rm -f $(GENERATED_SRC)
|
rm -f src/aeb_fate_opcodes.erl
|
||||||
rm -f ebin/*
|
rm -f src/aeb_fate_code.erl
|
||||||
|
rm -f include/aeb_fate_opcodes.hrl
|
||||||
|
|
||||||
dialyzer: local
|
dialyzer: local
|
||||||
@$(REBAR) as local dialyzer
|
@$(REBAR) as local dialyzer
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
distclean: clean
|
distclean: clean
|
||||||
@rm -rf _build/
|
@rm -rf _build/
|
||||||
|
|
||||||
@@ -29,8 +30,12 @@ eunit: local
|
|||||||
test: local
|
test: local
|
||||||
@$(REBAR) as local eunit
|
@$(REBAR) as local eunit
|
||||||
|
|
||||||
ebin/%.beam: src/%.erl
|
|
||||||
|
ebin/aeb_fate_generate_ops.beam: src/aeb_fate_generate_ops.erl ebin
|
||||||
erlc -o $(dir $@) $<
|
erlc -o $(dir $@) $<
|
||||||
|
|
||||||
$(GENERATED_SRC): $(GENERATOR_DEPS)
|
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/
|
erl -pa ebin/ -noshell -s aeb_fate_generate_ops gen_and_halt src/ include/
|
||||||
|
|
||||||
|
ebin:
|
||||||
|
mkdir ebin
|
||||||
|
|||||||
@@ -1,110 +1,9 @@
|
|||||||
# aebytecode
|
aebytecode
|
||||||
An library and stand alone assembler for aeternity bytecode.
|
=====
|
||||||
|
|
||||||
This version supports Aevm bytecode and Fate bytecode.
|
An OTP library
|
||||||
|
|
||||||
## Build
|
Build
|
||||||
|
-----
|
||||||
$ make
|
|
||||||
|
|
||||||
## Fate Code
|
|
||||||
|
|
||||||
Fate code exists in 3 formats:
|
|
||||||
|
|
||||||
1. Fate byte code. This format is under consensus.
|
|
||||||
2. Fate assembler. This is a text represenation of fate code.
|
|
||||||
This is not under consensus and other
|
|
||||||
implemenation and toolchains could have
|
|
||||||
their own format.
|
|
||||||
3. Internal. This is an Erlang representation of fate code
|
|
||||||
Used by this particular engin implementation.
|
|
||||||
|
|
||||||
This library handles all tree representations.
|
|
||||||
The byte code format is described in a separate document.
|
|
||||||
The internal format is described in a separate document.
|
|
||||||
The text representation is described below.
|
|
||||||
|
|
||||||
### Fate Assembler Code
|
|
||||||
|
|
||||||
Assembler code can be read from a file.
|
|
||||||
The assembler has the following format:
|
|
||||||
|
|
||||||
Comments start with 2 semicolons and runs till end of line
|
|
||||||
`;; This is a comment`
|
|
||||||
|
|
||||||
Opcode mnemonics start with an upper case letter.
|
|
||||||
`DUP`
|
|
||||||
|
|
||||||
Identifiers start with a lower case letter
|
|
||||||
`an_identifier`
|
|
||||||
|
|
||||||
References to function arguments start with arg followed by an integer
|
|
||||||
`arg0`
|
|
||||||
|
|
||||||
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`
|
|
||||||
|
|
||||||
Immediate values can be of 9 types:
|
|
||||||
|
|
||||||
1. Integers as decimals: {Digits} or -{Digits}
|
|
||||||
`42`
|
|
||||||
`-2374683271468723648732648736498712634876147`
|
|
||||||
And integers as Hexadecimals:: 0x{Hexdigits}
|
|
||||||
`0x0deadbeef0`
|
|
||||||
|
|
||||||
2. addresses, a base58 encoded string starting with # followed by a number of base58chars
|
|
||||||
`#nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv`
|
|
||||||
|
|
||||||
3. Boolean true or false
|
|
||||||
`true`
|
|
||||||
`false`
|
|
||||||
|
|
||||||
4. Strings "{Characters}"
|
|
||||||
`"Hello"`
|
|
||||||
|
|
||||||
5. Map { Key => Value }
|
|
||||||
`{}`
|
|
||||||
`{ 1 => { "foo" => true, "bar" => false}`
|
|
||||||
|
|
||||||
6. Lists [ Elements ]
|
|
||||||
`[]`
|
|
||||||
`[1, 2]`
|
|
||||||
|
|
||||||
7. Bit field < Bits > or !< Bits >
|
|
||||||
`<000>`
|
|
||||||
`<1010 1010>`
|
|
||||||
`<>`
|
|
||||||
`!<>`
|
|
||||||
|
|
||||||
8. Tuples ( Elements )
|
|
||||||
`()`
|
|
||||||
`(1, "foo")`
|
|
||||||
|
|
||||||
9. Variants: (| Size | Tag | ( Elements ) |)
|
|
||||||
`(| 42 | 12 | ( "foo", 12) |)`
|
|
||||||
|
|
||||||
Where
|
|
||||||
|
|
||||||
Digits: [0123456789]
|
|
||||||
|
|
||||||
Hexdigits: [0123456789abcdef]
|
|
||||||
|
|
||||||
base58char: [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
|
|
||||||
|
|
||||||
Characters: any printable ascii character 0..255 (except " no quoting yet)
|
|
||||||
|
|
||||||
Key: any value except for a map
|
|
||||||
|
|
||||||
Bits: 01 or space
|
|
||||||
|
|
||||||
Elements: Nothing or Value , Elements
|
|
||||||
|
|
||||||
Size: Digits (0 < Size < 256)
|
|
||||||
|
|
||||||
Tag: Digits (0 =< Tag < Size)
|
|
||||||
|
|
||||||
|
$ rebar3 compile
|
||||||
|
|||||||
@@ -12,11 +12,6 @@
|
|||||||
{escript_main_app, aebytecode}.
|
{escript_main_app, aebytecode}.
|
||||||
{escript_name, aefateasm}.
|
{escript_name, aefateasm}.
|
||||||
{escript_emu_args, "%%!"}.
|
{escript_emu_args, "%%!"}.
|
||||||
|
|
||||||
{pre_hooks,
|
|
||||||
[{"(linux|darwin|solaris|win32)", compile, "make sources"},
|
|
||||||
{"(freebsd)", compile, "gmake sources"}]}.
|
|
||||||
|
|
||||||
{provider_hooks, [{post, [{compile, escriptize}]}]}.
|
{provider_hooks, [{post, [{compile, escriptize}]}]}.
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+214
-376
@@ -2,21 +2,6 @@
|
|||||||
%%% @copyright (C) 2019, Aeternity Anstalt
|
%%% @copyright (C) 2019, Aeternity Anstalt
|
||||||
%%% @doc Assembler for Fate machine code.
|
%%% @doc Assembler for Fate machine code.
|
||||||
%%%
|
%%%
|
||||||
%%% Fate code exists in 3 formats:
|
|
||||||
%%%
|
|
||||||
%%% 1. Fate byte code. This format is under consensus.
|
|
||||||
%%% 2. Fate assembler. This is a text represenation of fate code.
|
|
||||||
%%% This is not under consensus and other
|
|
||||||
%%% implemenation and toolchains could have
|
|
||||||
%%% their own format.
|
|
||||||
%%% 3. Internal. This is an Erlang representation of fate code
|
|
||||||
%%% Used by this particular engin implementation.
|
|
||||||
%%%
|
|
||||||
%%% This library handles all tree representations.
|
|
||||||
%%% The byte code format is described in a separate document.
|
|
||||||
%%% The internal format is described in a separate document.
|
|
||||||
%%% The text representation is described here:
|
|
||||||
%%%
|
|
||||||
%%% Assembler code can be read from a file.
|
%%% Assembler code can be read from a file.
|
||||||
%%% The assembler has the following format
|
%%% The assembler has the following format
|
||||||
%%% Comments start with 2 semicolons and runs till end of line
|
%%% Comments start with 2 semicolons and runs till end of line
|
||||||
@@ -34,47 +19,33 @@
|
|||||||
%%% stack1
|
%%% stack1
|
||||||
%%% a
|
%%% a
|
||||||
%%%
|
%%%
|
||||||
%%% Immediate values can be of 9 types:
|
%%% Immediates can be of 9 types:
|
||||||
%%% 1a. Integers as decimals: {Digits} or -{Digits}
|
%%% 1. Integers
|
||||||
%%% 42
|
%%% 42
|
||||||
%%% -2374683271468723648732648736498712634876147
|
%%% -2374683271468723648732648736498712634876147
|
||||||
%%% 1b. Integers as Hexadecimals:: 0x{Hexdigits}
|
%%% 2. Hexadecimal integers starting with 0x
|
||||||
%%% 0x0deadbeef0
|
%%% 0x0deadbeef0
|
||||||
%%% 2. addresses, a base58 encoded string starting with #{base58char}
|
%%% 3. addresses, a 256-bit hash strings starting with #
|
||||||
%%% followed by up to 64 hex chars
|
%%% followed by up to 64 hex chars
|
||||||
%%% #00000deadbeef
|
%%% #00000deadbeef
|
||||||
%%% 3. Boolean true or false
|
%%% 4. Boolean
|
||||||
%%% true
|
%%% true
|
||||||
%%% false
|
%%% false
|
||||||
%%% 4. Strings "{Characters}"
|
%%% 5. Strings
|
||||||
%%% "Hello"
|
%%% "Hello"
|
||||||
%%% 5. Map { Key => Value }
|
%%% 6. Empty map
|
||||||
%%% {}
|
%%% {}
|
||||||
%%% { 1 => { "foo" => true, "bar" => false}
|
%%% 7. Lists
|
||||||
%%% 6. Lists [ Elements ]
|
|
||||||
%%% []
|
%%% []
|
||||||
%%% [1, 2]
|
%%% [1, 2]
|
||||||
%%% 7. Bit field < Bits > or !< Bits >
|
%%% 8. Bit field
|
||||||
%%% <000>
|
%%% <000>
|
||||||
%%% <1010 1010>
|
%%% <1010>
|
||||||
%%% <>
|
%%% <>
|
||||||
%%% !<>
|
%%% !<>
|
||||||
%%% 8. Tuples ( Elements )
|
%%% 9. Tuples
|
||||||
%%% ()
|
%%% ()
|
||||||
%%% (1, "foo")
|
%%% (1, "foo")
|
||||||
%%% 9. Variants: (| Size | Tag | ( Elements ) |)
|
|
||||||
%%% (| 42 | 12 | ( "foo", 12) |)
|
|
||||||
%%%
|
|
||||||
%%% Where Digits: [0123456789]
|
|
||||||
%%% Hexdigits: [0123456789abcdef]
|
|
||||||
%%% base58char: [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
|
|
||||||
%%% Characters any printable ascii character 0..255 (except " no quoting yet)
|
|
||||||
%%% Key: any value except for a map
|
|
||||||
%%% Bits: 01 or space
|
|
||||||
%%% Elements: Nothing or Value , Elements
|
|
||||||
%%% Size: Digits
|
|
||||||
%%% Tag: Digits
|
|
||||||
%%%
|
|
||||||
%%% @end
|
%%% @end
|
||||||
%%% Created : 21 Dec 2017
|
%%% Created : 21 Dec 2017
|
||||||
%%%-------------------------------------------------------------------
|
%%%-------------------------------------------------------------------
|
||||||
@@ -113,7 +84,7 @@ parse_function_call([{id,_,Name}, {'(',_}| Rest]) ->
|
|||||||
|
|
||||||
to_args([{')', _}]) -> {[], []};
|
to_args([{')', _}]) -> {[], []};
|
||||||
to_args(Tokens) ->
|
to_args(Tokens) ->
|
||||||
case parse_value(Tokens) of
|
case to_data(Tokens) of
|
||||||
{Arg, [{',', _} | Rest]} ->
|
{Arg, [{',', _} | Rest]} ->
|
||||||
{More, Rest2} = to_args(Rest),
|
{More, Rest2} = to_args(Rest),
|
||||||
{[Arg|More], Rest2};
|
{[Arg|More], Rest2};
|
||||||
@@ -121,6 +92,13 @@ to_args(Tokens) ->
|
|||||||
{[Arg], Rest}
|
{[Arg], Rest}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
to_data([{int,_line, Int}|Rest]) ->
|
||||||
|
{Int, Rest};
|
||||||
|
to_data([{boolean,_line, Bool}|Rest]) ->
|
||||||
|
{Bool, Rest};
|
||||||
|
to_data([{hash,_line, Hash}|Rest]) ->
|
||||||
|
{Hash, Rest}.
|
||||||
|
|
||||||
pp(FateCode) ->
|
pp(FateCode) ->
|
||||||
Listing = to_asm(FateCode),
|
Listing = to_asm(FateCode),
|
||||||
io_lib:format("~ts~n",[Listing]).
|
io_lib:format("~ts~n",[Listing]).
|
||||||
@@ -179,6 +157,14 @@ format_arg_types([T|Ts]) ->
|
|||||||
, ", "
|
, ", "
|
||||||
, format_arg_types(Ts)].
|
, format_arg_types(Ts)].
|
||||||
|
|
||||||
|
format_arg({immediate, I}) ->
|
||||||
|
aeb_fate_data:format(I);
|
||||||
|
format_arg({arg, N}) -> io_lib:format("arg~p", [N]);
|
||||||
|
format_arg({var, N}) -> io_lib:format("var~p", [N]);
|
||||||
|
format_arg({stack, 0}) -> "a";
|
||||||
|
format_arg({stack, N}) -> io_lib:format("a~p", [N]).
|
||||||
|
|
||||||
|
|
||||||
format_type(T) ->
|
format_type(T) ->
|
||||||
%% TODO: Limit to ok types.
|
%% TODO: Limit to ok types.
|
||||||
io_lib:format("~p", [T]).
|
io_lib:format("~p", [T]).
|
||||||
@@ -194,10 +180,157 @@ format_code([], _) ->
|
|||||||
"";
|
"";
|
||||||
format_code([Op|Rest], Symbols) ->
|
format_code([Op|Rest], Symbols) ->
|
||||||
[" ",
|
[" ",
|
||||||
aeb_fate_pp:format_op(Op, Symbols),
|
format_op(Op, Symbols),
|
||||||
"\n",
|
"\n",
|
||||||
format_code(Rest, Symbols)].
|
format_code(Rest, Symbols)].
|
||||||
|
|
||||||
|
format_op('RETURN', _) -> "RETURN";
|
||||||
|
format_op({'RETURNR', Arg}, _) -> ["RETURNR ", format_arg(Arg)];
|
||||||
|
format_op({'CALL', {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL ", lookup(Function, Symbols)];
|
||||||
|
format_op({'CALL_T', {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL_T ", lookup(Function, Symbols)];
|
||||||
|
format_op({'CALL_R', {immediate, Contract}, {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL_R ", lookup(Contract, Symbols), "." , lookup(Function, Symbols)];
|
||||||
|
format_op({'CALL_R', Contract, {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL_R ", format_arg(Contract), "." , lookup(Function, Symbols)];
|
||||||
|
format_op({'CALL_TR', {immediate, Contract}, {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL_TR ", lookup(Contract, Symbols), "." , lookup(Function, Symbols)];
|
||||||
|
format_op({'CALL_TR', Contract, {immediate, Function}}, Symbols) ->
|
||||||
|
["CALL_TR ", format_arg(Contract), "." , lookup(Function, Symbols)];
|
||||||
|
format_op({'JUMP', {immediate, BB}}, _) ->
|
||||||
|
["JUMP ", io_lib:format("~p", [BB])];
|
||||||
|
format_op({'JUMPIF', Arg, {immediate, BB}}, _) ->
|
||||||
|
["JUMPIF ", format_arg(Arg), " ", io_lib:format("~p", [BB])];
|
||||||
|
format_op({'SWITCH_V2', Variant, {immediate, BB1}, {immediate, BB2}}, _) ->
|
||||||
|
["SWITCH_V2 ", format_arg(Variant), " ", BB1, " ", BB2];
|
||||||
|
format_op({'SWITCH_V3', Variant, {immediate, BB1}, {immediate, BB2}, {immediate, BB3}}, _) ->
|
||||||
|
["SWITCH_V2 ", format_arg(Variant), " ", BB1, " ", BB2, " ", BB3];
|
||||||
|
format_op({'SWITCH_VN', Variant, BBs}, _) ->
|
||||||
|
["SWITCH_VN ", format_arg(Variant), [[" ", BB] || {immedate, BB} <- BBs]];
|
||||||
|
format_op({'PUSH', Arg0}, _) ->
|
||||||
|
["PUSH ", format_arg(Arg0)];
|
||||||
|
format_op('INCA', _) -> "INCA";
|
||||||
|
format_op({'INC', Name}, _) -> ["INC ", format_arg(Name)];
|
||||||
|
format_op({'DEC', Name}, _) -> ["DEC ", format_arg(Name)];
|
||||||
|
format_op('DECA', _) -> "DECA";
|
||||||
|
format_op({'ADD', Dest, Left, Right}, _) ->
|
||||||
|
["ADD ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'SUB', Dest, Left, Right}, _) ->
|
||||||
|
["SUB ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'MUL', Dest, Left, Right}, _) ->
|
||||||
|
["MUL ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'DIV', Dest, Left, Right}, _) ->
|
||||||
|
["DIV ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'MOD', Dest, Left, Right}, _) ->
|
||||||
|
["MOD ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'POW', Dest, Left, Right}, _) ->
|
||||||
|
["POW ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'LT', Dest, Left, Right}, _) ->
|
||||||
|
["LT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'GT', Dest, Left, Right}, _) ->
|
||||||
|
["GT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'ELT', Dest, Left, Right}, _) ->
|
||||||
|
["ELT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'EGT', Dest, Left, Right}, _) ->
|
||||||
|
["EGT ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'EQ', Dest, Left, Right}, _) ->
|
||||||
|
["EQ ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'NEQ', Dest, Left, Right}, _) ->
|
||||||
|
["NEQ ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'AND', Dest, Left, Right}, _) ->
|
||||||
|
["AND ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'OR', Dest, Left, Right}, _) ->
|
||||||
|
["OR ", format_arg(Dest), " ", format_arg(Left), " ", format_arg(Right)];
|
||||||
|
format_op({'NOT', Dest, Name}, _) ->
|
||||||
|
["NOT ", format_arg(Dest), " ", format_arg(Name)];
|
||||||
|
format_op({'TUPLE', {immediate, Size}}, _) ->
|
||||||
|
["TUPLE ", io_lib:format("~p", [Size])];
|
||||||
|
format_op({'ELEMENT', Type, Dest, Which, Tuple}, _) ->
|
||||||
|
[ "ELEMENT "
|
||||||
|
, io_lib:format("~p ", [Type])
|
||||||
|
, format_arg(Dest), " "
|
||||||
|
, format_arg(Which), " "
|
||||||
|
, format_arg(Tuple)];
|
||||||
|
format_op({'MAP_EMPTY', Dest}, _) ->
|
||||||
|
["MAP_EMPTY ", format_arg(Dest)];
|
||||||
|
format_op({'MAP_LOOKUP', Dest, Map, Key}, _) ->
|
||||||
|
["MAP_LOOKUP ", format_arg(Dest), " "
|
||||||
|
, format_arg(Map), " ", format_arg(Key)];
|
||||||
|
format_op({'MAP_DELETE', Dest, Map, Key}, _) ->
|
||||||
|
["MAP_DELETE ", format_arg(Dest), " "
|
||||||
|
, format_arg(Map), " ", format_arg(Key)];
|
||||||
|
format_op({'MAP_LOOKUPD', Dest, Map, Key, Default}, _) ->
|
||||||
|
["MAP_LOOKUPD ", format_arg(Dest), " "
|
||||||
|
, format_arg(Map), " ", format_arg(Key), " ", format_arg(Default)];
|
||||||
|
format_op({'MAP_UPDATE', Dest, Map, Key, Value}, _) ->
|
||||||
|
["MAP_UPDATE ", format_arg(Dest), " "
|
||||||
|
, format_arg(Map), " ", format_arg(Key), " ", format_arg(Value)];
|
||||||
|
format_op({'MAP_MEMBER', Dest, Map, Key}, _) ->
|
||||||
|
["MAP_MEMBER ", format_arg(Dest), " "
|
||||||
|
, format_arg(Map), " ", format_arg(Key)];
|
||||||
|
format_op({'MAP_FROM_LIST', Dest, List}, _) ->
|
||||||
|
["MAP_FROM_LIST ", format_arg(Dest), " ", format_arg(List)];
|
||||||
|
format_op({'NIL', Dest}, _) ->
|
||||||
|
["NIL ", format_arg(Dest)];
|
||||||
|
format_op({'IS_NIL', Dest, List}, _) ->
|
||||||
|
["IS_NIL ", format_arg(Dest), " ", format_arg(List)];
|
||||||
|
format_op({'CONS', Dest, Hd, Tl}, _) ->
|
||||||
|
["CONS ", format_arg(Dest), " ", format_arg(Hd), " ", format_arg(Tl)];
|
||||||
|
format_op({'HD', Dest, List}, _) ->
|
||||||
|
["HD ", format_arg(Dest), " ", format_arg(List)];
|
||||||
|
format_op({'TL', Dest, List}, _) ->
|
||||||
|
["TL ", format_arg(Dest), " ", format_arg(List)];
|
||||||
|
format_op({'LENGTH', Dest, List}, _) ->
|
||||||
|
["LENGTH ", format_arg(Dest), " ", format_arg(List)];
|
||||||
|
format_op({'STR_EQ', Dest, Str1, Str2}, _) ->
|
||||||
|
["STR_EQ ", format_arg(Dest), " ", format_arg(Str1), format_arg(Str2)];
|
||||||
|
format_op({'STR_JOIN', Dest, Str1, Str2}, _) ->
|
||||||
|
["STR_JOIN ", format_arg(Dest), " ", format_arg(Str1), format_arg(Str2)];
|
||||||
|
format_op({'INT_TO_STR', Dest, Str}, _) ->
|
||||||
|
["INT_TO_STR ", format_arg(Dest), " ", format_arg(Str)];
|
||||||
|
format_op({'ADDR_TO_STR', Dest, Str}, _) ->
|
||||||
|
["ADDR_TO_STR ", format_arg(Dest), " ", format_arg(Str)];
|
||||||
|
format_op({'STR_REVERSE', Dest, Str}, _) ->
|
||||||
|
["STR_REVERSE ", format_arg(Dest), " ", format_arg(Str)];
|
||||||
|
format_op({'INT_TO_ADDR', Dest, Str}, _) ->
|
||||||
|
["INT_TO_ADDR ", format_arg(Dest), " ", format_arg(Str)];
|
||||||
|
format_op({'VARIANT_TEST', Dest, Variant, Tag}, _) ->
|
||||||
|
["VARIANT_TEST ", format_arg(Dest), " ", format_arg(Variant), " ", format_arg(Tag)];
|
||||||
|
format_op({'VARIANT_ELEMENT', Dest, Variant, Index}, _) ->
|
||||||
|
["VARIANT_ELEMENT ", format_arg(Dest), " ", format_arg(Variant), " ", format_arg(Index)];
|
||||||
|
format_op({'VARIANT', Dest, SizeA, TagA, ElementsA}, _) ->
|
||||||
|
["VARIANT ", format_arg(Dest), " ", format_arg(SizeA), " "
|
||||||
|
, format_arg(TagA), " ", format_arg(ElementsA)];
|
||||||
|
format_op('BITS_NONEA', _) -> "BITS_NONEA ";
|
||||||
|
format_op({'BITS_NONE', To}, _) -> ["BITS_NONE ", format_arg(To)];
|
||||||
|
format_op('BITS_ALLA', _) -> "BITS_ALLA";
|
||||||
|
format_op({'BITS_ALL', To}, _) -> ["BITS_ALL ", format_arg(To)];
|
||||||
|
format_op({'BITS_ALL_N', To, N}, _) ->
|
||||||
|
["BITS_ALL_N ", format_arg(To), " ", format_arg(N)];
|
||||||
|
format_op({'BITS_SET', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_SET ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op({'BITS_CLEAR', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_CLEAR ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op({'BITS_TEST', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_TEST ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op({'BITS_SUM', To, Bits}, _) ->
|
||||||
|
["BITS_SUM ", format_arg(To), " ", format_arg(Bits)];
|
||||||
|
format_op({'BITS_OR', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_OR ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op({'BITS_AND', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_AND ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op({'BITS_DIFF', To, Bits, Bit}, _) ->
|
||||||
|
["BITS_DIFF ", format_arg(To), " ", format_arg(Bits), " ", format_arg(Bit)];
|
||||||
|
format_op('DUPA', _) -> "DUPA";
|
||||||
|
format_op({'DUP', {immediate, N}}, _) ->
|
||||||
|
["DUP ", io_lib:format("~p", [N])];
|
||||||
|
format_op({'POP', Dest}, _) ->
|
||||||
|
["POP ", format_arg(Dest)];
|
||||||
|
format_op({'STORE', Var, What}, _) ->
|
||||||
|
["STORE ", format_arg(Var), " ", format_arg(What)];
|
||||||
|
format_op('NOP', _) -> "NOP".
|
||||||
|
|
||||||
|
|
||||||
read_file(Filename) ->
|
read_file(Filename) ->
|
||||||
{ok, File} = file:read_file(Filename),
|
{ok, File} = file:read_file(Filename),
|
||||||
@@ -341,13 +474,14 @@ deserialize_op(?SWITCH_VN, Rest, Code) ->
|
|||||||
<<ArgType:8, Rest2/binary>> = Rest,
|
<<ArgType:8, Rest2/binary>> = Rest,
|
||||||
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
||||||
case aeb_fate_encoding:deserialize_one(Rest3) of
|
case aeb_fate_encoding:deserialize_one(Rest3) of
|
||||||
{L, Rest4} when is_list(L) ->
|
{N, Rest4} when is_integer(N), N >= 0 ->
|
||||||
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
||||||
immediate = bits_to_modifier((ArgType bsr 2) band 2#11),
|
immediate = bits_to_modifier((ArgType bsr 2) band 2#11),
|
||||||
{Rest4, [{aeb_fate_opcodes:mnemonic(?SWITCH_VN)
|
{BBs, Rest5} = deserialize_n(N, Rest4),
|
||||||
|
{Rest5, [{aeb_fate_opcodes:mnemonic(?SWITCH_VN)
|
||||||
, {Modifier0, Arg0}
|
, {Modifier0, Arg0}
|
||||||
, {immediate, L}
|
, {immediate, N}
|
||||||
}
|
, list_to_tuple(BBs)}
|
||||||
| Code]};
|
| Code]};
|
||||||
_ -> exit(bad_argument_to_switch_vn)
|
_ -> exit(bad_argument_to_switch_vn)
|
||||||
end;
|
end;
|
||||||
@@ -396,107 +530,17 @@ deserialize_op(Op, Rest, Code) ->
|
|||||||
, {Modifier1, Arg1}
|
, {Modifier1, Arg1}
|
||||||
, {Modifier2, Arg2}
|
, {Modifier2, Arg2}
|
||||||
, {Modifier3, Arg3}}
|
, {Modifier3, Arg3}}
|
||||||
| Code]};
|
|
||||||
5 ->
|
|
||||||
<<ArgType:8, ArgType2:8, Rest2/binary>> = Rest,
|
|
||||||
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
|
||||||
{Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3),
|
|
||||||
{Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4),
|
|
||||||
{Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5),
|
|
||||||
{Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6),
|
|
||||||
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
|
||||||
Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11),
|
|
||||||
Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11),
|
|
||||||
Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11),
|
|
||||||
Modifier4 = bits_to_modifier(ArgType2 band 2#11),
|
|
||||||
{Rest7, [{ OpName
|
|
||||||
, {Modifier0, Arg0}
|
|
||||||
, {Modifier1, Arg1}
|
|
||||||
, {Modifier2, Arg2}
|
|
||||||
, {Modifier3, Arg3}
|
|
||||||
, {Modifier4, Arg4}
|
|
||||||
}
|
|
||||||
| Code]};
|
|
||||||
6 ->
|
|
||||||
<<ArgType:8, ArgType2:8, Rest2/binary>> = Rest,
|
|
||||||
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
|
||||||
{Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3),
|
|
||||||
{Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4),
|
|
||||||
{Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5),
|
|
||||||
{Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6),
|
|
||||||
{Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7),
|
|
||||||
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
|
||||||
Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11),
|
|
||||||
Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11),
|
|
||||||
Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11),
|
|
||||||
Modifier4 = bits_to_modifier(ArgType2 band 2#11),
|
|
||||||
Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11),
|
|
||||||
{Rest8, [{ OpName
|
|
||||||
, {Modifier0, Arg0}
|
|
||||||
, {Modifier1, Arg1}
|
|
||||||
, {Modifier2, Arg2}
|
|
||||||
, {Modifier3, Arg3}
|
|
||||||
, {Modifier4, Arg4}
|
|
||||||
, {Modifier5, Arg5}
|
|
||||||
}
|
|
||||||
| Code]};
|
|
||||||
7 ->
|
|
||||||
<<ArgType:8, ArgType2:8, Rest2/binary>> = Rest,
|
|
||||||
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
|
||||||
{Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3),
|
|
||||||
{Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4),
|
|
||||||
{Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5),
|
|
||||||
{Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6),
|
|
||||||
{Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7),
|
|
||||||
{Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8),
|
|
||||||
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
|
||||||
Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11),
|
|
||||||
Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11),
|
|
||||||
Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11),
|
|
||||||
Modifier4 = bits_to_modifier(ArgType2 band 2#11),
|
|
||||||
Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11),
|
|
||||||
Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11),
|
|
||||||
{Rest9, [{ OpName
|
|
||||||
, {Modifier0, Arg0}
|
|
||||||
, {Modifier1, Arg1}
|
|
||||||
, {Modifier2, Arg2}
|
|
||||||
, {Modifier3, Arg3}
|
|
||||||
, {Modifier4, Arg4}
|
|
||||||
, {Modifier5, Arg5}
|
|
||||||
, {Modifier6, Arg6}
|
|
||||||
}
|
|
||||||
| Code]};
|
|
||||||
8 ->
|
|
||||||
<<ArgType:8, ArgType2:8, Rest2/binary>> = Rest,
|
|
||||||
{Arg0, Rest3} = aeb_fate_encoding:deserialize_one(Rest2),
|
|
||||||
{Arg1, Rest4} = aeb_fate_encoding:deserialize_one(Rest3),
|
|
||||||
{Arg2, Rest5} = aeb_fate_encoding:deserialize_one(Rest4),
|
|
||||||
{Arg3, Rest6} = aeb_fate_encoding:deserialize_one(Rest5),
|
|
||||||
{Arg4, Rest7} = aeb_fate_encoding:deserialize_one(Rest6),
|
|
||||||
{Arg5, Rest8} = aeb_fate_encoding:deserialize_one(Rest7),
|
|
||||||
{Arg6, Rest9} = aeb_fate_encoding:deserialize_one(Rest8),
|
|
||||||
{Arg7, Rest10} = aeb_fate_encoding:deserialize_one(Rest9),
|
|
||||||
Modifier0 = bits_to_modifier(ArgType band 2#11),
|
|
||||||
Modifier1 = bits_to_modifier((ArgType bsr 2) band 2#11),
|
|
||||||
Modifier2 = bits_to_modifier((ArgType bsr 4) band 2#11),
|
|
||||||
Modifier3 = bits_to_modifier((ArgType bsr 6) band 2#11),
|
|
||||||
Modifier4 = bits_to_modifier(ArgType2 band 2#11),
|
|
||||||
Modifier5 = bits_to_modifier((ArgType2 bsr 2) band 2#11),
|
|
||||||
Modifier6 = bits_to_modifier((ArgType2 bsr 4) band 2#11),
|
|
||||||
Modifier7 = bits_to_modifier((ArgType2 bsr 6) band 2#11),
|
|
||||||
{Rest10, [{ OpName
|
|
||||||
, {Modifier0, Arg0}
|
|
||||||
, {Modifier1, Arg1}
|
|
||||||
, {Modifier2, Arg2}
|
|
||||||
, {Modifier3, Arg3}
|
|
||||||
, {Modifier4, Arg4}
|
|
||||||
, {Modifier5, Arg5}
|
|
||||||
, {Modifier6, Arg6}
|
|
||||||
, {Modifier7, Arg7}
|
|
||||||
}
|
|
||||||
| Code]}
|
| Code]}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
deserialize_n(N, Binary) ->
|
||||||
|
deserialize_n(N, Binary, []).
|
||||||
|
|
||||||
|
deserialize_n(0, Binary, Acc) ->
|
||||||
|
{lists:reverse(Acc), Binary};
|
||||||
|
deserialize_n(N, Binary, Acc) ->
|
||||||
|
{Value, Rest} = aeb_fate_encoding:deserialize_one(Binary),
|
||||||
|
deserialize_n(N-1, Rest, [Value|Acc]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -536,114 +580,11 @@ serialize(#{functions := Functions} =_Env) ->
|
|||||||
%% bitpos: 6 4 2 0
|
%% bitpos: 6 4 2 0
|
||||||
%% xx xx xx xx
|
%% xx xx xx xx
|
||||||
%% Arg3 Arg2 Arg1 Arg0
|
%% Arg3 Arg2 Arg1 Arg0
|
||||||
%% For 5-8 args another Argument Spec Byte is used
|
|
||||||
%% Bit pattern
|
%% Bit pattern
|
||||||
%% 00 : stack/unused (depending on instruction)
|
%% 00 : stack/unused (depending on instruction)
|
||||||
%% 01 : argN
|
%% 01 : argN
|
||||||
%% 10 : varN
|
%% 10 : varN
|
||||||
%% 11 : immediate
|
%% 11 : immediate
|
||||||
serialize_code([ {Arg0Type, Arg0}
|
|
||||||
, {Arg1Type, Arg1}
|
|
||||||
, {Arg2Type, Arg2}
|
|
||||||
, {Arg3Type, Arg3}
|
|
||||||
, {Arg4Type, Arg4}
|
|
||||||
, {Arg5Type, Arg5}
|
|
||||||
, {Arg6Type, Arg6}
|
|
||||||
, {Arg7Type, Arg7}
|
|
||||||
| Rest]) ->
|
|
||||||
ArgSpec1 =
|
|
||||||
modifier_bits(Arg0Type) bor
|
|
||||||
(modifier_bits(Arg1Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg2Type) bsl 4) bor
|
|
||||||
(modifier_bits(Arg3Type) bsl 6),
|
|
||||||
ArgSpec2 =
|
|
||||||
modifier_bits(Arg4Type) bor
|
|
||||||
(modifier_bits(Arg5Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg6Type) bsl 4) bor
|
|
||||||
(modifier_bits(Arg7Type) bsl 6),
|
|
||||||
[ ArgSpec1
|
|
||||||
, ArgSpec2
|
|
||||||
, serialize_data(Arg0Type, Arg0)
|
|
||||||
, serialize_data(Arg1Type, Arg1)
|
|
||||||
, serialize_data(Arg2Type, Arg2)
|
|
||||||
, serialize_data(Arg3Type, Arg3)
|
|
||||||
, serialize_data(Arg4Type, Arg4)
|
|
||||||
, serialize_data(Arg5Type, Arg5)
|
|
||||||
, serialize_data(Arg6Type, Arg6)
|
|
||||||
, serialize_data(Arg7Type, Arg7)
|
|
||||||
| serialize_code(Rest)];
|
|
||||||
serialize_code([ {Arg0Type, Arg0}
|
|
||||||
, {Arg1Type, Arg1}
|
|
||||||
, {Arg2Type, Arg2}
|
|
||||||
, {Arg3Type, Arg3}
|
|
||||||
, {Arg4Type, Arg4}
|
|
||||||
, {Arg5Type, Arg5}
|
|
||||||
, {Arg6Type, Arg6}
|
|
||||||
| Rest]) ->
|
|
||||||
ArgSpec1 =
|
|
||||||
modifier_bits(Arg0Type) bor
|
|
||||||
(modifier_bits(Arg1Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg2Type) bsl 4) bor
|
|
||||||
(modifier_bits(Arg3Type) bsl 6),
|
|
||||||
ArgSpec2 =
|
|
||||||
modifier_bits(Arg4Type) bor
|
|
||||||
(modifier_bits(Arg5Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg6Type) bsl 4),
|
|
||||||
[ ArgSpec1
|
|
||||||
, ArgSpec2
|
|
||||||
, serialize_data(Arg0Type, Arg0)
|
|
||||||
, serialize_data(Arg1Type, Arg1)
|
|
||||||
, serialize_data(Arg2Type, Arg2)
|
|
||||||
, serialize_data(Arg3Type, Arg3)
|
|
||||||
, serialize_data(Arg4Type, Arg4)
|
|
||||||
, serialize_data(Arg5Type, Arg5)
|
|
||||||
, serialize_data(Arg6Type, Arg6)
|
|
||||||
| serialize_code(Rest)];
|
|
||||||
serialize_code([ {Arg0Type, Arg0}
|
|
||||||
, {Arg1Type, Arg1}
|
|
||||||
, {Arg2Type, Arg2}
|
|
||||||
, {Arg3Type, Arg3}
|
|
||||||
, {Arg4Type, Arg4}
|
|
||||||
, {Arg5Type, Arg5}
|
|
||||||
| Rest]) ->
|
|
||||||
ArgSpec1 =
|
|
||||||
modifier_bits(Arg0Type) bor
|
|
||||||
(modifier_bits(Arg1Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg2Type) bsl 4) bor
|
|
||||||
(modifier_bits(Arg3Type) bsl 6),
|
|
||||||
ArgSpec2 =
|
|
||||||
modifier_bits(Arg4Type) bor
|
|
||||||
(modifier_bits(Arg5Type) bsl 2),
|
|
||||||
[ ArgSpec1
|
|
||||||
, ArgSpec2
|
|
||||||
, serialize_data(Arg0Type, Arg0)
|
|
||||||
, serialize_data(Arg1Type, Arg1)
|
|
||||||
, serialize_data(Arg2Type, Arg2)
|
|
||||||
, serialize_data(Arg3Type, Arg3)
|
|
||||||
, serialize_data(Arg4Type, Arg4)
|
|
||||||
, serialize_data(Arg5Type, Arg5)
|
|
||||||
| serialize_code(Rest)];
|
|
||||||
serialize_code([ {Arg0Type, Arg0}
|
|
||||||
, {Arg1Type, Arg1}
|
|
||||||
, {Arg2Type, Arg2}
|
|
||||||
, {Arg3Type, Arg3}
|
|
||||||
, {Arg4Type, Arg4}
|
|
||||||
| Rest]) ->
|
|
||||||
ArgSpec1 =
|
|
||||||
modifier_bits(Arg0Type) bor
|
|
||||||
(modifier_bits(Arg1Type) bsl 2) bor
|
|
||||||
(modifier_bits(Arg2Type) bsl 4) bor
|
|
||||||
(modifier_bits(Arg3Type) bsl 6),
|
|
||||||
ArgSpec2 =
|
|
||||||
modifier_bits(Arg4Type),
|
|
||||||
[ ArgSpec1
|
|
||||||
, ArgSpec2
|
|
||||||
, serialize_data(Arg0Type, Arg0)
|
|
||||||
, serialize_data(Arg1Type, Arg1)
|
|
||||||
, serialize_data(Arg2Type, Arg2)
|
|
||||||
, serialize_data(Arg3Type, Arg3)
|
|
||||||
, serialize_data(Arg4Type, Arg4)
|
|
||||||
| serialize_code(Rest)];
|
|
||||||
|
|
||||||
serialize_code([ {Arg0Type, Arg0}
|
serialize_code([ {Arg0Type, Arg0}
|
||||||
, {Arg1Type, Arg1}
|
, {Arg1Type, Arg1}
|
||||||
@@ -697,19 +638,35 @@ serialize_code([ ?ELEMENT
|
|||||||
| serialize_code(Rest)];
|
| serialize_code(Rest)];
|
||||||
serialize_code([ ?SWITCH_VN
|
serialize_code([ ?SWITCH_VN
|
||||||
, {Arg0Type, Arg0}
|
, {Arg0Type, Arg0}
|
||||||
, {immediate, L}
|
, {immediate, N}
|
||||||
| Rest]) ->
|
| Rest]) when is_integer(N), N >= 0 ->
|
||||||
ArgSpec =
|
ArgSpec =
|
||||||
modifier_bits(Arg0Type) bor
|
modifier_bits(Arg0Type) bor
|
||||||
(modifier_bits(immediate) bsl 2),
|
(modifier_bits(immediate) bsl 2),
|
||||||
|
{Serialization, Rest2} = serialize_n_ints(N, Rest),
|
||||||
[?SWITCH_VN
|
[?SWITCH_VN
|
||||||
, ArgSpec
|
, ArgSpec
|
||||||
, serialize_data(Arg0Type, Arg0)
|
, serialize_data(Arg0Type, Arg0)
|
||||||
, serialize_data(immediate, L)] ++ serialize_code(Rest);
|
, serialize_data(immediate, N)
|
||||||
|
| Serialization] ++ serialize_code(Rest2);
|
||||||
serialize_code([B|Rest]) ->
|
serialize_code([B|Rest]) ->
|
||||||
[B | serialize_code(Rest)];
|
[B | serialize_code(Rest)];
|
||||||
serialize_code([]) -> [].
|
serialize_code([]) -> [].
|
||||||
|
|
||||||
|
serialize_n_ints(N, Rest) ->
|
||||||
|
serialize_n_ints(N, Rest, []).
|
||||||
|
|
||||||
|
serialize_n_ints(0, Rest, Acc) ->
|
||||||
|
%% Acc is a list of binaries.
|
||||||
|
{lists:reverse(Acc), Rest};
|
||||||
|
serialize_n_ints(N, [Int|Rest], Acc) when is_integer(Int), Int >= 0 ->
|
||||||
|
serialize_n_ints(N - 1, Rest, [aeb_fate_encoding:serialize(Int)|Acc]);
|
||||||
|
serialize_n_ints(_, [], _) ->
|
||||||
|
exit(not_enough_bbs_for_switch_vn);
|
||||||
|
serialize_n_ints(_, _, _) ->
|
||||||
|
exit(bad_bbs_value_for_switch_vn).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%% 00 : stack/unused (depending on instruction)
|
%% 00 : stack/unused (depending on instruction)
|
||||||
%% 01 : argN
|
%% 01 : argN
|
||||||
@@ -752,20 +709,7 @@ deserialize_type(<<5, Rest/binary>>) -> {bits, Rest};
|
|||||||
deserialize_type(<<6, Rest/binary>>) ->
|
deserialize_type(<<6, Rest/binary>>) ->
|
||||||
{K, Rest2} = deserialize_type(Rest),
|
{K, Rest2} = deserialize_type(Rest),
|
||||||
{V, Rest3} = deserialize_type(Rest2),
|
{V, Rest3} = deserialize_type(Rest2),
|
||||||
{{map, K, V}, Rest3};
|
{{map, K, V}, Rest3}.
|
||||||
deserialize_type(<<7, Rest/binary>>) ->
|
|
||||||
{string, Rest};
|
|
||||||
deserialize_type(<<8, Size, Rest/binary>>) ->
|
|
||||||
{Variants, Rest2} = deserialize_variants(Size, Rest, []),
|
|
||||||
{{variant, Variants}, Rest2}.
|
|
||||||
|
|
||||||
deserialize_variants(0, Rest, Variants) ->
|
|
||||||
{lists:reverse(Variants), Rest};
|
|
||||||
deserialize_variants(N, Rest, Variants) ->
|
|
||||||
{T, Rest2} = deserialize_type(Rest),
|
|
||||||
deserialize_variants(N-1, Rest2, [T|Variants]).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
deserialize_types(0, Binary, Acc) ->
|
deserialize_types(0, Binary, Acc) ->
|
||||||
{lists:reverse(Acc), Binary};
|
{lists:reverse(Acc), Binary};
|
||||||
@@ -807,35 +751,11 @@ to_bytecode([{int,_line, Int}|Rest], Address, Env, Code, Opts) ->
|
|||||||
to_bytecode(Rest, Address, Env, [{immediate, Int}|Code], Opts);
|
to_bytecode(Rest, Address, Env, [{immediate, Int}|Code], Opts);
|
||||||
to_bytecode([{boolean,_line, Bool}|Rest], Address, Env, Code, Opts) ->
|
to_bytecode([{boolean,_line, Bool}|Rest], Address, Env, Code, Opts) ->
|
||||||
to_bytecode(Rest, Address, Env, [{immediate, Bool}|Code], Opts);
|
to_bytecode(Rest, Address, Env, [{immediate, Bool}|Code], Opts);
|
||||||
to_bytecode([{string,_line, String}|Rest], Address, Env, Code, Opts) ->
|
to_bytecode([{hash,_line, Hash}|Rest], Address, Env, Code, Opts) ->
|
||||||
to_bytecode(Rest, Address, Env,
|
to_bytecode(Rest, Address, Env, [{immediate, Hash}|Code], Opts);
|
||||||
[{immediate, aeb_fate_data:make_string(String)}|Code],
|
|
||||||
Opts);
|
|
||||||
to_bytecode([{address,_line, Value}|Rest], Address, Env, Code, Opts) ->
|
|
||||||
to_bytecode(Rest, Address, Env,
|
|
||||||
[{immediate, aeb_fate_data:make_address(Value)}|Code],
|
|
||||||
Opts);
|
|
||||||
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
|
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
|
||||||
{Hash, Env2} = insert_symbol(ID, Env),
|
{Hash, Env2} = insert_symbol(ID, Env),
|
||||||
to_bytecode(Rest, Address, Env2, [{immediate, Hash}|Code], Opts);
|
to_bytecode(Rest, Address, Env2, [{immediate, Hash}|Code], Opts);
|
||||||
to_bytecode([{'{',_line}|Rest], Address, Env, Code, Opts) ->
|
|
||||||
{Map, Rest2} = parse_map(Rest),
|
|
||||||
to_bytecode(Rest2, Address, Env, [{immediate, Map}|Code], Opts);
|
|
||||||
to_bytecode([{'[',_line}|Rest], Address, Env, Code, Opts) ->
|
|
||||||
{List, Rest2} = parse_list(Rest),
|
|
||||||
to_bytecode(Rest2, Address, Env, [{immediate, List}|Code], Opts);
|
|
||||||
to_bytecode([{'(',_line}|Rest], Address, Env, Code, Opts) ->
|
|
||||||
{Elements, Rest2} = parse_tuple(Rest),
|
|
||||||
Tuple = aeb_fate_data:make_tuple(list_to_tuple(Elements)),
|
|
||||||
to_bytecode(Rest2, Address, Env, [{immediate, Tuple}|Code], Opts);
|
|
||||||
to_bytecode([{start_variant,_line}|_] = Tokens, Address, Env, Code, Opts) ->
|
|
||||||
{Size, Tag, Values, Rest} = parse_variant(Tokens),
|
|
||||||
Variant = aeb_fate_data:make_variant(Size, Tag, Values),
|
|
||||||
to_bytecode(Rest, Address, Env, [{immediate, Variant}|Code], Opts);
|
|
||||||
to_bytecode([{bits,_line, Bits}|Rest], Address, Env, Code, Opts) ->
|
|
||||||
to_bytecode(Rest, Address, Env,
|
|
||||||
[{immediate, aeb_fate_data:make_bits(Bits)}|Code], Opts);
|
|
||||||
|
|
||||||
to_bytecode([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) ->
|
to_bytecode([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) ->
|
||||||
Env2 = insert_annotation(comment, Line, Comment, Env),
|
Env2 = insert_annotation(comment, Line, Comment, Env),
|
||||||
to_bytecode(Rest, Address, Env2, Code, Opts);
|
to_bytecode(Rest, Address, Env2, Code, Opts);
|
||||||
@@ -852,73 +772,6 @@ to_bytecode([], Address, Env, Code, Opts) ->
|
|||||||
end,
|
end,
|
||||||
Env2.
|
Env2.
|
||||||
|
|
||||||
parse_map([{'}',_line}|Rest]) ->
|
|
||||||
{#{}, Rest};
|
|
||||||
parse_map(Tokens) ->
|
|
||||||
{Key, [{arrow, _} | Rest]} = parse_value(Tokens),
|
|
||||||
{Value, Rest2} = parse_value(Rest),
|
|
||||||
case Rest2 of
|
|
||||||
[{',',_} | Rest3] ->
|
|
||||||
{Map, Rest4} = parse_map(Rest3),
|
|
||||||
{Map#{Key => Value}, Rest4};
|
|
||||||
[{'}',_} | Rest3] ->
|
|
||||||
{#{Key => Value}, Rest3}
|
|
||||||
end.
|
|
||||||
|
|
||||||
parse_list([{']',_line}|Rest]) ->
|
|
||||||
{[], Rest};
|
|
||||||
parse_list(Tokens) ->
|
|
||||||
{Head , Rest} = parse_value(Tokens),
|
|
||||||
case Rest of
|
|
||||||
[{',',_} | Rest2] ->
|
|
||||||
{Tail, Rest3} = parse_list(Rest2),
|
|
||||||
{[Head | Tail], Rest3};
|
|
||||||
[{']',_} | Rest3] ->
|
|
||||||
{[Head], Rest3}
|
|
||||||
end.
|
|
||||||
|
|
||||||
parse_tuple([{')',_line}|Rest]) ->
|
|
||||||
{[], Rest};
|
|
||||||
parse_tuple(Tokens) ->
|
|
||||||
{Head , Rest} = parse_value(Tokens),
|
|
||||||
case Rest of
|
|
||||||
[{',',_} | Rest2] ->
|
|
||||||
{Tail, Rest3} = parse_tuple(Rest2),
|
|
||||||
{[Head | Tail], Rest3};
|
|
||||||
[{')',_} | Rest3] ->
|
|
||||||
{[Head], Rest3}
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
parse_variant([{start_variant,_line}
|
|
||||||
, {int,_line, Size}
|
|
||||||
, {'|',_}
|
|
||||||
, {int,_line, Tag}
|
|
||||||
, {'|',_}
|
|
||||||
, {'(',_}
|
|
||||||
| Rest]) when (Size > 0), (Tag < Size) ->
|
|
||||||
{Elements , [{end_variant, _} | Rest2]} = parse_tuple(Rest),
|
|
||||||
{Size, Tag, list_to_tuple(Elements), Rest2}.
|
|
||||||
|
|
||||||
|
|
||||||
parse_value([{int,_line, Int} | Rest]) -> {Int, Rest};
|
|
||||||
parse_value([{boolean,_line, Bool} | Rest]) -> {Bool, Rest};
|
|
||||||
parse_value([{hash,_line, Hash} | Rest]) -> {Hash, Rest};
|
|
||||||
parse_value([{'{',_line} | Rest]) -> parse_map(Rest);
|
|
||||||
parse_value([{'[',_line} | Rest]) -> parse_list(Rest);
|
|
||||||
parse_value([{'(',_line} | Rest]) ->
|
|
||||||
{T, Rest2} = parse_tuple(Rest),
|
|
||||||
{aeb_fate_data:make_tuple(list_to_tuple(T)), Rest2};
|
|
||||||
parse_value([{bits,_line, Bits} | Rest]) ->
|
|
||||||
{aeb_fate_data:make_bits(Bits), Rest};
|
|
||||||
parse_value([{start_variant,_line}|_] = Tokens) ->
|
|
||||||
{Size, Tag, Values, Rest} = parse_variant(Tokens),
|
|
||||||
Variant = aeb_fate_data:make_variant(Size, Tag, Values),
|
|
||||||
{Variant, Rest};
|
|
||||||
parse_value([{string,_line, String} | Rest]) ->
|
|
||||||
{aeb_fate_data:make_string(String), Rest};
|
|
||||||
parse_value([{address,_line, Address} | Rest]) ->
|
|
||||||
{aeb_fate_data:make_address(Address), Rest}.
|
|
||||||
|
|
||||||
to_fun_def([{id, _, Name}, {'(', _} | Rest]) ->
|
to_fun_def([{id, _, Name}, {'(', _} | Rest]) ->
|
||||||
{ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest),
|
{ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest),
|
||||||
@@ -955,16 +808,7 @@ to_type([{'{', _}, {id, _, "map"}, {',', _} | Rest]) ->
|
|||||||
%% TODO: Error handling
|
%% TODO: Error handling
|
||||||
{KeyType, [{',', _}| Rest2]} = to_type(Rest),
|
{KeyType, [{',', _}| Rest2]} = to_type(Rest),
|
||||||
{ValueType, [{'}', _}| Rest3]} = to_type(Rest2),
|
{ValueType, [{'}', _}| Rest3]} = to_type(Rest2),
|
||||||
{{map, KeyType, ValueType}, Rest3};
|
{{map, KeyType, ValueType}, Rest3}.
|
||||||
to_type([{'{', _}
|
|
||||||
, {id, _, "variant"}
|
|
||||||
, {',', _}
|
|
||||||
, {'[', _}
|
|
||||||
| Rest]) ->
|
|
||||||
%% TODO: Error handling
|
|
||||||
{ElementTypes, [{'}', _}| Rest2]} = to_list_of_types(Rest),
|
|
||||||
{{variant, ElementTypes}, Rest2}.
|
|
||||||
|
|
||||||
|
|
||||||
to_list_of_types([{']', _} | Rest]) -> {[], Rest};
|
to_list_of_types([{']', _} | Rest]) -> {[], Rest};
|
||||||
to_list_of_types(Tokens) ->
|
to_list_of_types(Tokens) ->
|
||||||
@@ -985,15 +829,9 @@ serialize_type({tuple, Ts}) ->
|
|||||||
N when N =< 255 ->
|
N when N =< 255 ->
|
||||||
[3, N | [serialize_type(T) || T <- Ts]]
|
[3, N | [serialize_type(T) || T <- Ts]]
|
||||||
end;
|
end;
|
||||||
serialize_type(address) -> [4];
|
serialize_type(address) -> 4;
|
||||||
serialize_type(bits) -> [5];
|
serialize_type(bits) -> 5;
|
||||||
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)];
|
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)].
|
||||||
serialize_type(string) -> [7];
|
|
||||||
serialize_type({variant, ListOfVariants}) ->
|
|
||||||
Size = length(ListOfVariants),
|
|
||||||
if Size < 256 ->
|
|
||||||
[8, Size | [serialize_type(T) || T <- ListOfVariants]]
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
%% -------------------------------------------------------------------
|
%% -------------------------------------------------------------------
|
||||||
|
|||||||
@@ -12,14 +12,12 @@ DIGIT = [0-9]
|
|||||||
HEXDIGIT = [0-9a-fA-F]
|
HEXDIGIT = [0-9a-fA-F]
|
||||||
LOWER = [a-z_]
|
LOWER = [a-z_]
|
||||||
UPPER = [A-Z]
|
UPPER = [A-Z]
|
||||||
BASE58 = [123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]
|
|
||||||
INT = {DIGIT}+
|
INT = {DIGIT}+
|
||||||
HEX = 0x{HEXDIGIT}+
|
HEX = 0x{HEXDIGIT}+
|
||||||
HASH = #{BASE58}+
|
HASH = #{HEXDIGIT}+
|
||||||
WS = [\000-\s]
|
WS = [\000-\s]
|
||||||
ID = {LOWER}[a-zA-Z0-9_]*
|
ID = {LOWER}[a-zA-Z0-9_]*
|
||||||
STRING = "[^"]*"
|
|
||||||
BITS = (\!)?\<[\s01]*\>
|
|
||||||
|
|
||||||
Rules.
|
Rules.
|
||||||
arg{INT} : {token, {arg, TokenLine, parse_arg(TokenChars)}}.
|
arg{INT} : {token, {arg, TokenLine, parse_arg(TokenChars)}}.
|
||||||
@@ -40,24 +38,13 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
|||||||
{token, {int, TokenLine, parse_hex(TokenChars)}}.
|
{token, {int, TokenLine, parse_hex(TokenChars)}}.
|
||||||
{INT} :
|
{INT} :
|
||||||
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
||||||
-{INT} :
|
|
||||||
{token, {int, TokenLine, parse_int(TokenChars)}}.
|
|
||||||
{HASH} :
|
{HASH} :
|
||||||
{token, {address, TokenLine, parse_hash(TokenChars)}}.
|
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
|
||||||
{STRING} :
|
|
||||||
{token, {string, TokenLine, list_to_binary(TokenChars)}}.
|
|
||||||
{BITS} :
|
|
||||||
{token, {bits, TokenLine, bits(TokenChars)}}.
|
|
||||||
|
|
||||||
|
|
||||||
%% Symbols
|
%% Symbols
|
||||||
\-\> : {token, {to, TokenLine}}.
|
\-\> : {token, {'to', TokenLine}}.
|
||||||
\: : {token, {to, TokenLine}}.
|
\: : {token, {'to', TokenLine}}.
|
||||||
|
|
||||||
\=\> : {token, {arrow, TokenLine}}.
|
|
||||||
\(\| : {token, {start_variant, TokenLine}}.
|
|
||||||
\|\) : {token, {end_variant, TokenLine}}.
|
|
||||||
|
|
||||||
, : {token, {',', TokenLine}}.
|
, : {token, {',', TokenLine}}.
|
||||||
\( : {token, {'(', TokenLine}}.
|
\( : {token, {'(', TokenLine}}.
|
||||||
\) : {token, {')', TokenLine}}.
|
\) : {token, {')', TokenLine}}.
|
||||||
@@ -65,7 +52,6 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
|||||||
\] : {token, {']', TokenLine}}.
|
\] : {token, {']', TokenLine}}.
|
||||||
\{ : {token, {'{', TokenLine}}.
|
\{ : {token, {'{', TokenLine}}.
|
||||||
\} : {token, {'}', TokenLine}}.
|
\} : {token, {'}', TokenLine}}.
|
||||||
\| : {token, {'|', TokenLine}}.
|
|
||||||
|
|
||||||
;;.* :
|
;;.* :
|
||||||
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
|
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
|
||||||
@@ -102,7 +88,8 @@ parse_acc("a" ++ N) -> list_to_integer(N).
|
|||||||
|
|
||||||
|
|
||||||
parse_hash("#" ++ Chars) ->
|
parse_hash("#" ++ Chars) ->
|
||||||
base58_to_address(Chars).
|
N = list_to_integer(Chars, 16),
|
||||||
|
<<N:256>>.
|
||||||
|
|
||||||
scan(S) ->
|
scan(S) ->
|
||||||
string(S).
|
string(S).
|
||||||
@@ -110,33 +97,3 @@ scan(S) ->
|
|||||||
drop_prefix(C, [C|Rest]) ->
|
drop_prefix(C, [C|Rest]) ->
|
||||||
drop_prefix(C, Rest);
|
drop_prefix(C, Rest);
|
||||||
drop_prefix(_, Tail) -> Tail.
|
drop_prefix(_, Tail) -> Tail.
|
||||||
|
|
||||||
bits([$!, $< | Rest]) ->
|
|
||||||
bits(Rest, -1);
|
|
||||||
bits([$< | Rest]) ->
|
|
||||||
bits(Rest, 0).
|
|
||||||
|
|
||||||
bits([$> |_Rest], Acc) -> Acc;
|
|
||||||
bits([$0 | Rest], Acc) -> bits(Rest, Acc bsl 1);
|
|
||||||
bits([$1 | Rest], Acc) -> bits(Rest, (Acc bsl 1) bor 1);
|
|
||||||
bits([$ | Rest], Acc) -> bits(Rest, Acc).
|
|
||||||
|
|
||||||
char_to_base58(C) ->
|
|
||||||
binary:at(<<0,1,2,3,4,5,6,7,8,0,0,0,0,0,0,0,9,10,11,12,13,14,15,16,0,17,
|
|
||||||
18,19,20,21,0,22,23,24,25,26,27,28,29,30,31,32,0,0,0,0,0,0,
|
|
||||||
33,34,35,36,37,38,39,40,41,42,43,0,44,45,46,47,48,49,50,51,
|
|
||||||
52,53,54,55,56,57>>, C-$1).
|
|
||||||
|
|
||||||
base58_to_integer(C, []) -> C;
|
|
||||||
base58_to_integer(C, [X | Xs]) ->
|
|
||||||
base58_to_integer(C * 58 + char_to_base58(X), Xs).
|
|
||||||
|
|
||||||
base58_to_integer([]) -> error;
|
|
||||||
base58_to_integer([Char]) -> char_to_base58(Char);
|
|
||||||
base58_to_integer([Char | Str]) ->
|
|
||||||
base58_to_integer(char_to_base58(Char), Str).
|
|
||||||
|
|
||||||
base58_to_address(Base58) ->
|
|
||||||
I = base58_to_integer(Base58),
|
|
||||||
Bin = <<I:256>>,
|
|
||||||
Bin.
|
|
||||||
+1
-15
@@ -137,30 +137,16 @@ format(?FATE_UNIT) -> "()";
|
|||||||
format(?FATE_TUPLE(T)) ->
|
format(?FATE_TUPLE(T)) ->
|
||||||
["( ", lists:join(", ", [ 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(S) when ?IS_FATE_STRING(S) -> [S];
|
||||||
format(?FATE_BITS(B)) when B >= 0 ->
|
|
||||||
["<", format_bits(B, "") , ">"];
|
|
||||||
format(?FATE_BITS(B)) when B < 0 ->
|
|
||||||
["!< ", format_nbits(-B-1, "") , " >"];
|
|
||||||
format(?FATE_VARIANT(Size, Tag, T)) ->
|
format(?FATE_VARIANT(Size, Tag, T)) ->
|
||||||
["(| ",
|
["(| ",
|
||||||
lists:join("| ", [integer_to_list(Size), integer_to_list(Tag) |
|
lists:join("| ", [integer_to_list(Size), integer_to_list(Tag) |
|
||||||
[format(make_tuple(T))]]),
|
[format(E) || E <- erlang:tuple_to_list(T)]]),
|
||||||
" |)"];
|
" |)"];
|
||||||
format(M) when ?IS_FATE_MAP(M) ->
|
format(M) when ?IS_FATE_MAP(M) ->
|
||||||
["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"];
|
["{ ", format_kvs(maps:to_list(?FATE_MAP_VALUE(M))), " }"];
|
||||||
format(?FATE_ADDRESS(Address)) -> ["#", address_to_base58(Address)];
|
format(?FATE_ADDRESS(Address)) -> ["#", address_to_base58(Address)];
|
||||||
format(V) -> exit({not_a_fate_type, V}).
|
format(V) -> exit({not_a_fate_type, V}).
|
||||||
|
|
||||||
format_bits(0, Acc) -> Acc;
|
|
||||||
format_bits(N, Acc) ->
|
|
||||||
Bit = $0 + (N band 1),
|
|
||||||
format_bits(N bsr 1, [Bit|Acc]).
|
|
||||||
|
|
||||||
format_nbits(0, Acc) -> Acc;
|
|
||||||
format_nbits(N, Acc) ->
|
|
||||||
Bit = $1 - (N band 1),
|
|
||||||
format_nbits(N bsr 1, [Bit|Acc]).
|
|
||||||
|
|
||||||
format_list(List) ->
|
format_list(List) ->
|
||||||
["[ ", lists:join(", ", [format(E) || E <- List]), " ]"].
|
["[ ", lists:join(", ", [format(E) || E <- List]), " ]"].
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ serialize(L) when ?IS_FATE_LIST(L) ->
|
|||||||
<<?LONG_LIST, Val/binary, Rest/binary>>
|
<<?LONG_LIST, Val/binary, Rest/binary>>
|
||||||
end;
|
end;
|
||||||
serialize(Map) when ?IS_FATE_MAP(Map) ->
|
serialize(Map) when ?IS_FATE_MAP(Map) ->
|
||||||
L = [{_K,_V}|_] = lists:sort(maps:to_list(?FATE_MAP_VALUE(Map))),
|
L = [{_K,_V}|_] = maps:to_list(?FATE_MAP_VALUE(Map)),
|
||||||
Size = length(L),
|
Size = length(L),
|
||||||
%% TODO: check all K same type, and all V same type
|
%% TODO: check all K same type, and all V same type
|
||||||
%% check K =/= map
|
%% check K =/= map
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
-module(aeb_fate_generate_ops).
|
-module(aeb_fate_generate_ops).
|
||||||
|
|
||||||
-export([ gen_and_halt/1
|
-export([ gen_and_halt/1
|
||||||
, generate/0
|
, generate/0]).
|
||||||
, generate_documentation/1
|
|
||||||
, test_asm_generator/1]).
|
|
||||||
|
|
||||||
gen_and_halt([SrcDirArg, IncludeDirArg]) ->
|
gen_and_halt([SrcDirArg, IncludeDirArg]) ->
|
||||||
generate(atom_to_list(SrcDirArg),
|
generate(atom_to_list(SrcDirArg),
|
||||||
@@ -20,8 +18,7 @@ generate(Src, Include) ->
|
|||||||
generate_header_file(HrlFile, Ops),
|
generate_header_file(HrlFile, Ops),
|
||||||
generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops),
|
generate_opcodes_ops(aeb_fate_opcodes, HrlFile, Src, Ops),
|
||||||
generate_code_ops(aeb_fate_code, Src, Ops),
|
generate_code_ops(aeb_fate_code, Src, Ops),
|
||||||
generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops),
|
generate_scanner("aeb_fate_asm_scan.template", "aeb_fate_asm_scan.xrl", Src, Ops).
|
||||||
gen_asm_pp(aeb_fate_pp, Src, Ops).
|
|
||||||
|
|
||||||
%% TODO: Some real gas numbers...
|
%% TODO: Some real gas numbers...
|
||||||
ops_defs() ->
|
ops_defs() ->
|
||||||
@@ -138,9 +135,6 @@ ops_defs() ->
|
|||||||
, { 'SHA256', 16#7c, 0, false,3, atomic, sha256, ""}
|
, { 'SHA256', 16#7c, 0, false,3, atomic, sha256, ""}
|
||||||
, { 'BLAKE2B', 16#7d, 0, false,3, atomic, blake2b, ""}
|
, { 'BLAKE2B', 16#7d, 0, false,3, atomic, blake2b, ""}
|
||||||
|
|
||||||
|
|
||||||
, { 'DUMMY7ARG', 16#f9, 7, false,3, [a,a,a,a,a,a,a], dummyarg, "Temporary dummy instruction to test 7 args."}
|
|
||||||
, { 'DUMMY8ARG', 16#fa, 8, false,3, [a,a,a,a,a,a,a,a],dummyarg, "Temporary dummy instruction to test 8 args."}
|
|
||||||
, {'ABORT', 16#fb, 1, false, 3, [a], abort, "Abort execution (dont use all gas) with error message in Arg0."}
|
, {'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."}
|
, {'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."}
|
, { 'NOP', 16#fd, 0, false, 1, atomic, nop, "The no op. does nothing."}
|
||||||
@@ -404,284 +398,5 @@ insert_tokens_in_template(<<"###REPLACEWITHNOTE###", Rest/binary >>, Tokens) ->
|
|||||||
insert_tokens_in_template(<<B,Rest/binary>>, Tokens) ->
|
insert_tokens_in_template(<<B,Rest/binary>>, Tokens) ->
|
||||||
[B|insert_tokens_in_template(Rest, Tokens)].
|
[B|insert_tokens_in_template(Rest, Tokens)].
|
||||||
|
|
||||||
gen_asm_pp(Module, Path, Ops) ->
|
|
||||||
Filename = filename:join(Path, atom_to_list(Module)) ++ ".erl",
|
|
||||||
{ok, File} = file:open(Filename, [write]),
|
|
||||||
Formats = lists:flatten([gen_format(Op)++"\n" || Op <- Ops]),
|
|
||||||
|
|
||||||
io:format(File, "~s", [prelude(" Provide pretty printing functuions for "
|
|
||||||
"Fate instructions.\n")]),
|
|
||||||
io:format(File, "-module(~w).\n\n", [Module]),
|
|
||||||
io:format(File,
|
|
||||||
"-export([format_op/2]).\n\n"
|
|
||||||
"format_arg(t, T) ->\n"
|
|
||||||
" io_lib:format(\"~~p \", [T]);\n"
|
|
||||||
"format_arg(li, {immediate, LI}) ->\n"
|
|
||||||
" aeb_fate_data:format(LI);\n"
|
|
||||||
"format_arg(_, {immediate, I}) ->\n"
|
|
||||||
" aeb_fate_data:format(I);\n"
|
|
||||||
"format_arg(a, {arg, N}) -> io_lib:format(\"arg~~p\", [N]);\n"
|
|
||||||
"format_arg(a, {var, N}) -> io_lib:format(\"var~~p\", [N]);\n"
|
|
||||||
"format_arg(a, {stack, 0}) -> \"a\";\n"
|
|
||||||
"format_arg(a, {stack, N}) -> io_lib:format(\"a~~p\", [N]).\n\n"
|
|
||||||
"lookup(Name, Symbols) ->\n"
|
|
||||||
" maps:get(Name, Symbols, io_lib:format(\"~~w\",[Name])).\n\n"
|
|
||||||
"~s"
|
|
||||||
, [Formats]),
|
|
||||||
|
|
||||||
io:format(File, "format_op(Op, _Symbols) -> io_lib:format(\";; Bad Op: ~~w\\n\", [Op]).\n", []),
|
|
||||||
file:close(File).
|
|
||||||
|
|
||||||
gen_format(#{opname := Name}) when ('CALL' =:= Name) or (Name =:= 'CALL_T') ->
|
|
||||||
io_lib:format("format_op({~w, {immediate, Function}}, Symbols) ->\n"
|
|
||||||
"[\"~s \", lookup(Function, Symbols)];",
|
|
||||||
[Name, atom_to_list(Name)]);
|
|
||||||
gen_format(#{opname := Name}) when (Name =:= 'CALL_R') or (Name =:= 'CALL_TR') ->
|
|
||||||
io_lib:format("format_op({~w, {immediate, Contract}, {immediate, Function}}, Symbols) ->\n"
|
|
||||||
"[\"~s \", lookup(Contract, Symbols), \".\", lookup(Function, Symbols)];\n"
|
|
||||||
"format_op({~w, Contract, {immediate, Function}}, Symbols) ->\n"
|
|
||||||
"[\"~s \", format_arg(a, Contract), \".\", lookup(Function, Symbols)];",
|
|
||||||
[Name, atom_to_list(Name), Name, atom_to_list(Name)]);
|
|
||||||
gen_format(#{opname := Name, format := atomic}) ->
|
|
||||||
io_lib:format("format_op(~w, _) -> [\"~s\"];", [Name, atom_to_list(Name)]);
|
|
||||||
gen_format(#{opname := Name, format := Args}) ->
|
|
||||||
NameAsString = atom_to_list(Name),
|
|
||||||
case Args of
|
|
||||||
[T0] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0)];",
|
|
||||||
[Name, NameAsString, T0]);
|
|
||||||
[T0, T1] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1)];",
|
|
||||||
[Name, NameAsString, T0, T1]);
|
|
||||||
[T0, T1, T2] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2]);
|
|
||||||
[T0, T1, T2, T3] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2, Arg3}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2),"
|
|
||||||
"\" \", format_arg(~w, Arg3)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2, T3]);
|
|
||||||
[T0, T1, T2, T3, T4] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2),"
|
|
||||||
"\" \", format_arg(~w, Arg3),"
|
|
||||||
"\" \", format_arg(~w, Arg4)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2, T3, T4]);
|
|
||||||
[T0, T1, T2, T3, T4, T5] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2),"
|
|
||||||
"\" \", format_arg(~w, Arg3),"
|
|
||||||
"\" \", format_arg(~w, Arg4),"
|
|
||||||
"\" \", format_arg(~w, Arg5)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2, T3, T4, T5]);
|
|
||||||
[T0, T1, T2, T3, T4, T5, T6] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2),"
|
|
||||||
"\" \", format_arg(~w, Arg3),"
|
|
||||||
"\" \", format_arg(~w, Arg4),"
|
|
||||||
"\" \", format_arg(~w, Arg5),"
|
|
||||||
"\" \", format_arg(~w, Arg6)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2, T3, T4, T5, T6]);
|
|
||||||
[T0, T1, T2, T3, T4, T5, T6, T7] ->
|
|
||||||
io_lib:format(
|
|
||||||
"format_op({~w, Arg0, Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7}, _) ->\n"
|
|
||||||
" [\"~s \", format_arg(~w, Arg0), "
|
|
||||||
"\" \", format_arg(~w, Arg1),"
|
|
||||||
"\" \", format_arg(~w, Arg2),"
|
|
||||||
"\" \", format_arg(~w, Arg3),"
|
|
||||||
"\" \", format_arg(~w, Arg4),"
|
|
||||||
"\" \", format_arg(~w, Arg5),"
|
|
||||||
"\" \", format_arg(~w, Arg6),"
|
|
||||||
"\" \", format_arg(~w, Arg7)];",
|
|
||||||
[Name, NameAsString, T0, T1, T2, T3, T4, T5, T6, T7])
|
|
||||||
end.
|
|
||||||
|
|
||||||
test_asm_generator(Filename) ->
|
|
||||||
{ok, File} = file:open(Filename, [write]),
|
|
||||||
Instructions = lists:flatten([gen_instruction(Op)++"\n" || Op <- gen(ops_defs())]),
|
|
||||||
io:format(File,
|
|
||||||
";; CONTRACT all_instructions\n\n"
|
|
||||||
";; Dont expect this contract to typecheck or run.\n"
|
|
||||||
";; Just used to check assembler rountrip of all instruction.\n\n"
|
|
||||||
"FUNCTION foo () : {tuple, []}\n"
|
|
||||||
"~s"
|
|
||||||
, [Instructions]),
|
|
||||||
io:format(File, " RETURNR ()\n", []),
|
|
||||||
file:close(File).
|
|
||||||
|
|
||||||
|
|
||||||
gen_instruction(#{opname := Name, format := atomic}) ->
|
|
||||||
io_lib:format(" ~s\n", [Name]);
|
|
||||||
gen_instruction(#{opname := Name, format := ArgTypes}) ->
|
|
||||||
Args = lists:flatten(lists:join(" ", [gen_arg(A) || A <- ArgTypes])),
|
|
||||||
I = io_lib:format(" ~s ~s\n", [Name, Args]),
|
|
||||||
I.
|
|
||||||
|
|
||||||
%% This should be done with a Quick Check generator...
|
|
||||||
gen_arg(a) -> any_arg();
|
|
||||||
gen_arg(is) -> "foo";
|
|
||||||
gen_arg(ii) -> gen_int();
|
|
||||||
gen_arg(li) -> "[1, 2, 3]";
|
|
||||||
gen_arg(t) -> "integer".
|
|
||||||
|
|
||||||
any_arg() ->
|
|
||||||
element(rand:uniform(5), {"a", stack_arg(), var_arg(), arg_arg(), imm_arg()}).
|
|
||||||
stack_arg() -> "a" ++ integer_to_list(rand:uniform(255)-1).
|
|
||||||
arg_arg() -> "arg" ++ integer_to_list(rand:uniform(256)-1).
|
|
||||||
var_arg() -> "var" ++ integer_to_list(rand:uniform(256)-1).
|
|
||||||
imm_arg() ->
|
|
||||||
case rand:uniform(15) of
|
|
||||||
1 -> gen_int();
|
|
||||||
2 -> gen_int();
|
|
||||||
3 -> gen_int();
|
|
||||||
4 -> gen_int();
|
|
||||||
5 -> gen_int();
|
|
||||||
6 -> gen_int();
|
|
||||||
7 -> gen_int();
|
|
||||||
8 -> gen_address();
|
|
||||||
9 -> gen_boolean();
|
|
||||||
10 -> gen_string();
|
|
||||||
11 -> gen_map();
|
|
||||||
12 -> gen_list();
|
|
||||||
13 -> gen_bits();
|
|
||||||
14 -> gen_tuple();
|
|
||||||
15 -> gen_variant()
|
|
||||||
end.
|
|
||||||
|
|
||||||
gen_key() ->
|
|
||||||
case rand:uniform(15) of
|
|
||||||
1 -> gen_int();
|
|
||||||
2 -> gen_int();
|
|
||||||
3 -> gen_int();
|
|
||||||
4 -> gen_int();
|
|
||||||
5 -> gen_int();
|
|
||||||
6 -> gen_int();
|
|
||||||
7 -> gen_int();
|
|
||||||
8 -> gen_address();
|
|
||||||
9 -> gen_boolean();
|
|
||||||
10 -> gen_string();
|
|
||||||
11 -> gen_string();
|
|
||||||
12 -> gen_list();
|
|
||||||
13 -> gen_bits();
|
|
||||||
14 -> gen_tuple();
|
|
||||||
15 -> gen_variant()
|
|
||||||
end.
|
|
||||||
|
|
||||||
gen_boolean() ->
|
|
||||||
element(rand:uniform(2), {"true", "false"}).
|
|
||||||
|
|
||||||
gen_int() ->
|
|
||||||
element(rand:uniform(4),
|
|
||||||
{ integer_to_list(rand:uniform(round(math:pow(10,40))))
|
|
||||||
, integer_to_list(rand:uniform(10))
|
|
||||||
, integer_to_list(rand:uniform(100))
|
|
||||||
, io_lib:format("0x~.16b",[rand:uniform(round(math:pow(10,10)))])}).
|
|
||||||
|
|
||||||
gen_address() -> "#nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv".
|
|
||||||
gen_string() -> "\"foo\"".
|
|
||||||
gen_map() -> "{ " ++ gen_key() ++ " => " ++ imm_arg() ++ "}".
|
|
||||||
gen_list() ->
|
|
||||||
case rand:uniform(4) of
|
|
||||||
1 -> "[]";
|
|
||||||
2 -> "[" ++ lists:join(", ", gen_list_elements()) ++ " ]";
|
|
||||||
3 -> "[ " ++ imm_arg() ++ " ]";
|
|
||||||
4 -> "[ " ++ imm_arg() ++ ", " ++ imm_arg() ++ " ]"
|
|
||||||
end.
|
|
||||||
|
|
||||||
%% Not type correct.
|
|
||||||
gen_list_elements() ->
|
|
||||||
case rand:uniform(3) of
|
|
||||||
1 -> [imm_arg() | gen_list_elements()];
|
|
||||||
2 -> [];
|
|
||||||
3 -> [imm_arg()]
|
|
||||||
end.
|
|
||||||
|
|
||||||
gen_bits() ->
|
|
||||||
element(rand:uniform(3),
|
|
||||||
{"<>"
|
|
||||||
,"!<>"
|
|
||||||
, "101010"}).
|
|
||||||
|
|
||||||
gen_tuple() ->
|
|
||||||
case rand:uniform(3) of
|
|
||||||
1 -> "()";
|
|
||||||
2 -> "(42)";
|
|
||||||
3 -> "(" ++ imm_arg() ++ ")"
|
|
||||||
end.
|
|
||||||
|
|
||||||
gen_variant() ->
|
|
||||||
case rand:uniform(3) of
|
|
||||||
1 -> "(| 5 | 2 | (1, \"foo\", ()) |)";
|
|
||||||
2 -> "(| 2 | 1 | ( " ++ imm_arg() ++ " ) |)";
|
|
||||||
3 -> "(| 2 | 0 | ( " ++ imm_arg() ++ ", " ++ imm_arg() ++ " ) |)"
|
|
||||||
end.
|
|
||||||
|
|
||||||
|
|
||||||
%% TODO: add gas cost.
|
|
||||||
generate_documentation(Filename) ->
|
|
||||||
{ok, File} = file:open(Filename, [write]),
|
|
||||||
Instructions = lists:flatten([gen_doc(Op)++"\n" || Op <- gen(ops_defs())]),
|
|
||||||
io:format(File,
|
|
||||||
"### Operations\n\n"
|
|
||||||
"| OpCode | Name | Args | Description |\n"
|
|
||||||
"| --- | --- | --- | --- |\n"
|
|
||||||
"~s"
|
|
||||||
, [Instructions]),
|
|
||||||
io:format(File, "\n", []),
|
|
||||||
file:close(File).
|
|
||||||
|
|
||||||
gen_doc(#{ opname := Name
|
|
||||||
, 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
|
|
||||||
}) ->
|
|
||||||
Arguments =
|
|
||||||
case FateFormat of
|
|
||||||
atomic -> "";
|
|
||||||
_ -> lists:join(" ",
|
|
||||||
[format_arg_doc(A) ||
|
|
||||||
A <-
|
|
||||||
lists:zip(FateFormat,
|
|
||||||
lists:seq(0,length(FateFormat)-1))])
|
|
||||||
end,
|
|
||||||
io_lib:format("| 0x~.16b | ~w | ~s | ~s |\n",
|
|
||||||
[ OpCode
|
|
||||||
, Name
|
|
||||||
, Arguments
|
|
||||||
, Doc]).
|
|
||||||
|
|
||||||
format_arg_doc({a, N}) -> io_lib:format("Arg~w", [N]);
|
|
||||||
format_arg_doc({is,N}) -> "Identifier";
|
|
||||||
format_arg_doc({ii,N}) -> "Integer";
|
|
||||||
format_arg_doc({li,N}) -> "[Integers]";
|
|
||||||
format_arg_doc({t,N}) -> "Type".
|
|
||||||
|
|
||||||
|
|||||||
@@ -50,9 +50,6 @@ sources() ->
|
|||||||
, "remote"
|
, "remote"
|
||||||
, "test"
|
, "test"
|
||||||
, "tuple"
|
, "tuple"
|
||||||
, "mapofmap"
|
|
||||||
, "immediates"
|
|
||||||
, "all_instructions"
|
|
||||||
].
|
].
|
||||||
|
|
||||||
check_roundtrip(File) ->
|
check_roundtrip(File) ->
|
||||||
@@ -65,5 +62,4 @@ check_roundtrip(File) ->
|
|||||||
{_Env2, ByteCode2} = assemble(DissasmCode),
|
{_Env2, ByteCode2} = assemble(DissasmCode),
|
||||||
Code1 = aeb_fate_asm:strip(ByteCode),
|
Code1 = aeb_fate_asm:strip(ByteCode),
|
||||||
Code2 = aeb_fate_asm:strip(ByteCode2),
|
Code2 = aeb_fate_asm:strip(ByteCode2),
|
||||||
io:format("~s~n", [aeb_fate_asm:to_asm(disassemble(ByteCode2))]),
|
|
||||||
?assertEqual(Code1, Code2).
|
?assertEqual(Code1, Code2).
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ sources() ->
|
|||||||
"0123456789012345678901234567890123456789">>), %% Magic concat 80 char string.
|
"0123456789012345678901234567890123456789">>), %% Magic concat 80 char string.
|
||||||
aeb_fate_data:make_tuple({True, FortyTwo}),
|
aeb_fate_data:make_tuple({True, FortyTwo}),
|
||||||
aeb_fate_data:make_tuple(list_to_tuple(make_int_list(65))),
|
aeb_fate_data:make_tuple(list_to_tuple(make_int_list(65))),
|
||||||
aeb_fate_data:make_tuple(list_to_tuple(make_int_list(16))),
|
|
||||||
aeb_fate_data:make_map(#{ aeb_fate_data:make_integer(1) => True, aeb_fate_data:make_integer(2) => False}),
|
aeb_fate_data:make_map(#{ aeb_fate_data:make_integer(1) => True, aeb_fate_data:make_integer(2) => False}),
|
||||||
aeb_fate_data:make_map(#{ aeb_fate_data:make_string(<<"foo">>) => aeb_fate_data:make_tuple({FortyTwo, True})}),
|
aeb_fate_data:make_map(#{ aeb_fate_data:make_string(<<"foo">>) => aeb_fate_data:make_tuple({FortyTwo, True})}),
|
||||||
aeb_fate_data:make_list(make_int_list(3)),
|
aeb_fate_data:make_list(make_int_list(3)),
|
||||||
|
|||||||
@@ -1,233 +0,0 @@
|
|||||||
;; CONTRACT all_instructions
|
|
||||||
|
|
||||||
;; Dont expect this contract to typecheck or run.
|
|
||||||
;; Just used to check assembler rountrip of all instruction.
|
|
||||||
|
|
||||||
FUNCTION foo () : {tuple, []}
|
|
||||||
RETURN
|
|
||||||
|
|
||||||
RETURNR a13
|
|
||||||
|
|
||||||
CALL foo
|
|
||||||
|
|
||||||
CALL_R arg125 foo
|
|
||||||
|
|
||||||
CALL_T foo
|
|
||||||
|
|
||||||
CALL_TR arg245 foo
|
|
||||||
|
|
||||||
JUMP 5514251025295783441695716053282666408426
|
|
||||||
|
|
||||||
JUMPIF arg196 0x12c651665
|
|
||||||
|
|
||||||
SWITCH_V2 a27 63 33
|
|
||||||
|
|
||||||
SWITCH_V3 var4 0x1d61723dd 79 7
|
|
||||||
|
|
||||||
SWITCH_VN #nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv [1, 2, 3]
|
|
||||||
|
|
||||||
PUSH var80
|
|
||||||
|
|
||||||
DUPA
|
|
||||||
|
|
||||||
DUP a
|
|
||||||
|
|
||||||
POP a107
|
|
||||||
|
|
||||||
STORE arg183 var225
|
|
||||||
|
|
||||||
INCA
|
|
||||||
|
|
||||||
INC a25
|
|
||||||
|
|
||||||
DECA
|
|
||||||
|
|
||||||
DEC a
|
|
||||||
|
|
||||||
ADD a217 a a
|
|
||||||
|
|
||||||
SUB arg35 arg165 var74
|
|
||||||
|
|
||||||
MUL 44 35 "foo"
|
|
||||||
|
|
||||||
DIV 263838340369912686645632650718169038811 a24 a
|
|
||||||
|
|
||||||
MOD var113 arg80 arg207
|
|
||||||
|
|
||||||
POW a176 a a123
|
|
||||||
|
|
||||||
LT a 78 var81
|
|
||||||
|
|
||||||
GT arg19 4729414120208894485838100532547810615352 var175
|
|
||||||
|
|
||||||
EQ 85 a arg164
|
|
||||||
|
|
||||||
ELT a161 arg226 a168
|
|
||||||
|
|
||||||
EGT a131 1 var250
|
|
||||||
|
|
||||||
NEQ a85 a a83
|
|
||||||
|
|
||||||
AND var255 0x294a24f6 var189
|
|
||||||
|
|
||||||
OR (| 2 | 0 | ( (), (42) ) |) arg168 var107
|
|
||||||
|
|
||||||
NOT arg124 a
|
|
||||||
|
|
||||||
TUPLE 5019186157739257888756115213149493826410
|
|
||||||
|
|
||||||
ELEMENT integer arg148 var25 a219
|
|
||||||
|
|
||||||
MAP_EMPTY a135
|
|
||||||
|
|
||||||
MAP_LOOKUP a82 a a143
|
|
||||||
|
|
||||||
MAP_LOOKUPD var112 arg35 a163 var112
|
|
||||||
|
|
||||||
MAP_UPDATE false a0 a56 a
|
|
||||||
|
|
||||||
MAP_DELETE arg180 a var1
|
|
||||||
|
|
||||||
MAP_MEMBER a { true => 4} 94
|
|
||||||
|
|
||||||
MAP_FROM_LIST () a159
|
|
||||||
|
|
||||||
NIL arg91
|
|
||||||
|
|
||||||
IS_NIL a121 var6
|
|
||||||
|
|
||||||
CONS arg185 "foo" a114
|
|
||||||
|
|
||||||
HD a150 var124
|
|
||||||
|
|
||||||
TL arg223 a
|
|
||||||
|
|
||||||
LENGTH var216 a143
|
|
||||||
|
|
||||||
STR_EQ { 203961992615221001243597889146034217896 => 0x1f53a1843} 281217554184165828643225535776787296845 a177
|
|
||||||
|
|
||||||
STR_JOIN a a 7144184027126178769820155907121270843348
|
|
||||||
|
|
||||||
INT_TO_STR var238 a
|
|
||||||
|
|
||||||
ADDR_TO_STR a arg216
|
|
||||||
|
|
||||||
STR_REVERSE a174 #nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv
|
|
||||||
|
|
||||||
INT_TO_ADDR arg127 var207
|
|
||||||
|
|
||||||
VARIANT a a 0x1f7b72200 a
|
|
||||||
|
|
||||||
VARIANT_TEST a26 arg217 a
|
|
||||||
|
|
||||||
VARIANT_ELEMENT a86 arg103 arg108
|
|
||||||
|
|
||||||
BITS_NONEA
|
|
||||||
|
|
||||||
BITS_NONE a
|
|
||||||
|
|
||||||
BITS_ALLA
|
|
||||||
|
|
||||||
BITS_ALL a164
|
|
||||||
|
|
||||||
BITS_ALL_N a221 arg135
|
|
||||||
|
|
||||||
BITS_SET arg150 a48 { 0x1a715e2a6 => 3}
|
|
||||||
|
|
||||||
BITS_CLEAR arg98 a arg164
|
|
||||||
|
|
||||||
BITS_TEST a a242 (| 5 | 2 | (1, "foo", ()) |)
|
|
||||||
|
|
||||||
BITS_SUM a244 a71
|
|
||||||
|
|
||||||
BITS_OR var20 var186 a
|
|
||||||
|
|
||||||
BITS_AND a187 4 arg203
|
|
||||||
|
|
||||||
BITS_DIFF var200 arg247 var20
|
|
||||||
|
|
||||||
ADDRESS a237
|
|
||||||
|
|
||||||
BALANCE a231
|
|
||||||
|
|
||||||
ORIGIN arg216
|
|
||||||
|
|
||||||
CALLER a27
|
|
||||||
|
|
||||||
GASPRICE arg119
|
|
||||||
|
|
||||||
BLOCKHASH arg110
|
|
||||||
|
|
||||||
BENEFICIARY var163
|
|
||||||
|
|
||||||
TIMESTAMP a
|
|
||||||
|
|
||||||
GENERATION 242795038229506961431398379342231049652
|
|
||||||
|
|
||||||
MICROBLOCK arg43
|
|
||||||
|
|
||||||
DIFFICULTY var24
|
|
||||||
|
|
||||||
GASLIMIT arg220
|
|
||||||
|
|
||||||
GAS var35
|
|
||||||
|
|
||||||
LOG0 a a85
|
|
||||||
|
|
||||||
LOG1 arg94 arg86 arg208
|
|
||||||
|
|
||||||
LOG2 a113 (| 5 | 2 | (1, "foo", ()) |) arg238 var108
|
|
||||||
|
|
||||||
LOG3 arg255 arg15 arg211 var139 arg44
|
|
||||||
|
|
||||||
LOG4 #nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv a247 a 9 a38 a
|
|
||||||
|
|
||||||
DEACTIVATE
|
|
||||||
|
|
||||||
SPEND #nv5B93FPzRHrGNmMdTDfGdd5xGZvep3MVSpJqzcQmMp59bBCv var136
|
|
||||||
|
|
||||||
ORACLE_REGISTER arg29 48 ((| 5 | 2 | (1, "foo", ()) |)) arg65 { <> => false} <>
|
|
||||||
|
|
||||||
ORACLE_QUERY
|
|
||||||
|
|
||||||
ORACLE_RESPOND
|
|
||||||
|
|
||||||
ORACLE_EXTEND
|
|
||||||
|
|
||||||
ORACLE_GET_ANSWER
|
|
||||||
|
|
||||||
ORACLE_GET_QUESTION
|
|
||||||
|
|
||||||
ORACLE_QUERY_FEE
|
|
||||||
|
|
||||||
AENS_RESOLVE
|
|
||||||
|
|
||||||
AENS_PRECLAIM
|
|
||||||
|
|
||||||
AENS_CLAIM
|
|
||||||
|
|
||||||
AENS_UPDATE
|
|
||||||
|
|
||||||
AENS_TRANSFER
|
|
||||||
|
|
||||||
AENS_REVOKE
|
|
||||||
|
|
||||||
ECVERIFY
|
|
||||||
|
|
||||||
SHA3
|
|
||||||
|
|
||||||
SHA256
|
|
||||||
|
|
||||||
BLAKE2B
|
|
||||||
|
|
||||||
DUMMY7ARG a a 7607708484837907159893701471377343595877 (| 2 | 0 | ( [], [ 45, { 1 => 3441201581501946066216994494994943246334} ] ) |) a0 var56 "foo"
|
|
||||||
|
|
||||||
DUMMY8ARG 3673679924816289365509492271980889822579 a69 arg242 var237 a175 arg106 () var255
|
|
||||||
|
|
||||||
ABORT a
|
|
||||||
|
|
||||||
EXIT var120
|
|
||||||
|
|
||||||
NOP
|
|
||||||
|
|
||||||
RETURNR ()
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
;; CONTRACT immediates
|
|
||||||
|
|
||||||
FUNCTION integer() : integer
|
|
||||||
RETURNR 42
|
|
||||||
|
|
||||||
FUNCTION neg_integer() : integer
|
|
||||||
RETURNR -2374683271468723648732648736498712634876147
|
|
||||||
|
|
||||||
FUNCTION hex_integer() : integer
|
|
||||||
RETURNR 0x0deadbeef0
|
|
||||||
|
|
||||||
FUNCTION bool() : boolean
|
|
||||||
RETURNR true
|
|
||||||
|
|
||||||
FUNCTION bool_f() : boolean
|
|
||||||
RETURNR false
|
|
||||||
|
|
||||||
FUNCTION string() : string
|
|
||||||
RETURNR "Hello"
|
|
||||||
|
|
||||||
FUNCTION map() : {map, integer, boolean}
|
|
||||||
RETURNR {}
|
|
||||||
|
|
||||||
FUNCTION map2() : {map, integer, boolean}
|
|
||||||
RETURNR {1 => true}
|
|
||||||
|
|
||||||
FUNCTION map3() : {map, integer, boolean}
|
|
||||||
RETURNR {1 => true,
|
|
||||||
2 => false}
|
|
||||||
|
|
||||||
FUNCTION map4() : {map, integer, {map, string, boolean}}
|
|
||||||
RETURNR {1 => { "foo" => true, "bar" => false},
|
|
||||||
2 => {},
|
|
||||||
3 => { "foo" => false}}
|
|
||||||
|
|
||||||
FUNCTION nil() : {list, integer}
|
|
||||||
RETURNR []
|
|
||||||
|
|
||||||
FUNCTION list1() : {list, integer}
|
|
||||||
RETURNR [1]
|
|
||||||
|
|
||||||
FUNCTION list2() : {list, integer}
|
|
||||||
RETURNR [1, 2]
|
|
||||||
|
|
||||||
|
|
||||||
FUNCTION no_bits() : bits
|
|
||||||
RETURNR <>
|
|
||||||
|
|
||||||
FUNCTION all_bits() : bits
|
|
||||||
RETURNR !<>
|
|
||||||
|
|
||||||
FUNCTION some_bits() : bits
|
|
||||||
RETURNR <101010>
|
|
||||||
|
|
||||||
FUNCTION many_bits() : bits
|
|
||||||
RETURNR !<010101>
|
|
||||||
|
|
||||||
FUNCTION group_bits() : bits
|
|
||||||
RETURNR <1010 1010 0011 1001>
|
|
||||||
|
|
||||||
FUNCTION unit() : {tuple, []}
|
|
||||||
RETURNR ()
|
|
||||||
|
|
||||||
FUNCTION tuple() : {tuple, [integer, boolean, string, {tuple, [integer, integer]}]}
|
|
||||||
RETURNR (42, true, "FooBar", (1, 2))
|
|
||||||
|
|
||||||
|
|
||||||
FUNCTION address() : address
|
|
||||||
RETURNR #deadbeef
|
|
||||||
|
|
||||||
;; Option(integer) = NONE | SOME(integer)
|
|
||||||
FUNCTION variant_none() : {variant, [{tuple, []}, {tuple, [integer]}]}
|
|
||||||
RETURNR (| 2 | 0 | () |)
|
|
||||||
|
|
||||||
;; Option(integer) = NONE | SOME(integer)
|
|
||||||
FUNCTION variant_some() : {variant, [{tuple, []}, {tuple, [integer]}]}
|
|
||||||
RETURNR (| 2 | 1 | (42) |)
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
;; CONTRACT mapofmap
|
|
||||||
FUNCTION map() : {map, integer, {map, string, boolean}}
|
|
||||||
RETURNR {1 => { "foo" => true, "bar" => false},
|
|
||||||
2 => {},
|
|
||||||
3 => { "foo" => false}}
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user