Skip to content

Commit a35307f

Browse files
committed
Add annotations (comments) to bytecode. Add strip function to remove symboltable and annotations from bytecode.
1 parent d04a827 commit a35307f

File tree

5 files changed

+115
-35
lines changed

5 files changed

+115
-35
lines changed

src/aeb_fate_asm.erl

Lines changed: 91 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353
, function_call/1
5454
, pp/1
5555
, read_file/1
56+
, strip/1
5657
, to_asm/1
5758
, to_hexstring/1
5859
]).
@@ -99,14 +100,36 @@ pp(FateCode) ->
99100

100101

101102
to_asm(#{ functions := Functions
102-
, symbols := Symbols} = _FateCode) ->
103-
lists:flatten(
104-
io_lib:format("~s",[
105-
[format(lookup(Name, Symbols),
106-
Sig,
107-
lists:sort(maps:to_list(CodeMap)),
108-
Symbols) ||
109-
{Name, {Sig, CodeMap}} <- maps:to_list(Functions)]])).
103+
, symbols := Symbols
104+
, annotations := Annotations} = _FateCode) ->
105+
insert_comments(get_comments(Annotations), 1,
106+
lists:flatten(
107+
io_lib:format("~s",
108+
[format_functions(Functions, Symbols)]))).
109+
110+
insert_comments([{L,C}|Comments], L, String) ->
111+
";; " ++ C ++ "\n" ++ insert_comments(Comments, L + 1, String);
112+
insert_comments(Comments, L, [$\n|String]) ->
113+
"\n" ++ insert_comments(Comments, L+1, String);
114+
insert_comments(Comments, L, [C|Rest]) ->
115+
[C|insert_comments(Comments, L, Rest)];
116+
insert_comments([],_,[]) -> [];
117+
insert_comments([{L,C}|Rest], _, []) ->
118+
";; " ++ C ++ "\n" ++ insert_comments(Rest, L + 1, []).
119+
120+
121+
122+
123+
124+
125+
126+
format_functions(Functions, Symbols) ->
127+
[format(lookup(Name, Symbols),
128+
Sig,
129+
lists:sort(maps:to_list(CodeMap)),
130+
Symbols)
131+
||
132+
{Name, {Sig, CodeMap}} <- maps:to_list(Functions)].
110133

111134

112135
format(Name, Sig, BBs, Symbols) ->
@@ -320,6 +343,7 @@ asm_to_bytecode(AssemblerCode, Options) ->
320343

321344
Env = to_bytecode(Tokens, none, #{ functions => #{}
322345
, symbols => #{}
346+
, annotations => #{}
323347
}, [], Options),
324348

325349
ByteList = serialize(Env),
@@ -329,7 +353,7 @@ asm_to_bytecode(AssemblerCode, Options) ->
329353
ByteCode = << (aeb_rlp:encode(list_to_binary(ByteList)))/binary,
330354
(aeb_rlp:encode(list_to_binary(Signatures)))/binary,
331355
(aeb_rlp:encode(SymbolTable))/binary,
332-
(aeb_rlp:encode(list_to_binary(Annotatations)))/binary
356+
(aeb_rlp:encode(Annotatations))/binary
333357
>>,
334358

335359
case proplists:lookup(pp_hex_string, Options) of
@@ -341,6 +365,10 @@ asm_to_bytecode(AssemblerCode, Options) ->
341365

342366
{Env, ByteCode}.
343367

368+
strip(ByteCode) ->
369+
{Code, _Rest} = aeb_rlp:decode_one(ByteCode),
370+
Code.
371+
344372
bytecode_to_fate_code(Bytes, _Options) ->
345373
{ByteCode, Rest1} = aeb_rlp:decode_one(Bytes),
346374
{Signatures, Rest2} = aeb_rlp:decode_one(Rest1),
@@ -517,15 +545,19 @@ deserialize_symbols(Table, Env) ->
517545
?FATE_MAP_VALUE(SymbolTable) = aeb_fate_encoding:deserialize(Table),
518546
Env#{symbols => SymbolTable}.
519547

520-
deserialize_annotations(_Annotations, Env) -> Env.
548+
deserialize_annotations(AnnotationsBin, Env) ->
549+
?FATE_MAP_VALUE(Annotations) = aeb_fate_encoding:deserialize(AnnotationsBin),
550+
Env#{annotations => Annotations}.
551+
552+
521553

