I still haven't been able to get the code to work with using quotes. 
However, with some experimentation I was able to write things out directly 
with Exprs. A condensed version of the code is:

macro grammar(grammar_name::Symbol, ex::Expr)
  code = {}
  push!(code, :(rules = Dict()))

  for definition in ex.args[2:2:end]
    name = Expr(:call, :string, Expr(:quote, definition.args[1]))
    ex = Expr(:quote, definition.args[2])
    action = Expr(:escape, definition.args[1].args[2])
      
    # rules[name] = parseDefinition(name, ex, nothing)
    push!(code, Expr(:(=), Expr(:ref, :rules, name), 
                Expr(:call, :parseDefinition, name, ex, action)))
  end

  # grammar_name = Grammar(rules)
  push!(code, :($(esc(grammar_name)) = Grammar(rules)))
  return Expr(:block, code...)
end

The tricky part being the definition of `action`. It can't be evaluated in 
the macro itself, as it would be in the wrong namespace, and thus had to be 
escaped. In a separate thread Tim Holy provided a method to get the 
expression passed to the `parseDefinition` method, but I couldn't get it to 
work with everything else.

I actually think keeping everything as `Expr`s is easier to understand, 
though I'm still curious how to properly express this in quote form.


On Thursday, August 7, 2014 1:51:30 PM UTC-4, Jameson wrote:
>
> A function which has access to the namespace in which it was defined is 
> also known in Julia as a closure, or simply function. All functions are 
> first-class objects, which don't need eval or macros. Eval and macros are 
> really bad at pretending to be functions. 
>
> Without a bit more example code, it is hard to understand what problem you 
> are trying to solve. Macros are for reducing typing (syntax transforms), 
> not magic (altering the environment), which is why they generally don't 
> have access to the environment. 
>
> On Friday, August 1, 2014, Abe Schneider <[email protected] 
> <javascript:>> wrote:
>
>> I tried a second approach where instead of keeping a function around I 
>> keep just the symbol. I have a `transform` function that applies the 
>> function to the resulting values. However, this only moves the problem to a 
>> new place. In my `transform` method I have:
>>
>> eval(Expr(:call, action, values))
>>
>>
>> where `action` is the symbol that I am now carrying around. The `eval` 
>> still works in the module's namespace, so I get the same error.
>>
>> If Julia had a way to access the namespace from the calling function, 
>> this could be made to work. Or for that matter, if I could get the calling 
>> namespace from the macro, I could then just get the macro that way.
>>
>> I'm guessing Julia doesn't currently have this functionality, but would 
>> it be something possible to add?
>>
>> On Friday, August 1, 2014 12:22:46 PM UTC-4, Abe Schneider wrote:
>>>
>>> I think the problem is that I'm not accessing it directly through the 
>>> macro parameters. The call:
>>>
>>> @grammar foo begin ... end
>>>
>>> passes just the single expression block to `foo`. Thus, I'm getting the 
>>> function from the resulting Expr tree. Even if I quote it, it still ends up 
>>> as an expression that contains a symbol that must be evaluated (unless I'm 
>>> missing something...)
>>>
>>>
>>> On Friday, August 1, 2014 11:42:52 AM UTC-4, Simon Kornblith wrote:
>>>>
>>>> That looks like the output of :(esc(fn)), but you don't want to quote 
>>>> that, you want to evaluate it when generating the code, i.e. use 
>>>> $(esc(fn)) wherever you were previously using $fn
>>>>
>>>> On Friday, August 1, 2014 11:38:44 AM UTC-4, Abe Schneider wrote:
>>>>>
>>>>> That's correct, I'm generating code that keeps a pointer to that 
>>>>> function to call later on.
>>>>>
>>>>> If I do that, I have the type `esc(fn)` in the macro (this is what I 
>>>>> get when printing it out), and taking a dump of that argument gives:
>>>>>
>>>>> Expr 
>>>>>   head: Symbol call
>>>>>   args: Array(Any,(2,))
>>>>>     1: Symbol esc
>>>>>     2: Symbol fn
>>>>>   typ: Any
>>>>>
>>>>>
>>>>> Does that mean instead of carrying around a function I will need to 
>>>>> carry around the Expr?
>>>>>
>>>>> Thanks!
>>>>>
>>>>> On Friday, August 1, 2014 11:17:50 AM UTC-4, Simon Kornblith wrote:
>>>>>>
>>>>>> Assuming you're generating code that calls fn, as opposed to trying 
>>>>>> to call it when generating code in the macro (usually a bad idea), you 
>>>>>> should use esc(fn) in place of fn
>>>>>>
>>>>>> On Friday, August 1, 2014 10:50:15 AM UTC-4, Abe Schneider wrote:
>>>>>>>
>>>>>>> I've come across a problem where I have macro to define  a grammar 
>>>>>>> (similar to how PEGParser currently works):
>>>>>>>
>>>>>>> @grammar foo begin
>>>>>>>   rule[fn] = "some" + ("rule" | "test")
>>>>>>> end
>>>>>>>
>>>>>>> where the `[fn]` next to the rule defines a function to call on the 
>>>>>>> results (in this case it's an expansion). The issue is that parsing the 
>>>>>>> Expr tree, `fn` is given as a Symbol (which makes sense).
>>>>>>>
>>>>>>> However, if I try to turn `fn` into a function I run into the 
>>>>>>> namespace issue I've had previously. If `fn` is defined in my module, 
>>>>>>> it 
>>>>>>> works without problem. If it's defined in the code that imports the 
>>>>>>> module, 
>>>>>>> it will not work because that function doesn't exist in the namespace 
>>>>>>> of 
>>>>>>> the module.
>>>>>>>
>>>>>>> I'm guessing there isn't an easy solution to fix this problem, but I 
>>>>>>> thought I'd check to see if someone had an idea.
>>>>>>>
>>>>>>> Thanks!
>>>>>>>
>>>>>>>  

Reply via email to