Permalink
Browse files

Use a custom runtime instead of stdlib dict

  • Loading branch information...
1 parent b013cde commit cdd2bb99f35e886afbc02c775c66019d8e12a4cd @alavrik committed Jul 9, 2011
Showing with 90 additions and 16 deletions.
  1. +2 −2 src/Makefile
  2. +62 −0 src/erlson.erl
  3. +11 −11 src/erlson_parse_transform.erl
  4. +15 −3 src/erlson_tests.erl
View
@@ -1,4 +1,4 @@
-ERL_SOURCES = erl_parse.erl erlson_parse_transform.erl erlson_tests.erl
+ERL_SOURCES = erl_parse.erl erlson_parse_transform.erl erlson.erl erlson_tests.erl
TEST = erlson_tests
ERL = erl
@@ -14,7 +14,7 @@ ERL_OBJECTS = $(ERL_SOURCES:%.erl=$(EBIN_DIR)/%.beam)
all: $(ERL_SOURCES) $(ERL_OBJECTS) expand test
-erlson_tests.erl: erlson_parse_transform.erl
+erlson_tests.erl: erlson_parse_transform.erl erlson.erl
#cp ../test/$@ $@
touch -r $< $@
View
@@ -0,0 +1,62 @@
+%% Copyright (c) 2011 Anton Lavrik, http://github.com/alavrik
+%%
+%% Permission is hereby granted, free of charge, to any person obtaining
+%% a copy of this software and associated documentation files (the
+%% "Software"), to deal in the Software without restriction, including
+%% without limitation the rights to use, copy, modify, merge, publish,
+%% distribute, sublicense, and/or sell copies of the Software, and to
+%% permit persons to whom the Software is furnished to do so, subject to
+%% the following conditions:
+%%
+%% The above copyright notice and this permission notice shall be
+%% included in all copies or substantial portions of the Software.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+%% EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+%% MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+%% NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+%% LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+%% OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+%% WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+%
+% Erlson runtime library
+%
+-module(erlson).
+-export([fetch/2, store/3]).
+
+
+% dictionary represented as an ordered list of name-value pairs
+-type orddict() :: [ {name(), value()} ].
+-type name() :: atom() | binary().
+-type value() :: name().
+
+
+-spec fetch/2 :: (
+ Name :: atom(),
+ Dict :: orddict() ) -> value().
+
+fetch(Name, Dict) ->
+ try
+ fetch_val(Name, Dict)
+ catch
+ 'erlson_not_found' ->
+ erlang:error('erlson_not_found', [Name, Dict])
+ end.
+
+
+fetch_val(Name, [{N, _V} | T]) when Name > N ->
+ fetch_val(Name, T);
+fetch_val(Name, [{N, V} | _T]) when Name =:= N -> V;
+fetch_val(_Name, _) ->
+ throw('erlson_not_found').
+
+
+-spec store/3 :: (
+ Name :: atom(),
+ Value :: any(),
+ Dict :: orddict() ) -> orddict().
+
+store(Name, Value, Dict) ->
+ orddict:store(Name, Value, Dict).
+
@@ -138,25 +138,26 @@ pattern(X, S) ->
expr(X, S#state{context = pattern}).
-% make dict:store(K1, V1, dict:store(K2, V2, dict:store(K3, V3, ...)))
+% make erlson:store(K1, V1, erlson:store(K2, V2, erlson:store(K3, V3, ...)))
make_dict_store(InitDict, L) ->
make_dict_store_1(InitDict, lists:reverse(L)).
make_dict_store_1(InitDict, []) -> InitDict;
make_dict_store_1(InitDict, [H|T]) ->
{record_field,LINE,Key,Value} = H,
Args = [Key, Value, make_dict_store_1(InitDict, T)],
- Res = make_call(LINE, 'dict', 'store', Args),
+ Res = make_call(LINE, 'erlson', 'store', Args),
%?PRINT("make_dict_store_1: ~p~n", [Res]),
Res.
-make_dict_new(LINE) ->
- make_call(LINE, 'dict', 'new', []).
+make_dict_new(LINE, L) ->
+ InitDict = {nil, LINE},
+ make_dict_store(InitDict, L).
make_dict_fetch(LINE, FieldName, Dict) ->
- make_call(LINE, 'dict', 'fetch', [FieldName, Dict]).
+ make_call(LINE, 'erlson', 'fetch', [FieldName, Dict]).
make_call(LINE, ModName, FunName, Args) ->
@@ -173,18 +174,17 @@ make_call(LINE, ModName, FunName, Args) ->
% this node was returned by the customized Erlang parser
expr({record,LINE,'',L}, S) when ?is_context(body) ->
- % convert #{...} to dict:store(Key, Value, dict:store(..., dict:new()))
- InitDict = make_dict_new(LINE),
- make_dict_store(InitDict, ?field_list(L));
+ % convert #{...} to erlson:store(Key, Value, erlson:store(..., []))
+ make_dict_new(LINE, ?field_list(L));
% this node was returned by the customized Erlang parser
expr({record,_LINE,E,'',L}, S) when ?is_context(body) ->
- % convert D#{...} to dict:store(Key, Value, dict:store(..., D))
+ % convert D#{...} to erlson:store(Key, Value, erlson:store(..., D))
make_dict_store(_InitDict = ?expr(E), ?field_list(L));
% this node was returned by the customized Erlang parser
expr({record_field,LINE,E,'',F}, S) when ?is_context(body) ->
- % convert #X.foo to dict:fetch(foo, X)
+ % convert #X.foo to erlson:fetch(foo, X)
make_dict_fetch(LINE, F, ?expr(E));
% NOTE: reusing Mensia field access syntax for accessing dict members
@@ -193,7 +193,7 @@ expr({record_field,LINE,E,F}, S) when ?is_context(body),
not (is_tuple(E) % prohibit using ".foo" without leading expression
andalso element(1, E) == 'atom'
andalso element(3, E) == '') ->
- % convert X.foo to dict:fetch(foo, X)
+ % convert X.foo to erlson:fetch(foo, X)
%?PRINT("record_field: ~p~n", [E]),
make_dict_fetch(LINE, F, ?expr(E));
View
@@ -41,7 +41,7 @@ basic_test() ->
100 = D1.baz,
% accessing undefined field
- {'EXIT', {badarg, _}} = (catch D.bar),
+ {'EXIT', {'erlson_not_found', _}} = (catch D.bar),
% several elements
D2 = D#{bar = 1, fum = 10, obj = D},
@@ -55,8 +55,20 @@ basic_test() ->
grammar_test() ->
dict_grammar(#{foo = 1}),
- foo().
-
+ foo(),
+ dict_grammar1(),
+ foo1(),
+ dict_grammar2(),
+ foo2(),
+ dict_grammar3(),
+ foo3(),
+ ok.
dict_grammar(D) -> D.foo, D. foo() -> ok.
+dict_grammar1() -> #{x = 1}. foo1() -> ok.
+
+dict_grammar2() -> #{x = 1}.x. foo2() -> ok.
+
+dict_grammar3() -> D = #{x = 1}, D.x. foo3() -> ok.
+

0 comments on commit cdd2bb9

Please sign in to comment.