Parse all types of values except variants.

This commit is contained in:
Erik Stenman 2019-02-28 17:52:00 +01:00
parent 1c7436edab
commit d78b78e494
7 changed files with 175 additions and 12 deletions

View File

@ -48,14 +48,15 @@
%%% false
%%% 5. Strings
%%% "Hello"
%%% 6. Empty map
%%% 6. Map
%%% {}
%%% { 1 => { "foo" => true, "bar" => false}
%%% 7. Lists
%%% []
%%% [1, 2]
%%% 8. Bit field
%%% <000>
%%% <1010>
%%% <1010 1010>
%%% <>
%%% !<>
%%% 9. Tuples
@ -569,7 +570,11 @@ deserialize_type(<<5, Rest/binary>>) -> {bits, Rest};
deserialize_type(<<6, Rest/binary>>) ->
{K, Rest2} = deserialize_type(Rest),
{V, Rest3} = deserialize_type(Rest2),
{{map, K, V}, Rest3}.
{{map, K, V}, Rest3};
deserialize_type(<<7, Rest/binary>>) ->
{string, Rest}.
deserialize_types(0, Binary, Acc) ->
{lists:reverse(Acc), Binary};
@ -616,6 +621,19 @@ to_bytecode([{hash,_line, Hash}|Rest], Address, Env, Code, Opts) ->
to_bytecode([{id,_line, ID}|Rest], Address, Env, Code, Opts) ->
{Hash, Env2} = insert_symbol(ID, Env),
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([{bits,_line, Bits}|Rest], Address, Env, Code, Opts) ->
to_bytecode(Rest, Address, Env, [{immediate, Bits}|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);
@ -632,6 +650,51 @@ to_bytecode([], Address, Env, Code, Opts) ->
end,
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_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]) -> parse_tuple(Rest).
to_fun_def([{id, _, Name}, {'(', _} | Rest]) ->
{ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest),
@ -689,9 +752,11 @@ serialize_type({tuple, Ts}) ->
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)].
serialize_type(address) -> [4];
serialize_type(bits) -> [5];
serialize_type({map, K, V}) -> [6 | serialize_type(K) ++ serialize_type(V)];
serialize_type(string) -> [7].
%% -------------------------------------------------------------------

View File

@ -17,7 +17,8 @@ HEX = 0x{HEXDIGIT}+
HASH = #{HEXDIGIT}+
WS = [\000-\s]
ID = {LOWER}[a-zA-Z0-9_]*
STRING = "[^"]*"
BITS = (\!)?\<[\s01]*\>
Rules.
arg{INT} : {token, {arg, TokenLine, parse_arg(TokenChars)}}.
@ -38,13 +39,22 @@ FUNCTION : {token, {function, TokenLine, 'FUNCTION' }}.
{token, {int, TokenLine, parse_hex(TokenChars)}}.
{INT} :
{token, {int, TokenLine, parse_int(TokenChars)}}.
-{INT} :
{token, {int, TokenLine, parse_int(TokenChars)}}.
{HASH} :
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
{STRING} :
{token, {hash, TokenLine, list_to_binary(TokenChars)}}.
{BITS} :
{token, {bits, TokenLine, bits(TokenChars)}}.
%% Symbols
\-\> : {token, {'to', TokenLine}}.
\: : {token, {'to', TokenLine}}.
\-\> : {token, {to, TokenLine}}.
\: : {token, {to, TokenLine}}.
\=\> : {token, {arrow, TokenLine}}.
, : {token, {',', TokenLine}}.
\( : {token, {'(', TokenLine}}.
\) : {token, {')', TokenLine}}.
@ -97,3 +107,13 @@ scan(S) ->
drop_prefix(C, [C|Rest]) ->
drop_prefix(C, Rest);
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).

View File

@ -23,7 +23,7 @@
| {map, fate_type(), fate_type()}
| {tuple, [fate_type()]}
| address
| bits
| bits
| {variant, integer()}.
@ -147,7 +147,7 @@ format(M) when ?IS_FATE_MAP(M) ->
format(?FATE_ADDRESS(Address)) -> ["#", address_to_base58(Address)];
format(V) -> exit({not_a_fate_type, V}).
format_list(List) ->
format_list(List) ->
["[ ", lists:join(", ", [format(E) || E <- List]), " ]"].
format_kvs(List) ->

View File

@ -128,7 +128,7 @@ serialize(L) when ?IS_FATE_LIST(L) ->
<<?LONG_LIST, Val/binary, Rest/binary>>
end;
serialize(Map) when ?IS_FATE_MAP(Map) ->
L = [{_K,_V}|_] = maps:to_list(?FATE_MAP_VALUE(Map)),
L = [{_K,_V}|_] = lists:sort(maps:to_list(?FATE_MAP_VALUE(Map))),
Size = length(L),
%% TODO: check all K same type, and all V same type
%% check K =/= map

View File

@ -50,6 +50,8 @@ sources() ->
, "remote"
, "test"
, "tuple"
, "mapofmap"
, "immediates"
].
check_roundtrip(File) ->
@ -62,4 +64,5 @@ check_roundtrip(File) ->
{_Env2, ByteCode2} = assemble(DissasmCode),
Code1 = aeb_fate_asm:strip(ByteCode),
Code2 = aeb_fate_asm:strip(ByteCode2),
io:format("~s~n", [aeb_fate_asm:to_asm(disassemble(ByteCode2))]),
?assertEqual(Code1, Code2).

View File

@ -0,0 +1,68 @@
;; 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))

View File

@ -0,0 +1,7 @@
;; CONTRACT mapofmap
FUNCTION map() : {map, integer, {map, string, boolean}}
RETURNR {1 => { "foo" => true, "bar" => false},
2 => {},
3 => { "foo" => false}}