Re: [julia-users] accessing an expression's global scope from macro

2016-07-22 Thread Yichao Yu
>> You should not do this. It is possible to access the current module
>> but you don't have any scope information.
>
>
> Do you mean that its possible to get the module where the expression (not
> the macro) is defined? If so, how do I do that?
>

`current_module()` is the module the expression is being expanded in
but it is completely the wrong scope to resolve the symbols in. It's
fine to implement something that sort of works for yourself but this
should not be used in general.

>
>
>>
>>
>> >
>
>


Re: [julia-users] accessing an expression's global scope from macro

2016-07-22 Thread Marius Millea
On Thu, Jul 21, 2016 at 10:33 PM, Yichao Yu  wrote:

> On Thu, Jul 21, 2016 at 4:01 PM, Marius Millea 
> wrote:
> > In an attempt to make some numerical code (ie something thats basically
> just
> > a bunch of equations) more readable, I am trying to write a macro that
> lets
> > me write the code more succinctly. The code uses parameters from some
> data
> > structure, call it "mytype", so its littered with "t.a", "t.b", etc..
> where
> > t::mytype. My macro basically splices in the the "t." part for me. Its
> kind
> > of like how C++ member functions automatically access the class's
> fields, as
> > an example. To my amazement / growing love of Julia, I actually managed
> to
> > hack it together without too much difficulty, it looks like this,
> >
> >
> > macro self(func)
> > @assert func.head == :function
> >
> > # add "self" as a first function argument
> > insert!(func.args[1].args,2,:(self::mytype))
> >
> >
> > # recurse through AST and rename X to self.X if
> > # its a fieldname of mytype
> > function visit(ex)
> > if typeof(ex) == Expr
> > ex.args = map(visit,ex.args)
> > elseif (typeof(ex) == Symbol) & (ex in fieldnames(mytype))
> > return :(self.$ex)
> > end
> > ex
> > end
> > func.args[2] = visit(func.args[2])
> >
> > show(func) # print the edited function so we can see it in action
> >
> > :($(esc(func)))
> > end
> >
> >
> >
> >
> > Here it is in action:
> >
> >> @self function inc()
> > x = x + 1
> > end
> >
> >
> > :(function inc(self::mytype)
> > self.x = self.x + 1
> > end)
> >
> >
> > inc (generic function with 1 method)
> >
> >
> >
> >
> >> inc(mytype(0))
> > 1
> >
> >
> >
> > where I'm assuming I've defined mytype as
> >
> > type mytype
> > x
> > end
> >
> >
> >
> > As you can see, all it did was add self::mytype as an arg and replace x
> with
> > self.x everywhere it found it. This is also super nice because there is
> zero
> > run-time overhead vs. having written the "self." myself, everything
> happens
> > compile time.
> >
> > Now for the question. I'd like to also to be able automatically pass the
> > "self" argument to functions, so that I could write something like,
> >
> > @self function inc2()
> > inc()
> > inc()
> > end
> >
> >
> >
> > and it would produce
> >
> > function inc2(self::mytype)
> > inc(self)
> > inc(self)
> > end
> >
> >
> >
> > For this though, my macro needs to somehow figure out that "inc" was also
> > defined with @self (since it shouldn't blindly add self as a first arg so
> > other non-@self'ed function calls). Is this possible in Julia? I suppose
> > somehow the macro must access the global scope where the expression is
> being
> > evaluated? I'm not entirely sure that's doable. I'm happy to take any
> tips
> > how to achieve this though, especially ones incurring minimal overhead
> for
> > the rewritten function. Thanks!
>
> You should not do this. It is possible to access the current module
> but you don't have any scope information.
>

Do you mean that its possible to get the module where the expression (not
the macro) is defined? If so, how do I do that?




>
> >
>


Re: [julia-users] accessing an expression's global scope from macro

2016-07-21 Thread Yichao Yu
On Thu, Jul 21, 2016 at 4:01 PM, Marius Millea  wrote:
> In an attempt to make some numerical code (ie something thats basically just
> a bunch of equations) more readable, I am trying to write a macro that lets
> me write the code more succinctly. The code uses parameters from some data
> structure, call it "mytype", so its littered with "t.a", "t.b", etc.. where
> t::mytype. My macro basically splices in the the "t." part for me. Its kind
> of like how C++ member functions automatically access the class's fields, as
> an example. To my amazement / growing love of Julia, I actually managed to
> hack it together without too much difficulty, it looks like this,
>
>
> macro self(func)
> @assert func.head == :function
>
> # add "self" as a first function argument
> insert!(func.args[1].args,2,:(self::mytype))
>
>
> # recurse through AST and rename X to self.X if
> # its a fieldname of mytype
> function visit(ex)
> if typeof(ex) == Expr
> ex.args = map(visit,ex.args)
> elseif (typeof(ex) == Symbol) & (ex in fieldnames(mytype))
> return :(self.$ex)
> end
> ex
> end
> func.args[2] = visit(func.args[2])
>
> show(func) # print the edited function so we can see it in action
>
> :($(esc(func)))
> end
>
>
>
>
> Here it is in action:
>
>> @self function inc()
> x = x + 1
> end
>
>
> :(function inc(self::mytype)
> self.x = self.x + 1
> end)
>
>
> inc (generic function with 1 method)
>
>
>
>
>> inc(mytype(0))
> 1
>
>
>
> where I'm assuming I've defined mytype as
>
> type mytype
> x
> end
>
>
>
> As you can see, all it did was add self::mytype as an arg and replace x with
> self.x everywhere it found it. This is also super nice because there is zero
> run-time overhead vs. having written the "self." myself, everything happens
> compile time.
>
> Now for the question. I'd like to also to be able automatically pass the
> "self" argument to functions, so that I could write something like,
>
> @self function inc2()
> inc()
> inc()
> end
>
>
>
> and it would produce
>
> function inc2(self::mytype)
> inc(self)
> inc(self)
> end
>
>
>
> For this though, my macro needs to somehow figure out that "inc" was also
> defined with @self (since it shouldn't blindly add self as a first arg so
> other non-@self'ed function calls). Is this possible in Julia? I suppose
> somehow the macro must access the global scope where the expression is being
> evaluated? I'm not entirely sure that's doable. I'm happy to take any tips
> how to achieve this though, especially ones incurring minimal overhead for
> the rewritten function. Thanks!

You should not do this. It is possible to access the current module
but you don't have any scope information.

>


[julia-users] accessing an expression's global scope from macro

2016-07-21 Thread Marius Millea
In an attempt to make some numerical code (ie something thats basically 
just a bunch of equations) more readable, I am trying to write a macro that 
lets me write the code more succinctly. The code uses parameters from some 
data structure, call it "mytype", so its littered with "t.a", "t.b", etc.. 
where t::mytype. My macro basically splices in the the "t." part for me. 
Its kind of like how C++ member functions automatically access the class's 
fields, as an example. To my amazement / growing love of Julia, I actually 
managed to hack it together without too much difficulty, it looks like this,


macro self(func)
@assert func.head == :function
   
# add "self" as a first function argument
insert!(func.args[1].args,2,:(self::mytype))


# recurse through AST and rename X to self.X if 
# its a fieldname of mytype
function visit(ex)
if typeof(ex) == Expr
ex.args = map(visit,ex.args)
elseif (typeof(ex) == Symbol) & (ex in fieldnames(mytype))
return :(self.$ex)
end
ex
end
func.args[2] = visit(func.args[2])

show(func) # print the edited function so we can see it in action

:($(esc(func)))
end




Here it is in action:

> @self function inc()
x = x + 1
end


:(function inc(self::mytype) 
self.x = self.x + 1
end)


inc (generic function with 1 method)




> inc(mytype(0))
1



where I'm assuming I've defined mytype as 

type mytype
x
end



As you can see, all it did was add self::mytype as an arg and replace x 
with self.x everywhere it found it. This is also super nice because there 
is zero run-time overhead vs. having written the "self." myself, everything 
happens compile time. 

Now for the question. I'd like to also to be able automatically pass the 
"self" argument to functions, so that I could write something like, 

@self function inc2()
inc()
inc()
end



and it would produce

function inc2(self::mytype)
inc(self)
inc(self)
end



For this though, my macro needs to somehow figure out that "inc" was also 
defined with @self (since it shouldn't blindly add self as a first arg so 
other non-@self'ed function calls). Is this possible in Julia? I suppose 
somehow the macro must access the global scope where the expression is 
being evaluated? I'm not entirely sure that's doable. I'm happy to take any 
tips how to achieve this though, especially ones incurring minimal overhead 
for the rewritten function. Thanks!