Skip to content
Browse files

added optional "OutDir" argument to compile command

  • Loading branch information...
1 parent 873b0ef commit 27cac56db6ccd890dd3ce59bfa2e42999a1a4441 @rsaccon rsaccon committed Jan 11, 2008
Showing with 173 additions and 169 deletions.
  1. +1 −2 Makefile
  2. +172 −167 src/erlydtl/erlydtl_compiler.erl
View
3 Makefile
@@ -5,8 +5,7 @@ APP_NAME=erlydtl
all:
- ( $(ERL) -make && \
- if [ ! -e ebin/$(APP_NAME).app ]; then cp -f src/$(APP_NAME)/$(APP_NAME).app.src ebin/$(APP_NAME).app; fi )
+ $(ERL) -make
run:
$(ERL) -pa `pwd`/ebin -s $(APP_NAME)
View
339 src/erlydtl/erlydtl_compiler.erl
@@ -35,69 +35,74 @@
-author('emmiller@gmail.com').
-author('emmiller@gmail.com').
--export([compile/3, compile/2, compile/4, parse/1, scan/1]).
+-export([compile/2, compile/3, compile/4, compile/5, parse/1, scan/1]).
-record(dtl_context, {
- local_scopes = [],
- block_dict = dict:new(),
- auto_escape = off,
- doc_root = "",
- parse_trail = []}).
+ local_scopes = [],
+ block_dict = dict:new(),
+ auto_escape = off,
+ doc_root = "",
+ parse_trail = []}).
compile(File, Module) ->
compile(File, "", Module).
compile(File, DocRoot, Module) ->
compile(File, DocRoot, Module, "render").
-
+
compile(File, DocRoot, Module, Function) ->
+ compile(File, DocRoot, Module, Function, "ebin").
+
+compile(File, DocRoot, Module, Function, OutDir) ->
case parse(File) of
{ok, DjangoAst} ->
- RenderFunctionAst = erl_syntax:function(
- erl_syntax:atom(Function),
- [erl_syntax:clause([erl_syntax:variable("Variables")], none,
- [body_ast(DjangoAst, #dtl_context{doc_root = DocRoot, parse_trail = [File]})])]),
- ExtensionFunctionAst = erl_syntax:function(
- erl_syntax:atom(file_extension),
- [erl_syntax:clause([], none, [erl_syntax:string(file_extension(File))])]),
- ModuleAst = erl_syntax:attribute(erl_syntax:atom(module), [erl_syntax:atom(Module)]),
- CompileAst = erl_syntax:attribute(erl_syntax:atom(compile), [erl_syntax:atom("export_all")]),
+ RenderFunctionAst = erl_syntax:function(
+ erl_syntax:atom(Function),
+ [erl_syntax:clause([erl_syntax:variable("Variables")], none,
+ [body_ast(DjangoAst, #dtl_context{doc_root = DocRoot, parse_trail = [File]})])]),
+ ExtensionFunctionAst = erl_syntax:function(
+ erl_syntax:atom(file_extension),
+ [erl_syntax:clause([], none, [erl_syntax:string(file_extension(File))])]),
+ ModuleAst = erl_syntax:attribute(erl_syntax:atom(module), [erl_syntax:atom(Module)]),
+ CompileAst = erl_syntax:attribute(erl_syntax:atom(compile), [erl_syntax:atom("export_all")]),
- Forms = [erl_syntax:revert(X) || X <- [ModuleAst, CompileAst, ExtensionFunctionAst, RenderFunctionAst]],
+ Forms = [erl_syntax:revert(X) || X <- [ModuleAst, CompileAst, ExtensionFunctionAst, RenderFunctionAst]],
- case compile:forms(Forms) of
- {ok, Module1, Bin} ->
- case file:write_file(atom_to_list(Module1) ++ ".beam", Bin) of
- ok ->
- code:purge(Module1),
- case code:load_binary(Module1, atom_to_list(Module1) ++ ".erl", Bin) of
- {module, _} -> ok;
- _ -> {error, "code reload failed"}
- end;
- _ ->
- {error, "beam generation failed"}
- end;
- _ ->
- {error, "compilation failed"}
- end;
- Error ->
- Error
+ case compile:forms(Forms) of
+ {ok, Module1, Bin} ->
+ Path = filename:join([OutDir, atom_to_list(Module1) ++ ".beam"]),
+ case file:write_file(Path, Bin) of
+ ok ->
+ code:purge(Module1),
+ case code:load_binary(Module1, atom_to_list(Module1) ++ ".erl", Bin) of
+ {module, _} -> ok;
+ _ -> {error, "code reload failed"}
+ end;
+ _ ->
+ {error, "beam generation failed"}
+ end;
+ _ ->
+ {error, "compilation failed"}
+ end;
+ Error ->
+ Error
end.
-
+
+
scan(File) ->
case file:read_file(File) of
{ok, B} ->
- erlydtl_scanner:scan(binary_to_list(B));
+ erlydtl_scanner:scan(binary_to_list(B));
_ ->
- {error, "reading " ++ File ++ " failed "}
+ {error, "reading " ++ File ++ " failed "}
end.
parse(File) ->
case scan(File) of
- {ok, Tokens} ->
- erlydtl_parser:parse(Tokens);
- Err ->
- Err
+ {ok, Tokens} ->
+ erlydtl_parser:parse(Tokens);
+ Err ->
+ Err
end.
full_path(File, DocRoot) ->
@@ -111,74 +116,74 @@ body_ast([{extends, {string_literal, _Pos, String}} | ThisAst], Context) ->
File = full_path(unescape_string_literal(String), Context#dtl_context.doc_root),
case lists:member(File, Context#dtl_context.parse_trail) of
true ->
- {error, "Circular file inclusion!"};
+ {error, "Circular file inclusion!"};
_ ->
- {ok, ParentAst} = parse(File),
- BlockDict = lists:foldl(
- fun
- ({block, {identifier, _, Name}, Contents}, Dict) ->
- dict:store(Name, Contents, Dict);
- (_, Dict) ->
- Dict
- end, dict:new(), ThisAst),
- body_ast(ParentAst, Context#dtl_context{
- block_dict =
- dict:merge(fun(_Key, _ParentVal, ChildVal) -> ChildVal end,
- BlockDict, Context#dtl_context.block_dict),
- parse_trail = [File | Context#dtl_context.parse_trail]
- })
+ {ok, ParentAst} = parse(File),
+ BlockDict = lists:foldl(
+ fun
+ ({block, {identifier, _, Name}, Contents}, Dict) ->
+ dict:store(Name, Contents, Dict);
+ (_, Dict) ->
+ Dict
+ end, dict:new(), ThisAst),
+ body_ast(ParentAst, Context#dtl_context{
+ block_dict =
+ dict:merge(fun(_Key, _ParentVal, ChildVal) -> ChildVal end,
+ BlockDict, Context#dtl_context.block_dict),
+ parse_trail = [File | Context#dtl_context.parse_trail]
+ })
end;
body_ast(DjangoAst, Context) ->
erl_syntax:list(
lists:map(fun
({'block', {identifier, _, Name}, Contents}) ->
- Block = case dict:find(Name, Context#dtl_context.block_dict) of
- {ok, ChildBlock} ->
- ChildBlock;
- _ ->
- Contents
- end,
- body_ast(Block, Context);
+ Block = case dict:find(Name, Context#dtl_context.block_dict) of
+ {ok, ChildBlock} ->
+ ChildBlock;
+ _ ->
+ Contents
+ end,
+ body_ast(Block, Context);
({'comment', _Contents}) ->
- erl_syntax:list([]);
- ({'autoescape', {identifier, _, OnOrOff}, Contents}) ->
- body_ast(Contents, Context#dtl_context{auto_escape = list_to_atom(OnOrOff)});
- ({'text', _Pos, String}) ->
- erl_syntax:string(String);
- ({'string_literal', _Pos, String}) ->
- erl_syntax:string(unescape_string_literal(String));
- ({'number_literal', _Pos, Number}) ->
- erl_syntax:string(Number);
- ({'variable', Variable}) ->
- resolve_variable_ast(Variable, Context);
+ erl_syntax:list([]);
+ ({'autoescape', {identifier, _, OnOrOff}, Contents}) ->
+ body_ast(Contents, Context#dtl_context{auto_escape = list_to_atom(OnOrOff)});
+ ({'text', _Pos, String}) ->
+ erl_syntax:string(String);
+ ({'string_literal', _Pos, String}) ->
+ erl_syntax:string(unescape_string_literal(String));
+ ({'number_literal', _Pos, Number}) ->
+ erl_syntax:string(Number);
+ ({'variable', Variable}) ->
+ resolve_variable_ast(Variable, Context);
({'tag', {identifier, _, Name}, Args}) ->
- tag_ast(Name, Args, Context);
- ({'include', {string_literal, _, File}}) ->
- FilePath = full_path(unescape_string_literal(File), Context#dtl_context.doc_root),
- {ok, IncludeAst} = parse(FilePath),
- body_ast(IncludeAst,
- Context#dtl_context{parse_trail =
- [FilePath | Context#dtl_context.parse_trail]});
- ({'if', {variable, Variable}, Contents}) ->
- ifelse_ast(Variable, body_ast(Contents, Context),
- erl_syntax:list([]), Context);
- ({'if', {'not', {variable, Variable}}, Contents}) ->
- ifelse_ast(Variable, erl_syntax:list([]),
- body_ast(Contents, Context), Context);
- ({'ifelse', {variable, Variable}, IfContents, ElseContents}) ->
- ifelse_ast(Variable, body_ast(IfContents, Context),
- body_ast(ElseContents, Context), Context);
- ({'ifelse', {'not', {variable, Variable}}, IfContents, ElseContents}) ->
- ifelse_ast(Variable, body_ast(ElseContents, Context),
- body_ast(IfContents, Context), Context);
+ tag_ast(Name, Args, Context);
+ ({'include', {string_literal, _, File}}) ->
+ FilePath = full_path(unescape_string_literal(File), Context#dtl_context.doc_root),
+ {ok, IncludeAst} = parse(FilePath),
+ body_ast(IncludeAst,
+ Context#dtl_context{parse_trail =
+ [FilePath | Context#dtl_context.parse_trail]});
+ ({'if', {variable, Variable}, Contents}) ->
+ ifelse_ast(Variable, body_ast(Contents, Context),
+ erl_syntax:list([]), Context);
+ ({'if', {'not', {variable, Variable}}, Contents}) ->
+ ifelse_ast(Variable, erl_syntax:list([]),
+ body_ast(Contents, Context), Context);
+ ({'ifelse', {variable, Variable}, IfContents, ElseContents}) ->
+ ifelse_ast(Variable, body_ast(IfContents, Context),
+ body_ast(ElseContents, Context), Context);
+ ({'ifelse', {'not', {variable, Variable}}, IfContents, ElseContents}) ->
+ ifelse_ast(Variable, body_ast(ElseContents, Context),
+ body_ast(IfContents, Context), Context);
({'apply_filter', Variable, Filter}) ->
- filter_ast(Variable, Filter, Context);
- ({'for', {'in', {identifier, _, Iterator}, {identifier, _, List}}, Contents}) ->
- for_loop_ast(Iterator, List, Contents, Context);
- ({'for', {'in', IteratorList, {identifier, _, List}}, Contents}) when is_list(IteratorList) ->
- for_list_loop_ast(IteratorList, List, Contents, Context)
- end, DjangoAst)
+ filter_ast(Variable, Filter, Context);
+ ({'for', {'in', {identifier, _, Iterator}, {identifier, _, List}}, Contents}) ->
+ for_loop_ast(Iterator, List, Contents, Context);
+ ({'for', {'in', IteratorList, {identifier, _, List}}, Contents}) when is_list(IteratorList) ->
+ for_list_loop_ast(IteratorList, List, Contents, Context)
+ end, DjangoAst)
).
filter_ast(Variable, Filter, Context) ->
@@ -188,24 +193,24 @@ filter_ast(Variable, Filter, Context) ->
% so don't do any more escaping
case search_for_escape_filter(Variable, Filter, Context) of
on ->
- erl_syntax:application(erl_syntax:atom(erlydtl_filters), erl_syntax:atom(force_escape),
- [filter_ast_noescape(Variable, Filter, Context#dtl_context{auto_escape = did})]);
- _ ->
- filter_ast_noescape(Variable, Filter, Context#dtl_context{auto_escape = did})
+ erl_syntax:application(erl_syntax:atom(erlydtl_filters), erl_syntax:atom(force_escape),
+ [filter_ast_noescape(Variable, Filter, Context#dtl_context{auto_escape = did})]);
+ _ ->
+ filter_ast_noescape(Variable, Filter, Context#dtl_context{auto_escape = did})
end.
filter_ast_noescape(Variable, [{identifier, _, "escape"}], Context) ->
body_ast([Variable], Context);
filter_ast_noescape(Variable, [{identifier, _, Name} | Arg], Context) ->
erl_syntax:application(erl_syntax:atom(erlydtl_filters), erl_syntax:atom(Name),
- [body_ast([Variable], Context) | case Arg of
- [{string_literal, _, ArgName}] ->
- [erl_syntax:string(unescape_string_literal(ArgName))];
- [{number_literal, _, ArgName}] ->
- [erl_syntax:integer(list_to_integer(ArgName))];
- _ ->
- []
- end]).
+ [body_ast([Variable], Context) | case Arg of
+ [{string_literal, _, ArgName}] ->
+ [erl_syntax:string(unescape_string_literal(ArgName))];
+ [{number_literal, _, ArgName}] ->
+ [erl_syntax:integer(list_to_integer(ArgName))];
+ _ ->
+ []
+ end]).
search_for_escape_filter(_, _, #dtl_context{auto_escape = on}) ->
on;
@@ -226,84 +231,84 @@ resolve_variable_ast({{identifier, _, VarName}}, Context) ->
resolve_variable_ast({{identifier, _, VarName}, {identifier, _, AttrName}}, Context) ->
erl_syntax:application(erl_syntax:atom(proplists), erl_syntax:atom(get_value),
- [erl_syntax:atom(AttrName), resolve_variable_name_ast(VarName, Context)]).
+ [erl_syntax:atom(AttrName), resolve_variable_name_ast(VarName, Context)]).
resolve_variable_name_ast(VarName, Context) ->
VarValue = lists:foldl(fun(Scope, Value) ->
- case Value of
- undefined ->
- proplists:get_value(list_to_atom(VarName), Scope);
- _ ->
- Value
- end
- end, undefined, Context#dtl_context.local_scopes),
+ case Value of
+ undefined ->
+ proplists:get_value(list_to_atom(VarName), Scope);
+ _ ->
+ Value
+ end
+ end, undefined, Context#dtl_context.local_scopes),
VarValue1 = case VarValue of
- undefined ->
- erl_syntax:application(erl_syntax:atom(proplists), erl_syntax:atom(get_value),
- [erl_syntax:atom(VarName), erl_syntax:variable("Variables")]);
- _ ->
- VarValue
- end,
+ undefined ->
+ erl_syntax:application(erl_syntax:atom(proplists), erl_syntax:atom(get_value),
+ [erl_syntax:atom(VarName), erl_syntax:variable("Variables")]);
+ _ ->
+ VarValue
+ end,
case Context#dtl_context.auto_escape of
on ->
- erl_syntax:application(erl_syntax:atom(emiller_filters), erl_syntax:atom(force_escape),
- [VarValue1]);
- _ ->
- VarValue1
+ erl_syntax:application(erl_syntax:atom(emiller_filters), erl_syntax:atom(force_escape),
+ [VarValue1]);
+ _ ->
+ VarValue1
end.
ifelse_ast(Variable, IfContentsAst, ElseContentsAst, Context) ->
erl_syntax:case_expr(resolve_variable_ast(Variable, Context),
- [erl_syntax:clause([erl_syntax:string("")], none,
- [ElseContentsAst]),
- erl_syntax:clause([erl_syntax:atom(undefined)], none,
- [ElseContentsAst]),
- erl_syntax:clause([erl_syntax:integer(0)], none,
- [ElseContentsAst]),
- erl_syntax:clause([erl_syntax:underscore()], none,
- [IfContentsAst])
- ]).
+ [erl_syntax:clause([erl_syntax:string("")], none,
+ [ElseContentsAst]),
+ erl_syntax:clause([erl_syntax:atom(undefined)], none,
+ [ElseContentsAst]),
+ erl_syntax:clause([erl_syntax:integer(0)], none,
+ [ElseContentsAst]),
+ erl_syntax:clause([erl_syntax:underscore()], none,
+ [IfContentsAst])
+ ]).
for_loop_ast(Iterator, List, Contents, Context) ->
erl_syntax:application(erl_syntax:atom(lists), erl_syntax:atom(map),
- [erl_syntax:fun_expr([
- erl_syntax:clause([erl_syntax:variable("Var_" ++ Iterator)],
- none, [body_ast(Contents,
- Context#dtl_context{local_scopes =
- [[{list_to_atom(Iterator), erl_syntax:variable("Var_" ++ Iterator)}]
- | Context#dtl_context.local_scopes]
- })]
- )]),
- resolve_variable_name_ast(list_to_atom(List), Context)]).
+ [erl_syntax:fun_expr([
+ erl_syntax:clause([erl_syntax:variable("Var_" ++ Iterator)],
+ none, [body_ast(Contents,
+ Context#dtl_context{local_scopes =
+ [[{list_to_atom(Iterator), erl_syntax:variable("Var_" ++ Iterator)}]
+ | Context#dtl_context.local_scopes]
+ })]
+ )]),
+ resolve_variable_name_ast(list_to_atom(List), Context)]).
for_list_loop_ast(IteratorList, List, Contents, Context) ->
erl_syntax:application(erl_syntax:atom(lists), erl_syntax:atom(map),
- [erl_syntax:fun_expr([
- erl_syntax:clause([erl_syntax:list(
- lists:map(fun({identifier, _, Iterator}) ->
- erl_syntax:variable("Var_" ++ Iterator)
- end, IteratorList))],
- none, [body_ast(Contents,
- Context#dtl_context{local_scopes = [lists:map(fun({identifier, _, Iterator}) ->
- {list_to_atom(Iterator), erl_syntax:variable("Var_" ++ Iterator)}
- end, IteratorList)
- | Context#dtl_context.local_scopes]})]
- )]),
+ [erl_syntax:fun_expr([
+ erl_syntax:clause([erl_syntax:list(
+ lists:map(fun({identifier, _, Iterator}) ->
+ erl_syntax:variable("Var_" ++ Iterator)
+ end, IteratorList))],
+ none, [body_ast(Contents,
+ Context#dtl_context{local_scopes = [lists:map(fun({identifier, _, Iterator}) ->
+ {list_to_atom(Iterator), erl_syntax:variable("Var_" ++ Iterator)}
+ end, IteratorList)
+ | Context#dtl_context.local_scopes]})]
+ )]),
resolve_variable_name_ast(list_to_atom(List), Context)]).
tag_ast(Name, Args, Context) ->
InterpretedArgs = lists:map(fun
- ({{identifier, _, Key}, {string_literal, _, Value}}) ->
- {list_to_atom(Key), erl_syntax:string(unescape_string_literal(Value))};
- ({{identifier, _, Key}, {variable, Value}}) ->
- {list_to_atom(Key), resolve_variable_ast(Value, Context)}
- end, Args),
+ ({{identifier, _, Key}, {string_literal, _, Value}}) ->
+ {list_to_atom(Key), erl_syntax:string(unescape_string_literal(Value))};
+ ({{identifier, _, Key}, {variable, Value}}) ->
+ {list_to_atom(Key), resolve_variable_ast(Value, Context)}
+ end, Args),
case parse(filename:join([erlydtl_deps:get_base_dir(), "priv", "tags", Name])) of
{ok, TagAst} ->
- body_ast(TagAst, Context#dtl_context{
- local_scopes = [ InterpretedArgs | Context#dtl_context.local_scopes ]});
- _ ->
- {error, Name, "Loading tag source failed"}
+ body_ast(TagAst, Context#dtl_context{
+ local_scopes = [ InterpretedArgs | Context#dtl_context.local_scopes ]});
+ _ ->
+ {error, Name, "Loading tag source failed"}
end.
unescape_string_literal(String) ->

0 comments on commit 27cac56

Please sign in to comment.
Something went wrong with that request. Please try again.