Browse Source

Fixed firstof functionality, an i bug fixed simultaneously

Alex Songe 15 years ago
parent
commit
011833a653

+ 13 - 0
src/erlydtl/erlydtl_compiler.erl

@@ -378,6 +378,8 @@ body_ast(DjangoParseTree, Context, TreeWalker) ->
             	call_ast(Name, TreeWalkerAcc);
             ({'call', {'identifier', _, Name}, With}, TreeWalkerAcc) ->
             	call_with_ast(Name, With, Context, TreeWalkerAcc);
+		    ({'firstof', Vars}, TreeWalkerAcc) ->
+				 firstof_ast(Vars, Context, TreeWalkerAcc);
             ({'cycle', Names}, TreeWalkerAcc) ->
                 cycle_ast(Names, Context, TreeWalkerAcc);
             ({'cycle_compat', Names}, TreeWalkerAcc) ->
@@ -563,6 +565,17 @@ auto_escape(Value, Context) ->
             Value
     end.
 
+firstof_ast(Vars, Context, TreeWalker) ->
+	body_ast([lists:foldl(fun
+        ({L, _, _}=Var, []) when L=:=string_literal;L=:=number_literal ->
+            Var;
+        ({L, _, _}, _) when L=:=string_literal;L=:=number_literal ->
+            erlang:error(errbadliteral);
+        (Var, []) ->
+            {'ifelse', Var, [Var], []};
+        (Var, Acc) ->
+            {'ifelse', Var, [Var], [Acc]} end,
+    	[], Vars)], Context, TreeWalker).
 
 ifelse_ast(Variable, {IfContentsAst, IfContentsInfo}, {ElseContentsAst, ElseContentsInfo}, Context, TreeWalker) ->
     Info = merge_info(IfContentsInfo, ElseContentsInfo),

+ 1 - 14
src/erlydtl/erlydtl_parser.yrl

@@ -196,7 +196,7 @@ CycleNamesCompat -> CycleNamesCompat identifier comma : '$1' ++ ['$2'].
 CycleNamesCompat -> CycleNamesCompat identifier : '$1' ++ ['$2'].
 
 FirstofTag -> open_tag firstof_keyword FirstofList close_tag : '$3'.
-FirstofList -> FirstofValues : firstof_create('$1').
+FirstofList -> FirstofValues : {firstof, '$1'}.
 FirstofValues -> FirstofValues Value : ['$2'|'$1'].
 FirstofValues -> Value : ['$1'].
 
@@ -245,16 +245,3 @@ Args -> Args identifier equal Value : '$1' ++ [{'$2', '$4'}].
 
 CallTag -> open_tag call_keyword identifier close_tag : {call, '$3'}.
 CallWithTag -> open_tag call_keyword identifier with_keyword Value close_tag : {call, '$3', '$5'}.
-
-Erlang code.
-firstof_create(List) when is_list(List) ->
-    lists:foldl(fun
-        ({L, _, _}=Var, []) when L=:=string_literal;L=:=number_literal ->
-            Var;
-        ({L, _, _}, _) when L=:=string_literal;L=:=number_literal ->
-            erlang:error(errbadliteral);
-        (Var, []) ->
-            {'ifelse', Var, [Var], []};
-        (Var, Acc) ->
-            {'ifelse', Var, [Var], [Acc]} end,
-    [], List).

+ 8 - 0
src/erlydtl/erlydtl_runtime.erl

@@ -2,6 +2,8 @@
 
 -compile(export_all).
 
+find_value(_, undefined) ->
+	undefined;
 find_value(Key, Fun) when is_function(Fun, 1) ->
     Fun(Key);
 find_value(Key, L) when is_list(L) ->
@@ -116,3 +118,9 @@ increment_counter_stats([{counter, Counter}, {counter0, Counter0}, {revcounter,
 
 cycle(NamesTuple, Counters) when is_tuple(NamesTuple) ->
     element(fetch_value(counter0, Counters) rem size(NamesTuple) + 1, NamesTuple).
+
+firstof([]) ->
+	[];
+
+firstof(Any) ->
+	io:format("Unhandled firstof: ~p~n", [Any]).

+ 30 - 2
src/tests/erlydtl_unittests.erl

@@ -104,7 +104,9 @@ tests() ->
                 {"If non-empty string",
                     <<"{% if var1 %}yay{% endif %}">>, [{var1, "hello"}], <<"yay">>},
                 {"If proplist",
-                    <<"{% if var1 %}yay{% endif %}">>, [{var1, [{foo, "bar"}]}], <<"yay">>}
+                    <<"{% if var1 %}yay{% endif %}">>, [{var1, [{foo, "bar"}]}], <<"yay">>},
+				{"If complex",
+					<<"{% if foo.bar.baz %}omgwtfbbq{% endif %}">>, [], <<"">>}
             ]},
         {"for", [
                 {"Simple loop",
@@ -357,7 +359,33 @@ tests() ->
                     <<"{% ifequal var1|length 1 %}Y{% else %}N{% endifequal %}">>,
                      [{var1, ["foo", "bar", "baz"]}],
                      <<"N">>}
-        ]}
+        ]},
+		{"firstof", [
+				{"Firstof first",
+				 	<<"{% firstof foo bar baz %}">>,
+				 	[{foo, "1"},{bar, "2"}],
+				 	<<"1">>},
+				{"Firstof second",
+				 	<<"{% firstof foo bar baz %}">>,
+				 	[{bar, "2"}],
+				 	<<"2">>},
+				{"Firstof none",
+				 	<<"{% firstof foo bar baz %}">>,
+				 	[],
+				 	<<"">>},
+				{"Firstof complex",
+				 	<<"{% firstof foo.bar.baz bar %}">>,
+				 	[{foo, [{bar, [{baz, "quux"}]}]}],
+				 	<<"quux">>},
+				{"Firstof undefined complex",
+				 	<<"{% firstof foo.bar.baz bar %}">>,
+				 	[{bar, "bar"}],
+				 	<<"bar">>},
+				{"Firstof literal",
+				 	<<"{% firstof foo bar \"baz\" %}">>,
+				 	[],
+				 	<<"baz">>}
+			]}
     ].
 
 run_tests() ->