As a (hopeful) final note, I figured out the correct way to escape the
expression:
for rule in all_rules
if typeof(rule.action) != Function
dot = Expr(:(.), rule, QuoteNode(:action))
fn = Expr(:(->),
Expr(:tuple, :rule, :value, :first, :last, :children),
Expr(:block, rule.action))
push!(code, Expr(:escape, Expr(:(=), dot, fn)))
end
end
which seems to do the trick.
On Monday, March 23, 2015 at 8:00:23 AM UTC-4, Abe Schneider wrote:
>
> Okay, I think I almost have a solution. I now collect all the actions from
> the rules with the function:
>
> function collect_rules(rule::Rule, lst::Array)
> push!(lst, rule)
>
> for child in get_children(rule)
> collect_rules(child, lst)
> end
>
> return lst
> end
>
>
> which is called from the loop:
>
> all_rules = Rule[]
> code = {}
>
> for definition in expr.args[2:2:end]
> name = string(definition.args[1])
> ref_by_name = Expr(:ref, :rules, name)
>
> rule = parseDefinition(name, definition.args[2], pdata)
> push!(code, :(rules[$name] = $rule))
> all_rules = collect_rules(rule, all_rules)
> end
>
> Finally, I add the transform to all the actions in the loop:
>
> for rule in all_rules
> if typeof(rule.action) != Function
> dot = Expr(:(.), rule, QuoteNode(:action))
> fn = Expr(:(->),
> Expr(:tuple, :rule, :value, :first, :last, :children),
> Expr(:block, rule.action))
> push!(code, Expr(:(=), dot, fn))
> end
> end
>
>
> Unfortunately, I'm still getting the namespace problem. I assume this is
> because I'm not escaping properly in the macro. However, after playing
> around with different variations, I can't figure out the proper place to
> put the escape.
>
> Thanks for all the help!
>
>
>
>
> On Sunday, March 22, 2015 at 10:02:28 AM UTC-4, Jameson wrote:
>>
>> the trick with macros is that everything should be generating code, not
>> actually evaluating that code. think of it as a series of functions that do
>> a text transformation to a new structured document, not a [partial]
>> execution of that document. for example:
>>
>> function parseDefinition(name::String, expr::Expr, pdata::ParserData)
>> #...
>> elseif expr.head === :curly
>> action_expr = expand_names(expr.args[2])
>> rule_expr = parseDefinition(name, expr.args[1], action_expr, pdata)
>> else
>> #...
>> return rule_expr
>> end
>> macro doAction(expr)
>> return parseDefinition(..., expr, ...)
>> end
>>
>> On Sun, Mar 22, 2015 at 8:15 AM Abe Schneider [email protected]
>> <http://mailto:[email protected]> wrote:
>>
>> I'm in the process of trying to figure out how to do something similar to
>>> that, but it's unfortunately not easy. I was hoping that there might be a
>>> method to insert an expression into the AST without an eval required, as it
>>> would greatly simplify the code Jameson suggested using the `insert` macro,
>>> which does as advertised, expect for the namespace issue.
>>>
>>>
>>
>