Doc update for hz_sophia and hz_aaci and some minor fixes #30

Merged
zxq9 merged 9 commits from spivee/docs into master 2026-05-26 09:44:53 +09:00
Showing only changes of commit 9fc89c0c22 - Show all commits
+69 -10
View File
@@ -4,26 +4,28 @@
-copyright("Jarvis Carroll <spiveehere@gmail.com>").
-license("GPL-3.0-or-later").
-export([parse_literal/1, parse_literal/2]).
-export([parse_literal/2, parse_literal/1]).
-export([fate_to_list/1, fate_to_list/2, fate_to_iolist/1, fate_to_iolist/2]).
-include_lib("eunit/include/eunit.hrl").
-spec parse_literal(Sophia) -> {ok, FATE} | {error, Reason}
when Sophia :: string(),
FATE :: gmb_fate_data:fate_type(),
Reason :: term().
parse_literal(String) ->
parse_literal(unknown_type(), String).
-spec parse_literal(Type, Sophia) -> {ok, FATE} | {error, Reason}
when Type :: hz_aaci:annotated_type(),
Sophia :: string(),
FATE :: gmb_fate_data:fate_type(),
Reason :: term().
%% @doc
%% Parse a typed Sophia expression into a FATE term
%% The Sophia expression must consist only of literals, thus making a 'Sophia
%% term', which means no arithmetic, no function calls, no variables, etc.
%% The FATE term is in the format that gmbytecode expects as input, for forming
%% contract calls, etc. Used by the hz module to implement the 'sophia' format.
%%
%% The function takes type information retrieved from the AACI data structure,
%% which is used to interpret record types and variant types, but is also used
%% to check inputs and generate errors.
parse_literal(Type, String) ->
case parse_expression(Type, {1, 1}, String) of
{ok, {Result, NewPos, NewString}} ->
@@ -43,6 +45,28 @@ parse_literal2(Result, Pos, String) ->
{error, Reason}
end.
-spec parse_literal(Sophia) -> {ok, FATE} | {error, Reason}
when Sophia :: string(),
FATE :: gmb_fate_data:fate_type(),
Reason :: term().
%% @doc
%% Parse an untyped Sophia expression into a FATE term
%% Like parse_literal/2, but will not produce type errors. This function can
%% still produce parsing errors, and can produce errors when variants or
%% records are encountered, since they can't be parsed unless you have type
%% information.
%%
%% Note that since records are implemented as tuples, if you are trying to call
%a function that you know takes a record, but you don't have type information
%% available in the context where the expression is being passed, then tuples
%% can be used instead. This does not work if you have type information,
%% though, as tuples and records are different Sophia/AACI types.
parse_literal(String) ->
parse_literal(unknown_type(), String).
%%% Tokenizer
-define(IS_LATIN_UPPER(C), (((C) >= $A) and ((C) =< $Z))).
@@ -927,6 +951,19 @@ wrap_error(Reason, _) -> Reason.
when FATE :: gmb_fate_data:fate_type(),
Sophia :: string().
%% @doc
%% Print a FATE term from gmbytecode in Sophia syntax
%% FATE terms usually come from using gmbytecode to decode the result of an
%% on-chain transaction.
%%
%% This function does not use any type information to interpret the data, and
%% so can make mistakes. It's okay for interpreting tuples, lists, maps,
%% integers, and strings, but it will misinterpret the types of records and
%% unicode characters, and will crash the process if variants are encountered.
%%
%% fate_to_list/2 should be used whenever possible, especially since
%% transaction results are type checked by nodes at runtime.
fate_to_list(Term) ->
fate_to_list(unknown_type(), Term).
@@ -935,10 +972,27 @@ fate_to_list(Term) ->
FATE :: gmb_fate_data:fate_type(),
Sophia :: string().
%% @doc
%% Print a FATE term from gmbytecode in Sophia syntax
%% Like fate_to_list/1, but now type information from the AACI data structure
%% can be provided, in order to correctly interpret types like records,
%% variants, and unicode characters. If the type information you provide is
%% incorrect for the FATE term provided, then the function will fall back to
%% untyped pretty printing like in fate_to_list/1, but this is not recommended,
%% as correct type information should always be available.
fate_to_list(Type, Term) ->
IOList = fate_to_iolist(Type, Term),
unicode:characters_to_list(IOList).
%% @doc
%% Print a FATE term in Sophia syntax, without concatenating
%% The fate_to_list/1 function builds an iolist, and then concatenates it into
%% a list. If you are going to put the term into a bigger iolist directly
%% after, or write it to a streaming device, then it can save effort and memory
%% to just use the iolist directly.
-spec fate_to_iolist(FATE) -> Sophia
when FATE :: gmb_fate_data:fate_type(),
Sophia :: iolist().
@@ -951,6 +1005,11 @@ fate_to_iolist(Term) ->
FATE :: gmb_fate_data:fate_type(),
Sophia :: iolist().
%% @doc
%% Print a FATE term in Sophia syntax, without concatenating
%% Prints using type information, like fate_to_list/2, but without spending
%% time or memory concatenating the result into a list, like fate_to_iolist/1.
% Special case for singleton records, since they are erased during compilation.
fate_to_iolist({_, _, {record, [{FieldName, FieldType}]}}, Term) ->
singleton_record_to_iolist(FieldName, FieldType, Term);