Add first draft of total order for FATE terms.
This commit is contained in:
parent
53130fc638
commit
942c7fb069
@ -96,7 +96,10 @@
|
||||
, make_bits/1
|
||||
, make_unit/0
|
||||
]).
|
||||
-export([format/1]).
|
||||
-export([
|
||||
elt/2
|
||||
, lt/2
|
||||
, format/1]).
|
||||
|
||||
|
||||
make_boolean(true) -> ?FATE_TRUE;
|
||||
@ -193,3 +196,54 @@ format_list(List) ->
|
||||
|
||||
format_kvs(List) ->
|
||||
lists:join(", ", [ [format(K), " => ", format(V)] || {K, V} <- List]).
|
||||
|
||||
|
||||
%% Total order of FATE terms.
|
||||
%% Integers < Booleans < Address < Channel < Contract < Name < Oracle
|
||||
%% < Hash < Signature < Bits < Tuple < Map < List
|
||||
ordinal(T) when ?IS_FATE_INTEGER(T) -> 0;
|
||||
ordinal(T) when ?IS_FATE_BOOLEAN(T) -> 1;
|
||||
ordinal(T) when ?IS_FATE_ADDRESS(T) -> 2;
|
||||
ordinal(T) when ?IS_FATE_CHANNEL(T) -> 3;
|
||||
ordinal(T) when ?IS_FATE_CONTRACT(T) -> 4;
|
||||
ordinal(T) when ?IS_FATE_NAME(T) -> 5;
|
||||
ordinal(T) when ?IS_FATE_ORACLE(T) -> 6;
|
||||
ordinal(T) when ?IS_FATE_HASH(T) -> 7;
|
||||
ordinal(T) when ?IS_FATE_SIGNATURE(T) -> 8;
|
||||
ordinal(T) when ?IS_FATE_BITS(T) -> 9;
|
||||
ordinal(T) when ?IS_FATE_TUPLE(T) -> 10;
|
||||
ordinal(T) when ?IS_FATE_MAP(T) -> 11;
|
||||
ordinal(T) when ?IS_FATE_LIST(T) -> 12.
|
||||
|
||||
|
||||
-spec lt(fate_type(), fate_type()) -> boolean.
|
||||
%% This function assumes that all lists and maps are monomorphic,
|
||||
%% and only tests one element of a list or a map.
|
||||
%% If there is a risc that the term is not monomorphic,
|
||||
%% use safe_lt.
|
||||
lt(A, B) ->
|
||||
O1 = ordinal(A),
|
||||
O2 = ordinal(B),
|
||||
if O1 == O2 -> lt(O1, A, B);
|
||||
true -> O1 < O2
|
||||
end.
|
||||
|
||||
%% Integer is the smallest FATE type.
|
||||
%% Integers themselves are ordered as usual.
|
||||
lt(0, A, B) when ?IS_FATE_INTEGER(A), ?IS_FATE_INTEGER(B) ->
|
||||
?FATE_INTEGER_VALUE(A) < ?FATE_INTEGER_VALUE(B);
|
||||
%% Boolean is the second smallest FATE type.
|
||||
%% false is smaller than true (true also for erlang booleans).
|
||||
lt(1, A, B) when ?IS_FATE_BOOLEAN(A), ?IS_FATE_INTEGER(B) -> false;
|
||||
lt(1, A, B) when ?IS_FATE_BOOLEAN(A), ?IS_FATE_BOOLEAN(B) ->
|
||||
?FATE_BOOLEAN_VALUE(A) < ?FATE_BOOLEAN_VALUE(B);
|
||||
lt(_, A, B) -> A < B.
|
||||
|
||||
|
||||
-spec elt(fate_type(), fate_type()) -> boolean.
|
||||
elt(A, A) -> true;
|
||||
elt(A, B) ->
|
||||
R = lt(A, B),
|
||||
io:format("~w < ~w : ~w~n", [A, B, R]),
|
||||
R.
|
||||
|
||||
|
@ -1,21 +1,29 @@
|
||||
%% Fate data (and instruction) serialization.
|
||||
%%
|
||||
%% The FATE serialization has to fullfill the following properties:
|
||||
%% * There has to be 1 and only 1 byte sequence
|
||||
%% representing each unique value in FATE.
|
||||
%% * A valid byte sequence has to be deserializable to a FATE value.
|
||||
%% * A valid byte sequence must not contain any trailing bytes.
|
||||
%% * A serialization is a sequence of 8-bit bytes.
|
||||
%%
|
||||
%% The serialization function should fullfill the following:
|
||||
%% * A valid FATE value should be serialized to a byte sequence.
|
||||
%% * Any other argument, not representing a valid FATE value should
|
||||
%% Assuming
|
||||
%% S is seralize/1 (fate_type() -> binary())
|
||||
%% D is deserialize/1 (binary) -> fate_type())
|
||||
%% V, V1, V2 are of the type fate_type()
|
||||
%% B is of the type binary()
|
||||
%% Then
|
||||
%% The FATE serialization has to fullfill the following properties:
|
||||
%% * For each value (V) in FATE there has to be a bytecode sequence (B)
|
||||
%% representing that value.
|
||||
%% * A valid byte sequence has to be deserializable to a FATE value.
|
||||
%% * A valid byte sequence must not contain any trailing bytes.
|
||||
%% * A serialization is a sequence of 8-bit bytes.
|
||||
%% The serialization function (S) should fullfill the following:
|
||||
%% * A valid FATE value should be serialized to a byte sequence.
|
||||
%% * Any other argument, not representing a valid FATE value should
|
||||
%% throw an exception
|
||||
%%
|
||||
%% The deserialization function should fullfill the following:
|
||||
%% * A valid byte sequence should be deserialized to a valid FATE value.
|
||||
%% * Any other argument, not representing a valid byte sequence should
|
||||
%% The deserialization function (D) should fullfill the following:
|
||||
%% * A valid byte sequence should be deserialized to a valid FATE value.
|
||||
%% * Any other argument, not representing a valid byte sequence should
|
||||
%% throw an exception
|
||||
%% The following equalities should hold:
|
||||
%% * D(S(V)) == V
|
||||
%% * if V1 == V2 then S(V1) == S(V2)
|
||||
%%
|
||||
%%
|
||||
%% History
|
||||
%% * First draft of FATE serialization encoding/decoding.
|
||||
@ -421,7 +429,7 @@ deserialize_elements(N, Es) ->
|
||||
{[E|Tail], Rest2}.
|
||||
|
||||
|
||||
%% It is important to rem ove duplicated keys.
|
||||
%% It is important to remove duplicated keys.
|
||||
%% For deserialize this check is needed to observe illegal duplicates.
|
||||
sort_and_check(List) ->
|
||||
UniqKeyList =
|
||||
@ -439,7 +447,7 @@ sort_and_check(List) ->
|
||||
|
||||
sort(KVList) ->
|
||||
SortFun = fun({K1, _}, {K2, _}) ->
|
||||
K1 =< K2
|
||||
aeb_fate_data:elt(K1, K2)
|
||||
end,
|
||||
lists:sort(SortFun, KVList).
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user