Parse all types of values except variants.
This commit is contained in:
parent
1c7436edab
commit
d78b78e494
@ -48,14 +48,15 @@
|
|||||||
%%% false
|
%%% false
|
||||||
%%% 5. Strings
|
%%% 5. Strings
|
||||||
%%% "Hello"
|
%%% "Hello"
|
||||||
%%% 6. Empty map
|
%%% 6. Map
|
||||||
%%% {}
|
%%% {}
|
||||||
|
%%% { 1 => { "foo" => true, "bar" => false}
|
||||||
%%% 7. Lists
|
%%% 7. Lists
|
||||||
%%% []
|
%%% []
|
||||||
%%% [1, 2]
|
%%% [1, 2]
|
||||||
%%% 8. Bit field
|
%%% 8. Bit field
|
||||||
%%% <000>
|
%%% <000>
|
||||||
%%% <1010>
|
%%% <1010 1010>
|
||||||
%%% <>
|
%%% <>
|
||||||
%%% !<>
|
%%% !<>
|
||||||
%%% 9. Tuples
|
%%% 9. Tuples
|
||||||
@ -569,7 +570,11 @@ 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_types(0, Binary, Acc) ->
|
deserialize_types(0, Binary, Acc) ->
|
||||||
{lists:reverse(Acc), Binary};
|
{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) ->
|
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([{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) ->
|
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);
|
||||||
@ -632,6 +650,51 @@ 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_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]) ->
|
to_fun_def([{id, _, Name}, {'(', _} | Rest]) ->
|
||||||
{ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest),
|
{ArgsType, [{'to', _} | Rest2]} = to_arg_types(Rest),
|
||||||
@ -689,9 +752,11 @@ 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].
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%% -------------------------------------------------------------------
|
%% -------------------------------------------------------------------
|
||||||
|
@ -17,7 +17,8 @@ HEX = 0x{HEXDIGIT}+
|
|||||||
HASH = #{HEXDIGIT}+
|
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)}}.
|
||||||
@ -38,13 +39,22 @@ 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, {hash, TokenLine, parse_hash(TokenChars)}}.
|
{token, {hash, TokenLine, parse_hash(TokenChars)}}.
|
||||||
|
{STRING} :
|
||||||
|
{token, {hash, 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, {',', TokenLine}}.
|
, : {token, {',', TokenLine}}.
|
||||||
\( : {token, {'(', TokenLine}}.
|
\( : {token, {'(', TokenLine}}.
|
||||||
\) : {token, {')', TokenLine}}.
|
\) : {token, {')', TokenLine}}.
|
||||||
@ -97,3 +107,13 @@ 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).
|
||||||
|
@ -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}|_] = maps:to_list(?FATE_MAP_VALUE(Map)),
|
L = [{_K,_V}|_] = lists:sort(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
|
||||||
|
@ -50,6 +50,8 @@ sources() ->
|
|||||||
, "remote"
|
, "remote"
|
||||||
, "test"
|
, "test"
|
||||||
, "tuple"
|
, "tuple"
|
||||||
|
, "mapofmap"
|
||||||
|
, "immediates"
|
||||||
].
|
].
|
||||||
|
|
||||||
check_roundtrip(File) ->
|
check_roundtrip(File) ->
|
||||||
@ -62,4 +64,5 @@ 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).
|
||||||
|
68
test/asm_code/immediates.fate
Normal file
68
test/asm_code/immediates.fate
Normal 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))
|
||||||
|
|
||||||
|
|
||||||
|
|
7
test/asm_code/mapofmap.fate
Normal file
7
test/asm_code/mapofmap.fate
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
;; CONTRACT mapofmap
|
||||||
|
FUNCTION map() : {map, integer, {map, string, boolean}}
|
||||||
|
RETURNR {1 => { "foo" => true, "bar" => false},
|
||||||
|
2 => {},
|
||||||
|
3 => { "foo" => false}}
|
||||||
|
|
||||||
|
|
Loading…
x
Reference in New Issue
Block a user