522554
serialize_sigs(_Env) -> [].
523555

524556
serialize_symbol_table(#{ symbols := Symbols }) ->
525557
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Symbols)).
526558

527-
serialize_annotations(_Env) ->
528-
[].
559+
serialize_annotations(#{ annotations := Annotations}) ->
560+
aeb_fate_encoding:serialize(aeb_fate_data:make_map(Annotations)).
529561

530562

531563

@@ -652,17 +684,6 @@ serialize_signature({Args, RetType}) ->
652684
[serialize_type({tuple, Args}) |
653685
serialize_type(RetType)].
654686

655-
serialize_type(integer) -> [0];
656-
serialize_type(boolean) -> [1];
657-
serialize_type({list, T}) -> [2 | serialize_type(T)];
658-
serialize_type({tuple, Ts}) ->
659-
case length(Ts) of
660-
N when N =< 255 ->
661-
[3, N | [serialize_type(T) || T <- Ts]]
662-
end;
663-
serialize_type(address) -> 4;
664-
serialize_type(bits) -> 5;
665-
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)].
666687

667688

668689
deserialize_signature(Binary) ->
@@ -697,6 +718,13 @@ to_hexstring(ByteList) ->
697718
[io_lib:format("~2.16.0b", [X])
698719
|| X <- ByteList]).
699720

721+
722+
723+
%% -------------------------------------------------------------------
724+
%% Parser
725+
%% Asm tokens -> Fate code env
726+
%% -------------------------------------------------------------------
727+
700728
to_bytecode([{function,_line, 'FUNCTION'}|Rest], Address, Env, Code, Opts) ->
701729
Env2 = insert_fun(Address, Code, Env),
702730
{Fun, Rest2} = to_fun_def(Rest),
@@ -723,6 +751,10 @@ to_bytecode([{hash,_line, Hash}|Rest], Address, Env, Code, Opts) ->
723751
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
724752
{Hash, Env2} = insert_symbol(ID, Env),
725753
to_bytecode(Rest, Address, Env2, [{immediate, Hash}|Code], Opts);
754+
to_bytecode([{comment, Line, Comment}|Rest], Address, Env, Code, Opts) ->
755+
Env2 = insert_annotation(comment, Line, Comment, Env),
756+
to_bytecode(Rest, Address, Env2, Code, Opts);
757+
726758
to_bytecode([], Address, Env, Code, Opts) ->
727759
Env2 = insert_fun(Address, Code, Env),
728760
#{functions := Funs} = Env2,
@@ -751,6 +783,9 @@ to_arg_types(Tokens) ->
751783
{[Type], Rest}
752784
end.
753785

786+
787+
%% Type handling
788+
754789
to_type([{id, _, "integer"} | Rest]) -> {integer, Rest};
755790
to_type([{id, _, "boolean"} | Rest]) -> {boolean, Rest};
756791
to_type([{id, _, "string"} | Rest]) -> {string, Rest};
@@ -781,6 +816,24 @@ to_list_of_types(Tokens) ->
781816
end.
782817

783818

819+
serialize_type(integer) -> [0];
820+
serialize_type(boolean) -> [1];
821+
serialize_type({list, T}) -> [2 | serialize_type(T)];
822+
serialize_type({tuple, Ts}) ->
823+
case length(Ts) of
824+
N when N =< 255 ->
825+
[3, N | [serialize_type(T) || T <- Ts]]
826+
end;
827+
serialize_type(address) -> 4;
828+
serialize_type(bits) -> 5;
829+
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)].
830+
831+
832+
%% -------------------------------------------------------------------
833+
%% Helper functions
834+
%% -------------------------------------------------------------------
835+
836+
%% State handling
784837

