From d16fb82e253a06d0d47bbfe8bded21e57cead159 Mon Sep 17 00:00:00 2001 From: Robert Virding Date: Wed, 8 May 2019 16:06:58 +0200 Subject: [PATCH] Break out state and event from typedefs and update docs --- docs/aeso_aci.md | 58 +++++++++++++++++++++++++++--------------------- src/aeso_aci.erl | 39 +++++++++++++++++++++++++++----- 2 files changed, 66 insertions(+), 31 deletions(-) diff --git a/docs/aeso_aci.md b/docs/aeso_aci.md index fe72804..8db3d85 100644 --- a/docs/aeso_aci.md +++ b/docs/aeso_aci.md @@ -31,24 +31,20 @@ generates the following JSON structure representing the contract interface: { "contract": { "name": "Answers", - "type_defs": [ - { - "name": "state", - "vars": [], - "typedef": { - "record": [ - { - "name": "a", - "type": { - "map": { - "key": "string", - "value": "int" - } - } + "state": { + "record": [ + { + "name": "a", + "type": { + "map": { + "key": "string", + "value": "int" } - ] + } } - }, + ] + }, + "type_defs": [ { "name": "answers", "vars": [], @@ -84,15 +80,11 @@ generates the following JSON structure representing the contract interface: "arguments": [ { "name": "q", - "type": [ - "string" - ] + "type": "string" }, { "name": "a", - "type": [ - "int" - ] + "type": "int" } ], "returns": { @@ -132,6 +124,18 @@ ConstractString = contract_string() JSONstring = json_string() ``` +This is equivalent to `aeso_aci:encode_contract(ConstractString, [])`. + +#### encode_contract(ContractString, Options) -> {ok,JSONstring} | {error,ErrorString} + +Types + +``` erlang +ConstractString = contract_string() +Options = [option()] +JSONstring = json_string() +``` + Generate the JSON encoding of the interface to a contract. The type definitions and non-private functions are included in the JSON string. #### decode_contract(JSONstring) -> ConstractString. @@ -185,15 +189,19 @@ JSONstring = json_string() Generate the JSON encoding of an expression from the AST of the expression. +### Notes + +The deprecated functions `aseo_aci:encode/2` and `aeso_aci:decode/1` are still available but should not be used. + ### Example run This is an example of using the ACI generator from an Erlang shell. The file called `aci_test.aes` contains the contract in the description from which we want to generate files `aci_test.json` which is the JSON encoding of the contract interface and `aci_test.include` which is the contract definition to be included inside another contract. ``` erlang 1> {ok,Contract} = file:read_file("aci_test.aes"). -{ok,<<"contract Answers =\n record state = { a : answers }\n type answers() = map(string, int)\n\n stateful function"...>>} +{ok,<<"contract Answers =\n\n record state = { a : answers }\n type answers() = map(string, int)\n\n stateful functio"...>>} 2> {ok,Encoding} = aeso_aci:encode_contract(Contract). -<<"{\"contract\":{\"name\":\"Answers\",\"type_defs\":[{\"name\":\"state\",\"vars\":[],\"typedef\":\"{a : map(string,int)}\"},{\"name\":\"ans"...>> +{ok,<<"{\"contract\":{\"name\":\"Answers\",\"state\":{\"record\":[{\"name\":\"a\",\"type\":{\"map\":{\"key\":\"string\",\"value\":\"int\"}}}]"...>>} 3> file:write_file("aci_test.aci", Encoding). ok 4> Decoded = aeso_aci:decode_contract(Encoding). @@ -201,7 +209,7 @@ ok 5> file:write_file("aci_test.include", Decoded). ok 6> jsx:prettify(Encoding). -<<"{\n \"contract\": {\n \"name\": \"Answers\",\n \"type_defs\": [\n {\n \"name\": \"state\",\n \"vars\": [],\n "...>> +<<"{\n \"contract\": {\n \"name\": \"Answers\",\n \"state\": {\n \"record\": [\n {\n \"name\": \"a\",\n "...>> ``` The final call to `jsx:prettify(Encoding)` returns the encoding in a diff --git a/src/aeso_aci.erl b/src/aeso_aci.erl index eb589bf..1981881 100644 --- a/src/aeso_aci.erl +++ b/src/aeso_aci.erl @@ -9,6 +9,7 @@ -module(aeso_aci). +%% Old deprecated interface. -export([encode/1,encode/2,decode/1]). -export([encode_contract/1,encode_contract/2,decode_contract/1]). @@ -93,13 +94,13 @@ encode_contract(ContractString, Options) -> %% We find and look at the last contract. Contract = lists:last(TypedAst), Cname = contract_name(Contract), - Tdefs = [ do_encode_typedef(T) || - T <- sort_decls(contract_types(Contract)) ], + Tdefs = do_encode_contract_typedefs(sort_decls(contract_types(Contract))), Fdefs = [ do_encode_func(F) || F <- sort_decls(contract_funcs(Contract)), not is_private_func(F) ], - Jmap = [{<<"contract">>, [{<<"name">>, do_encode_name(Cname)}, - {<<"type_defs">>, Tdefs}, - {<<"functions">>, Fdefs}]}], + Jmap = [{<<"contract">>, + [{<<"name">>, do_encode_name(Cname)}] ++ + Tdefs ++ + [{<<"functions">>, Fdefs}]}], %% io:format("~p\n", [Jmap]), {ok,jsx:encode(Jmap)} catch @@ -118,6 +119,32 @@ join_errors(Prefix, Errors, Pfun) -> Ess = [ Pfun(E) || E <- Errors ], list_to_binary(string:join([Prefix|Ess], "\n")). +%% do_encode_contract_typedefs(TypeDefs) -> [JSON]. +%% Return a list of typedefs and state and event if they occur. + +do_encode_contract_typedefs(Tdefs) -> + Fun = fun(T, {Ts,Ss,Es}) -> + %% Only one state and event. + case typedef_name(T) of + "state" -> {Ts,[do_encode_state_typedef(T)],Es}; + "event" -> {Ts,Ss,[do_encode_event_typedef(T)]}; + _Name -> {Ts ++ [do_encode_typedef(T)],Ss,Es} + end + end, + {Ts,Ss,Es} = lists:foldl(Fun, {[],[],[]}, Tdefs), + Ss ++ [{<<"type_defs">>, Ts}] ++ Es. + +%% do_encode_state_typedef(StateTdef) -> JSON. +%% do_encode_event_typedef(EventTdef) -> JSON. + +do_encode_state_typedef(State) -> + Def = typedef_def(State), + {<<"state">>,do_encode_alias(Def)}. + +do_encode_event_typedef(State) -> + Def = typedef_def(State), + {<<"event">>,do_encode_alias(Def)}. + %% encode_func(TypedAST) -> JSON. %% Encode a function AST into a JSON structure. @@ -276,7 +303,7 @@ do_encode_stmt(E) -> do_encode_expr(E). do_encode_stmt_case(#'case'{pat=Pat,body=Body}) -> - Epat = do_encode_expr(Pat), %Patterns are expessions + Epat = do_encode_expr(Pat), %Patterns are expessions Ebody = do_encode_stmt(Body), [{<<"pattern">>,Epat},{<<"body">>,Ebody}].