|
@@ -3,8 +3,8 @@
|
|
-behaviour(application).
|
|
-behaviour(application).
|
|
-behaviour(supervisor).
|
|
-behaviour(supervisor).
|
|
-export([init/1,start/2, stop/1]).
|
|
-export([init/1,start/2, stop/1]).
|
|
--export([behaviour_info/1, parse_transform/2, generate_to_json/3,
|
|
|
|
- generate_from_json/3, from_json/1, to_json/1, to_binary/1]).
|
|
|
|
|
|
+-export([behaviour_info/1, parse_transform/2, generate_to_json/3, binarize/1,
|
|
|
|
+ generate_from_json/3, from_json/2, to_json/1, to_binary/1, parse/1]).
|
|
|
|
|
|
stop(_State) -> ok.
|
|
stop(_State) -> ok.
|
|
start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
start(_StartType, _StartArgs) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
|
|
@@ -26,24 +26,42 @@ behaviour_info(callbacks) -> [{exists, 1}, {get, 0}, {get, 1}, {post, 1}, {delet
|
|
behaviour_info(_) -> undefined.
|
|
behaviour_info(_) -> undefined.
|
|
|
|
|
|
parse_transform(Forms, _Options) ->
|
|
parse_transform(Forms, _Options) ->
|
|
-% io:format("~p~n", [Forms]),
|
|
|
|
RecordName = rest_record(Forms),
|
|
RecordName = rest_record(Forms),
|
|
RecordFields = record_fields(RecordName, Forms),
|
|
RecordFields = record_fields(RecordName, Forms),
|
|
Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
|
|
Forms1 = generate({from_json, 2}, RecordName, RecordFields, Forms),
|
|
Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
|
|
Forms2 = generate({to_json, 1}, RecordName, RecordFields, Forms1),
|
|
-% io:format("~p~n", [Forms2]),
|
|
|
|
Forms2.
|
|
Forms2.
|
|
|
|
|
|
rest_record([]) -> [];
|
|
rest_record([]) -> [];
|
|
rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
|
|
rest_record([{attribute, _, rest_record, RecordName} | _Forms]) -> RecordName;
|
|
rest_record([_ | Forms]) -> rest_record(Forms).
|
|
rest_record([_ | Forms]) -> rest_record(Forms).
|
|
|
|
|
|
-record_field({record_field, _, {atom, _, Field} }) -> Field;
|
|
|
|
-record_field({record_field, _, {atom, _, Field}, _}) -> Field;
|
|
|
|
-record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, _}) -> Field.
|
|
|
|
|
|
+record_field({record_field, _, {atom, _, Field} },_cordName) ->
|
|
|
|
+% io:format("Case 1: ~p~n",[Field]),
|
|
|
|
+ Field;
|
|
|
|
+record_field({record_field, _, {atom, _, Field}, Type},_cordName) ->
|
|
|
|
+% io:format("Case 2: ~p~n",[Field]),
|
|
|
|
+ Field;
|
|
|
|
+record_field({typed_record_field, {record_field,_,{atom, _, Field},_}, Type},RecordName) ->
|
|
|
|
+ Rec = allow(Type),
|
|
|
|
+ put({RecordName,Field},Rec),
|
|
|
|
+% case Rec of
|
|
|
|
+% undefined -> io:format("Case 3: ~p~n",[Field]);
|
|
|
|
+% _ -> io:format("Case 3: ~p, Link: ~p~n",[Field,Rec]) end,
|
|
|
|
+ Field.
|
|
|
|
+
|
|
|
|
+allow({type,_,union,Components}) -> findType(Components);
|
|
|
|
+allow(Type) -> findType([Type]).
|
|
|
|
+
|
|
|
|
+findType([]) -> undefined;
|
|
|
|
+findType([{type,_,record,[{atom,_,X}]}|T]) -> X;
|
|
|
|
+findType([{remote_type,_,[{atom,_,_},{atom,_,X},_]}|T]) -> X;
|
|
|
|
+findType([H|T]) ->
|
|
|
|
+% io:format("Unknown Type: ~p~n",[H]),
|
|
|
|
+ findType(T).
|
|
|
|
|
|
record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
|
|
record_fields(RecordName, [{attribute, _, record, {RecordName, Fields}} | _Forms]) ->
|
|
- [record_field(Field) || Field <- Fields];
|
|
|
|
|
|
+ [record_field(Field,RecordName) || Field <- Fields];
|
|
record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
|
|
record_fields(RecordName, [_ | Forms]) -> record_fields(RecordName, Forms);
|
|
record_fields(__cordName, []) -> [].
|
|
record_fields(__cordName, []) -> [].
|
|
|
|
|
|
@@ -76,7 +94,10 @@ from_json_coda(Line) ->
|
|
{clause, Line,
|
|
{clause, Line,
|
|
[{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
|
|
[{cons, Line, {var, Line, '_'}, {var, Line, 'Json'}}, {var, Line, 'Acc'}],
|
|
[],
|
|
[],
|
|
- [{call, Line, {atom, Line, from_json}, [{var, Line, 'Json'}, {var, Line, 'Acc'}]}]}.
|
|
|
|
|
|
+ [{call, Line, {atom, Line, from_json}, [
|
|
|
|
+% {var, Line, 'Json'} % here is fix for recursive binarized preprocessing to raw X:from_json
|
|
|
|
+ {call,Line,{remote,Line,{atom,Line,?MODULE},{atom,Line,binarize}},[{var, Line, 'Json'}]}
|
|
|
|
+ , {var, Line, 'Acc'}]}]}.
|
|
|
|
|
|
from_json_clauses(_, _, []) -> [];
|
|
from_json_clauses(_, _, []) -> [];
|
|
from_json_clauses(Line, Record, [Field | Fields]) ->
|
|
from_json_clauses(Line, Record, [Field | Fields]) ->
|
|
@@ -97,9 +118,11 @@ from_json_clauses(Line, Record, [Field | Fields]) ->
|
|
Record,
|
|
Record,
|
|
[{record_field, Line,
|
|
[{record_field, Line,
|
|
{atom, Line, Field},
|
|
{atom, Line, Field},
|
|
- {call, Line,
|
|
|
|
- {remote, Line, {atom, Line, ?MODULE}, {atom, Line, from_json}},
|
|
|
|
- [{var, Line, field_var(Field)}]}}]}]}]}
|
|
|
|
|
|
+ {call, Line,
|
|
|
|
+ {remote, Line, {atom, Line, ?MODULE }, {atom, Line, from_json}},
|
|
|
|
+ [{var, Line, field_var(Field)},
|
|
|
|
+ {atom,Line, case get({Record,Field}) of undefined -> Record; FieldType -> FieldType end}]}
|
|
|
|
+ }]}]}]}
|
|
| from_json_clauses(Line, Record, Fields)].
|
|
| from_json_clauses(Line, Record, Fields)].
|
|
|
|
|
|
generate_from_json({eof, Line}, Record, Fields) ->
|
|
generate_from_json({eof, Line}, Record, Fields) ->
|
|
@@ -133,17 +156,24 @@ generate_to_json({eof, Line}, Record, Fields) ->
|
|
|
|
|
|
generate_to_json(Form, _, _) -> Form.
|
|
generate_to_json(Form, _, _) -> Form.
|
|
|
|
|
|
-from_json(<<Data/binary>>) -> binary_to_list(Data);
|
|
|
|
-from_json({struct, Props}) -> from_json(Props);
|
|
|
|
-from_json([{Key, _} | _] = Props) when Key =/= struct -> lists:foldr(fun props_skip/2, [], Props);
|
|
|
|
-from_json([_|_] = NonEmptyList) -> [from_json(X) || X <- NonEmptyList];
|
|
|
|
-from_json(Any) -> Any.
|
|
|
|
-
|
|
|
|
-props_skip({<<BinaryKey/binary>>, Value}, Acc) ->
|
|
|
|
- try Key = list_to_existing_atom(binary_to_list(BinaryKey)),
|
|
|
|
- props_skip({Key, Value}, Acc)
|
|
|
|
- catch _:_ -> Acc end;
|
|
|
|
-props_skip({Key, Value}, Acc) -> [{Key, from_json(Value)} | Acc].
|
|
|
|
|
|
+from_json(<<Data/binary>>,_) ->
|
|
|
|
+ binary_to_list(Data);
|
|
|
|
+from_json({struct, Props},X) ->
|
|
|
|
+ from_json(Props,X);
|
|
|
|
+from_json([{Key,_}|_]=Props,X) when Key =/= struct ->
|
|
|
|
+ X:from_json(binarize(Props),X:new());
|
|
|
|
+from_json(Any,X) ->
|
|
|
|
+ Any.
|
|
|
|
+
|
|
|
|
+atomize([{Key,_}|_]=Props) when Key =/= struct ->
|
|
|
|
+ lists:map(fun ({K,V}) when is_atom(K) -> {K,V};
|
|
|
|
+ ({K,V}) when is_binary(K) -> {list_to_existing_atom(binary_to_list(K)),V} end, Props);
|
|
|
|
+atomize(X) -> X.
|
|
|
|
+
|
|
|
|
+binarize([{Key,_}|_]=Props) when Key =/= struct ->
|
|
|
|
+ lists:map(fun ({K,V}) when is_atom(K) -> {list_to_binary(atom_to_list(K)),V};
|
|
|
|
+ ({K,V}) when is_binary(K) -> {K,V} end, Props);
|
|
|
|
+binarize(X) -> X.
|
|
|
|
|
|
to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
|
|
to_json(X) when is_tuple(X) -> Module = hd(tuple_to_list(X)), Module:to_json(X);
|
|
to_json(Data) ->
|
|
to_json(Data) ->
|
|
@@ -168,3 +198,8 @@ to_binary(I) when is_integer(I) -> to_binary(integer_to_list(I));
|
|
to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
|
|
to_binary(F) when is_float(F) -> float_to_binary(F,[{decimals,9},compact]);
|
|
to_binary(L) when is_list(L) -> iolist_to_binary(L).
|
|
to_binary(L) when is_list(L) -> iolist_to_binary(L).
|
|
|
|
|
|
|
|
+parse(String) ->
|
|
|
|
+ {ok,Tokens,_EndLine} = erl_scan:string(String),
|
|
|
|
+ {ok,AbsForm} = erl_parse:parse_exprs(Tokens),
|
|
|
|
+ {value,Value,_Bs} = erl_eval:exprs(AbsForm, erl_eval:new_bindings()),
|
|
|
|
+ Value.
|