785838
insert_fun(none, [], Env) -> Env;
786839
insert_fun({Name, Type, RetType}, Code, #{functions := Functions} = Env) ->
@@ -794,6 +847,20 @@ mk_hash(Id) ->
794847
{ok, <<A:8, B:8, C:8, D:8,_/binary>> } = aeb_blake2:blake2b(?HASH_BYTES, list_to_binary(Id)),
795848
<<A,B,C,D>>.
796849

850+
%% Handle annotations
851+
852+
insert_annotation(comment, Line, Comment, #{annotations := A} = Env) ->
853+
Key = aeb_fate_data:make_tuple({aeb_fate_data:make_string("comment"), Line}),
854+
Value = aeb_fate_data:make_string(Comment),
855+
Env#{annotations => A#{ Key => Value}}.
856+
857+
get_comments(Annotations) ->
858+
[ {Line, Comment} ||
859+
{?FATE_TUPLE({?FATE_STRING_VALUE("comment"), Line}),
860+
?FATE_STRING_VALUE(Comment)} <- maps:to_list(Annotations)].
861+
862+
%% Symbols handling
863+
797864
insert_symbol(Id, Env) ->
798865
Hash = mk_hash(Id),
799866
insert_symbol(Id, Hash, Env).
@@ -809,6 +876,7 @@ insert_symbol(Id, Hash, #{symbols := Symbols} = Env) ->
809876
, Hash => Id}}}
810877
end.
811878

879+
%% Symbol table handling
812880

813881
lookup(Name, Symbols) ->
814882
maps:get(Name, Symbols, Name).

src/aeb_fate_asm_scan.xrl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,14 +161,17 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
161161
\{ : {token, {'{', TokenLine}}.
162162
\} : {token, {'}', TokenLine}}.
163163

164+
;;.* :
165+
{token, {comment, TokenLine, drop_prefix($;, TokenChars)}}.
166+
164167
\. : skip_token.
165168

166169

167170
%% Whitespace ignore
168171
{WS} : skip_token.
169172

170173
%% Comments (TODO: nested comments)
171-
;;.* : skip_token.
174+
172175

173176
. : {error, "Unexpected token: " ++ TokenChars}.
174177

@@ -199,3 +202,6 @@ parse_hash("#" ++ Chars) ->
199202
scan(S) ->
200203
string(S).
201204

205+
drop_prefix(C, [C|Rest]) ->
206+
drop_prefix(C, Rest);
207+
drop_prefix(_, Tail) -> Tail.

test/aeb_fate_asm_test.erl

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ check_roundtrip(File) ->
6060
io:format("~s~n", [AssemblerCode]),
6161
io:format("~s~n", [DissasmCode]),
6262
{Env2, ByteCode2} = assemble(DissasmCode),
63-
?assertEqual(ByteCode, ByteCode2).
64-
65-
66-
63+
Code1 = aeb_fate_asm:strip(ByteCode),
64+
Code2 = aeb_fate_asm:strip(ByteCode2),
65+
?assertEqual(Code1, Code2).

test/asm_code/jumpif.fate

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
;; CONTRACT jumpif
22
FUNCTION skip(integer, integer) : integer
3-
PUSH arg1
4-
PUSH 0
5-
EQ a a arg0
6-
JUMPIF a 2
7-
INCA
8-
JUMP 2
9-
RETURN
3+
;; BB : 0
4+
PUSH arg1
5+
PUSH 0
6+
EQ a a arg0
7+
JUMPIF a 2
8+
;; BB : 1
9+
INCA
10+
JUMP 2
11+
RETURN

test/asm_code/tuple.fate

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
FUNCTION make_0tuple():{tuple, []}
2+
;; BB : 0
23
TUPLE 0
34
RETURN
45

56
FUNCTION make_2tuple(integer, integer):{tuple, [integer, integer]}
7+
;; BB : 0
68
PUSH arg0
79
PUSH arg1
810
TUPLE 2
911
RETURN
1012

1113
FUNCTION make_5tuple(integer, integer, integer, integer, integer):
1214
{tuple, [integer, integer, integer, integer, integer]}
15+
;; BB : 0
1316
PUSH arg0
1417
PUSH arg1
1518
PUSH arg2
@@ -19,12 +22,14 @@ FUNCTION make_5tuple(integer, integer, integer, integer, integer):
1922
RETURN
2023

2124
FUNCTION element1(integer, integer): integer
25+
;; BB : 0
2226
PUSH arg0
2327
PUSH arg1
2428
TUPLE 2
2529
ELEMENT integer a 1 a
2630
RETURN
2731

2832
FUNCTION element({tuple, [integer, integer]}, integer): integer
33+
;; BB : 0
2934
ELEMENT integer a arg1 arg0
3035
RETURN

0 commit comments

Comments
 (0)