Merge fortuna to master #136
@ -53,6 +53,7 @@
|
|||||||
, function_call/1
|
, function_call/1
|
||||||
, pp/1
|
, pp/1
|
||||||
, read_file/1
|
, read_file/1
|
||||||
|
, strip/1
|
||||||
, to_asm/1
|
, to_asm/1
|
||||||
, to_hexstring/1
|
, to_hexstring/1
|
||||||
]).
|
]).
|
||||||
@ -99,14 +100,36 @@ pp(FateCode) ->
|
|||||||
|
|
||||||
|
|
||||||
to_asm(#{ functions := Functions
|
to_asm(#{ functions := Functions
|
||||||
, symbols := Symbols} = _FateCode) ->
|
, symbols := Symbols
|
||||||
lists:flatten(
|
, annotations := Annotations} = _FateCode) ->
|
||||||
io_lib:format("~s",[
|
insert_comments(get_comments(Annotations), 1,
|
||||||
[format(lookup(Name, Symbols),
|
lists:flatten(
|
||||||
Sig,
|
io_lib:format("~s",
|
||||||
lists:sort(maps:to_list(CodeMap)),
|
[format_functions(Functions, Symbols)]))).
|
||||||
Symbols) ||
|
|
||||||
{Name, {Sig, CodeMap}} <- maps:to_list(Functions)]])).
|
insert_comments([{L,C}|Comments], L, String) ->
|
||||||
|
";; " ++ C ++ "\n" ++ insert_comments(Comments, L + 1, String);
|
||||||
|
insert_comments(Comments, L, [$\n|String]) ->
|
||||||
|
"\n" ++ insert_comments(Comments, L+1, String);
|
||||||
|
insert_comments(Comments, L, [C|Rest]) ->
|
||||||
|
[C|insert_comments(Comments, L, Rest)];
|
||||||
|
insert_comments([],_,[]) -> [];
|
||||||
|
insert_comments([{L,C}|Rest], _, []) ->
|
||||||
|
";; " ++ C ++ "\n" ++ insert_comments(Rest, L + 1, []).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
format_functions(Functions, Symbols) ->
|
||||||
|
[format(lookup(Name, Symbols),
|
||||||
|
Sig,
|
||||||
|
lists:sort(maps:to_list(CodeMap)),
|
||||||
|
Symbols)
|
||||||
|
||
|
||||||
|
{Name, {Sig, CodeMap}} <- maps:to_list(Functions)].
|
||||||
|
|
||||||
|
|
||||||
format(Name, Sig, BBs, Symbols) ->
|
format(Name, Sig, BBs, Symbols) ->
|
||||||
@ -320,6 +343,7 @@ asm_to_bytecode(AssemblerCode, Options) ->
|
|||||||
|
|
||||||
Env = to_bytecode(Tokens, none, #{ functions => #{}
|
Env = to_bytecode(Tokens, none, #{ functions => #{}
|
||||||
, symbols => #{}
|
, symbols => #{}
|
||||||
|
, annotations => #{}
|
||||||
}, [], Options),
|
}, [], Options),
|
||||||
|
|
||||||
ByteList = serialize(Env),
|
ByteList = serialize(Env),
|
||||||
@ -329,7 +353,7 @@ asm_to_bytecode(AssemblerCode, Options) ->
|
|||||||
ByteCode = << (aeb_rlp:encode(list_to_binary(ByteList)))/binary,
|
ByteCode = << (aeb_rlp:encode(list_to_binary(ByteList)))/binary,
|
||||||
(aeb_rlp:encode(list_to_binary(Signatures)))/binary,
|
(aeb_rlp:encode(list_to_binary(Signatures)))/binary,
|
||||||
(aeb_rlp:encode(SymbolTable))/binary,
|
(aeb_rlp:encode(SymbolTable))/binary,
|
||||||
(aeb_rlp:encode(list_to_binary(Annotatations)))/binary
|
(aeb_rlp:encode(Annotatations))/binary
|
||||||
>>,
|
>>,
|
||||||
|
|
||||||
case proplists:lookup(pp_hex_string, Options) of
|
case proplists:lookup(pp_hex_string, Options) of
|
||||||
@ -341,6 +365,10 @@ asm_to_bytecode(AssemblerCode, Options) ->
|
|||||||
|
|
||||||
{Env, ByteCode}.
|
{Env, ByteCode}.
|
||||||
|
|
||||||
|
strip(ByteCode) ->
|
||||||
|
{Code, _Rest} = aeb_rlp:decode_one(ByteCode),
|
||||||
|
Code.
|
||||||
|
|
||||||
bytecode_to_fate_code(Bytes, _Options) ->
|
bytecode_to_fate_code(Bytes, _Options) ->
|
||||||
{ByteCode, Rest1} = aeb_rlp:decode_one(Bytes),
|
{ByteCode, Rest1} = aeb_rlp:decode_one(Bytes),
|
||||||
{Signatures, Rest2} = aeb_rlp:decode_one(Rest1),
|
{Signatures, Rest2} = aeb_rlp:decode_one(Rest1),
|
||||||
@ -517,15 +545,19 @@ deserialize_symbols(Table, Env) ->
|
|||||||
?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table),
|
?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table),
|
||||||
Env#{symbols => SymbolTable}.
|
Env#{symbols => SymbolTable}.
|
||||||
|
|
||||||
deserialize_annotations(_Annotations, Env) -> Env.
|
deserialize_annotations(AnnotationsBin, Env) ->
|
||||||
|
?FATE_MAP_VALUE(Annotations) = aeb_fate_encoding:deserialize(AnnotationsBin),
|
||||||
|
Env#{annotations => Annotations}.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
serialize_sigs(_Env) -> [].
|
serialize_sigs(_Env) -> [].
|
||||||
|
|
||||||
serialize_symbol_table(#{ symbols := Symbols }) ->
|
serialize_symbol_table(#{ symbols := Symbols }) ->
|
||||||
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
|
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
|
||||||
|
|
||||||
serialize_annotations(_Env) ->
|
serialize_annotations(#{ annotations := Annotations}) ->
|
||||||
[].
|
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -652,17 +684,6 @@ serialize_signature({Args, RetType}) ->
|
|||||||
[serialize_type({tuple, Args}) |
|
[serialize_type({tuple, Args}) |
|
||||||
serialize_type(RetType)].
|
serialize_type(RetType)].
|
||||||
|
|
||||||
serialize_type(integer) -> [0];
|
|
||||||
serialize_type(boolean) -> [1];
|
|
||||||
serialize_type({list, T}) -> [2 | serialize_type(T)];
|
|
||||||
serialize_type({tuple, Ts}) ->
|
|
||||||
case length(Ts) of
|
|
||||||
N when N =< 255 ->
|
|
||||||
[3, N | [serialize_type(T) || T <- Ts]]
|
|
||||||
end;
|
|
||||||
serialize_type(address) -> 4;
|
|
||||||
serialize_type(bits) -> 5;
|
|
||||||
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)].
|
|
||||||
|
|
||||||
|
|
||||||
deserialize_signature(Binary) ->
|
deserialize_signature(Binary) ->
|
||||||
@ -697,6 +718,13 @@ to_hexstring(ByteList) ->
|
|||||||
[io_lib:format("~2.16.0b", [X])
|
[io_lib:format("~2.16.0b", [X])
|
||||||
|| X <- ByteList]).
|
|| X <- ByteList]).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%% Parser
|
||||||
|
%% Asm tokens -> Fate code env
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
to_bytecode([{function,_line, 'FUNCTION'}|Rest], Address, Env, Code, Opts) ->
|
to_bytecode([{function,_line, 'FUNCTION'}|Rest], Address, Env, Code, Opts) ->
|
||||||
Env2 = insert_fun(Address, Code, Env),
|
Env2 = insert_fun(Address, Code, Env),
|
||||||
{Fun, Rest2} = to_fun_def(Rest),
|
{Fun, Rest2} = to_fun_def(Rest),
|
||||||
@ -723,6 +751,10 @@ to_bytecode([{hash,_line, Hash}|Rest], Address, Env, 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([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) ->
|
||||||
|
Env2 = insert_annotation(comment, Line, Comment, Env),
|
||||||
|
to_bytecode(Rest, Address, Env2, Code, Opts);
|
||||||
|
|
||||||
to_bytecode([], Address, Env, Code, Opts) ->
|
to_bytecode([], Address, Env, Code, Opts) ->
|
||||||
Env2 = insert_fun(Address, Code, Env),
|
Env2 = insert_fun(Address, Code, Env),
|
||||||
#{functions := Funs} = Env2,
|
#{functions := Funs} = Env2,
|
||||||
@ -751,6 +783,9 @@ to_arg_types(Tokens) ->
|
|||||||
{[Type], Rest}
|
{[Type], Rest}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
%% Type handling
|
||||||
|
|
||||||
to_type([{id, _, "integer"} | Rest]) -> {integer, Rest};
|
to_type([{id, _, "integer"} | Rest]) -> {integer, Rest};
|
||||||
to_type([{id, _, "boolean"} | Rest]) -> {boolean, Rest};
|
to_type([{id, _, "boolean"} | Rest]) -> {boolean, Rest};
|
||||||
to_type([{id, _, "string"} | Rest]) -> {string, Rest};
|
to_type([{id, _, "string"} | Rest]) -> {string, Rest};
|
||||||
@ -781,6 +816,24 @@ to_list_of_types(Tokens) ->
|
|||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
|
serialize_type(integer) -> [0];
|
||||||
|
serialize_type(boolean) -> [1];
|
||||||
|
serialize_type({list, T}) -> [2 | serialize_type(T)];
|
||||||
|
serialize_type({tuple, Ts}) ->
|
||||||
|
case length(Ts) of
|
||||||
|
N when N =< 255 ->
|
||||||
|
[3, N | [serialize_type(T) || T <- Ts]]
|
||||||
|
end;
|
||||||
|
serialize_type(address) -> 4;
|
||||||
|
serialize_type(bits) -> 5;
|
||||||
|
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)].
|
||||||
|
|
||||||
|
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
%% Helper functions
|
||||||
|
%% -------------------------------------------------------------------
|
||||||
|
|
||||||
|
%% State handling
|
||||||
|
|
||||||
insert_fun(none, [], Env) -> Env;
|
insert_fun(none, [], Env) -> Env;
|
||||||
insert_fun({Name, Type, RetType}, Code, #{functions := Functions} = Env) ->
|
insert_fun({Name, Type, RetType}, Code, #{functions := Functions} = Env) ->
|
||||||
@ -794,6 +847,20 @@ mk_hash(Id) ->
|
|||||||
{ok, <<A:8, B:8, C:8, D:8,_/binary>> } = aeb_blake2:blake2b(?HASH_BYTES, list_to_binary(Id)),
|
{ok, <<A:8, B:8, C:8, D:8,_/binary>> } = aeb_blake2:blake2b(?HASH_BYTES, list_to_binary(Id)),
|
||||||
<<A,B,C,D>>.
|
<<A,B,C,D>>.
|
||||||
|
|
||||||
|
%% Handle annotations
|
||||||
|
|
||||||
|
insert_annotation(comment, Line, Comment, #{annotations := A} = Env) ->
|
||||||
|
Key = aeb_fate_data:make_tuple({aeb_fate_data:make_string("comment"), Line}),
|
||||||
|
Value = aeb_fate_data:make_string(Comment),
|
||||||
|
Env#{annotations => A#{ Key => Value}}.
|
||||||
|
|
||||||
|
get_comments(Annotations) ->
|
||||||
|
[ {Line, Comment} ||
|
||||||
|
{?FATE_TUPLE({?FATE_STRING_VALUE("comment"), Line}),
|
||||||
|
?FATE_STRING_VALUE(Comment)} <- maps:to_list(Annotations)].
|
||||||
|
|
||||||
|
%% Symbols handling
|
||||||
|
|
||||||
insert_symbol(Id, Env) ->
|
insert_symbol(Id, Env) ->
|
||||||
Hash = mk_hash(Id),
|
Hash = mk_hash(Id),
|
||||||
insert_symbol(Id, Hash, Env).
|
insert_symbol(Id, Hash, Env).
|
||||||
@ -809,6 +876,7 @@ insert_symbol(Id, Hash, #{symbols := Symbols} = Env) ->
|
|||||||
, Hash => Id}}}
|
, Hash => Id}}}
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
%% Symbol table handling
|
||||||
|
|
||||||
lookup(Name, Symbols) ->
|
lookup(Name, Symbols) ->
|
||||||
maps:get(Name, Symbols, Name).
|
maps:get(Name, Symbols, Name).
|
||||||
|
@ -161,6 +161,9 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
|||||||
\{ : {token, {'{', TokenLine}}.
|
\{ : {token, {'{', TokenLine}}.
|
||||||
\} : {token, {'}', TokenLine}}.
|
\} : {token, {'}', TokenLine}}.
|
||||||
|
|
||||||
|
;;.* :
|
||||||
|
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
|
||||||
|
|
||||||
\. : skip_token.
|
\. : skip_token.
|
||||||
|
|
||||||
|
|
||||||
@ -168,7 +171,7 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
|
|||||||
{WS} : skip_token.
|
{WS} : skip_token.
|
||||||
|
|
||||||
%% Comments (TODO: nested comments)
|
%% Comments (TODO: nested comments)
|
||||||
;;.* : skip_token.
|
|
||||||
|
|
||||||
. : {error, "Unexpected token: " ++ TokenChars}.
|
. : {error, "Unexpected token: " ++ TokenChars}.
|
||||||
|
|
||||||
@ -199,3 +202,6 @@ parse_hash("#" ++ Chars) ->
|
|||||||
scan(S) ->
|
scan(S) ->
|
||||||
string(S).
|
string(S).
|
||||||
|
|
||||||
|
drop_prefix(C, [C|Rest]) ->
|
||||||
|
drop_prefix(C, Rest);
|
||||||
|
drop_prefix(_, Tail) -> Tail.
|
||||||
|
@ -60,7 +60,6 @@ check_roundtrip(File) ->
|
|||||||
io:format("~s~n", [AssemblerCode]),
|
io:format("~s~n", [AssemblerCode]),
|
||||||
io:format("~s~n", [DissasmCode]),
|
io:format("~s~n", [DissasmCode]),
|
||||||
{Env2, ByteCode2} = assemble(DissasmCode),
|
{Env2, ByteCode2} = assemble(DissasmCode),
|
||||||
?assertEqual(ByteCode, ByteCode2).
|
Code1 = aeb_fate_asm:strip(ByteCode),
|
||||||
|
Code2 = aeb_fate_asm:strip(ByteCode2),
|
||||||
|
?assertEqual(Code1, Code2).
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
;; CONTRACT jumpif
|
;; CONTRACT jumpif
|
||||||
FUNCTION skip(integer, integer) : integer
|
FUNCTION skip(integer, integer) : integer
|
||||||
PUSH arg1
|
;; BB : 0
|
||||||
PUSH 0
|
PUSH arg1
|
||||||
EQ a a arg0
|
PUSH 0
|
||||||
JUMPIF a 2
|
EQ a a arg0
|
||||||
INCA
|
JUMPIF a 2
|
||||||
JUMP 2
|
;; BB : 1
|
||||||
RETURN
|
INCA
|
||||||
|
JUMP 2
|
||||||
|
RETURN
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
FUNCTION make_0tuple():{tuple, []}
|
FUNCTION make_0tuple():{tuple, []}
|
||||||
|
;; BB : 0
|
||||||
TUPLE 0
|
TUPLE 0
|
||||||
RETURN
|
RETURN
|
||||||
|
|
||||||
FUNCTION make_2tuple(integer, integer):{tuple, [integer, integer]}
|
FUNCTION make_2tuple(integer, integer):{tuple, [integer, integer]}
|
||||||
|
;; BB : 0
|
||||||
PUSH arg0
|
PUSH arg0
|
||||||
PUSH arg1
|
PUSH arg1
|
||||||
TUPLE 2
|
TUPLE 2
|
||||||
@ -10,6 +12,7 @@ FUNCTION make_2tuple(integer, integer):{tuple, [integer, integer]}
|
|||||||
|
|
||||||
FUNCTION make_5tuple(integer, integer, integer, integer, integer):
|
FUNCTION make_5tuple(integer, integer, integer, integer, integer):
|
||||||
{tuple, [integer, integer, integer, integer, integer]}
|
{tuple, [integer, integer, integer, integer, integer]}
|
||||||
|
;; BB : 0
|
||||||
PUSH arg0
|
PUSH arg0
|
||||||
PUSH arg1
|
PUSH arg1
|
||||||
PUSH arg2
|
PUSH arg2
|
||||||
@ -19,6 +22,7 @@ FUNCTION make_5tuple(integer, integer, integer, integer, integer):
|
|||||||
RETURN
|
RETURN
|
||||||
|
|
||||||
FUNCTION element1(integer, integer): integer
|
FUNCTION element1(integer, integer): integer
|
||||||
|
;; BB : 0
|
||||||
PUSH arg0
|
PUSH arg0
|
||||||
PUSH arg1
|
PUSH arg1
|
||||||
TUPLE 2
|
TUPLE 2
|
||||||
@ -26,5 +30,6 @@ FUNCTION element1(integer, integer): integer
|
|||||||
RETURN
|
RETURN
|
||||||
|
|
||||||
FUNCTION element({tuple, [integer, integer]}, integer): integer
|
FUNCTION element({tuple, [integer, integer]}, integer): integer
|
||||||
|
;; BB : 0
|
||||||
ELEMENT integer a arg1 arg0
|
ELEMENT integer a arg1 arg0
|
||||||
RETURN
|
RETURN
|
||||||
|
Loading…
x
Reference in New Issue
Block a user