Browse Source

* Render atom vars correctly
* Support for string literals in "if ... in" syntax

Evan Miller 15 years ago
parent
commit
bcf88533c5
3 changed files with 29 additions and 20 deletions
  1. 19 18
      src/erlydtl/erlydtl_compiler.erl
  2. 6 2
      src/erlydtl/erlydtl_runtime.erl
  3. 4 0
      src/tests/erlydtl_unittests.erl

+ 19 - 18
src/erlydtl/erlydtl_compiler.erl

@@ -530,6 +530,22 @@ resolve_variable_ast({apply_filter, Variable, Filter}, Context, FinderFunction)
 resolve_variable_ast(What, _Context, _FinderFunction) ->
    error_logger:error_msg("~p:resolve_variable_ast unhandled: ~p~n", [?MODULE, What]).
 
+resolve_multiple_ifvariable_ast(Args, Info, Context) ->
+    lists:foldr(fun
+            (X, {Asts, AccVarNames}) ->
+                case X of
+                    {string_literal, _, Literal} ->
+                        {[erl_syntax:string(unescape_string_literal(Literal)) | Asts], AccVarNames};
+                    {number_literal, _, Literal} ->
+                        {[erl_syntax:integer(list_to_integer(Literal)) | Asts], AccVarNames};
+                    Variable ->
+                        {Ast, VarName} = resolve_ifvariable_ast(Variable, Context),
+                        {[Ast | Asts], [VarName | AccVarNames]}
+                end                
+        end,
+        {[], Info#ast_info.var_names},
+        Args).
+
 resolve_scoped_variable_ast(VarName, Context) ->
     lists:foldl(fun(Scope, Value) ->
                 case Value of
@@ -561,15 +577,13 @@ ifelse_ast({'not', Expression}, IfAstInfo, ElseAstInfo, Context, TreeWalker) ->
     ifelse_ast(Expression, ElseAstInfo, IfAstInfo, Context, TreeWalker);
 ifelse_ast({'in', Variable1, Variable2}, {IfContentsAst, IfContentsInfo}, {ElseContentsAst, ElseContentsInfo}, Context, TreeWalker) ->
     Info = merge_info(IfContentsInfo, ElseContentsInfo),
-    VarNames = Info#ast_info.var_names,
-    {Ast1, VarName1} = resolve_ifvariable_ast(Variable1, Context),
-    {Ast2, VarName2} = resolve_ifvariable_ast(Variable2, Context),
+    {[Ast1, Ast2], VarNames} = resolve_multiple_ifvariable_ast([Variable1, Variable2], Info, Context),
     {{erl_syntax:case_expr(erl_syntax:application(erl_syntax:atom(erlydtl_runtime), erl_syntax:atom(is_in), [Ast1, Ast2]),
         [erl_syntax:clause([erl_syntax:atom(true)], none, 
                 [IfContentsAst]),
             erl_syntax:clause([erl_syntax:underscore()], none,
                 [ElseContentsAst])
-        ]), Info#ast_info{var_names = [VarName1, VarName2 | VarNames]}}, TreeWalker};
+        ]), Info#ast_info{var_names = VarNames}}, TreeWalker};
 ifelse_ast(Variable, {IfContentsAst, IfContentsInfo}, {ElseContentsAst, ElseContentsInfo}, Context, TreeWalker) ->
     Info = merge_info(IfContentsInfo, ElseContentsInfo),
     VarNames = Info#ast_info.var_names,
@@ -584,20 +598,7 @@ ifelse_ast(Variable, {IfContentsAst, IfContentsInfo}, {ElseContentsAst, ElseCont
         
 ifequalelse_ast(Args, {IfContentsAst, IfContentsInfo}, {ElseContentsAst, ElseContentsInfo}, Context, TreeWalker) ->
     Info = merge_info(IfContentsInfo, ElseContentsInfo),
-    {[Arg1Ast, Arg2Ast], VarNames} = lists:foldl(fun
-            (X, {Asts, AccVarNames}) ->
-                case X of
-                    {string_literal, _, Literal} ->
-                        {[erl_syntax:string(unescape_string_literal(Literal)) | Asts], AccVarNames};
-                    {number_literal, _, Literal} ->
-                        {[erl_syntax:integer(list_to_integer(Literal)) | Asts], AccVarNames};
-                    Variable ->
-                        {Ast, VarName} = resolve_ifvariable_ast(Variable, Context),
-                        {[Ast | Asts], [VarName | AccVarNames]}
-                end                
-        end,
-        {[], Info#ast_info.var_names},
-        Args),
+    {[Arg1Ast, Arg2Ast], VarNames} = resolve_multiple_ifvariable_ast(Args, Info, Context),
     Ast = erl_syntax:case_expr(erl_syntax:application(erl_syntax:atom(erlydtl_runtime), erl_syntax:atom(are_equal),
             [Arg1Ast, Arg2Ast]),
         [

+ 6 - 2
src/erlydtl/erlydtl_runtime.erl

@@ -30,8 +30,8 @@ find_value(Key, Tuple) when is_tuple(Tuple) ->
                     undefined
             end;
         Module ->
-            case proplists:get_value(Key, Module:module_info(exports)) of
-                1 ->
+            case lists:member({Key, 1}, Module:module_info(exports)) of
+                true ->
                     Tuple:Key();
                 _ ->
                     undefined
@@ -84,6 +84,8 @@ is_false(_) ->
 
 is_in(Sublist, [Sublist|_]) ->
     true;
+is_in(Sublist, List) when is_atom(List) ->
+    is_in(Sublist, atom_to_list(List));
 is_in(Sublist, List) when is_binary(Sublist) ->
     is_in(binary_to_list(Sublist), List);
 is_in(Sublist, List) when is_binary(List) ->
@@ -105,6 +107,8 @@ stringify_final([], Out) ->
    lists:reverse(Out);
 stringify_final([El | Rest], Out) when is_atom(El) ->
    stringify_final(Rest, [atom_to_list(El) | Out]);
+stringify_final([El | Rest], Out) when is_list(El) ->
+   stringify_final(Rest, [stringify_final(El) | Out]);
 stringify_final([El | Rest], Out) ->
    stringify_final(Rest, [El | Out]).
 

+ 4 - 0
src/tests/erlydtl_unittests.erl

@@ -109,6 +109,10 @@ tests() ->
                     <<"{% if var1 not in var2 %}yay{% endif %}">>, [{var1, "Cook"}, {var2, "Crooks"}], <<"yay">>},
                 {"If substring not in string (false)",
                     <<"{% if var1 not in var2 %}boo{% endif %}">>, [{var1, "rook"}, {var2, "Crooks"}], <<>>},
+                {"If literal substring in string",
+                    <<"{% if \"man\" in \"Ottoman\" %}yay{% endif %}">>, [], <<"yay">>},
+                {"If literal substring in string (false)",
+                    <<"{% if \"woman\" in \"Ottoman\" %}boo{% endif %}">>, [], <<>>},
                 {"If element in list",
                     <<"{% if var1 in var2 %}yay{% endif %}">>, [{var1, "foo"}, {var2, ["bar", "foo", "baz"]}], <<"yay">>},
                 {"If element in list (false)",