On Mon, Mar 21, 2016 at 4:16 PM, Yichao Yu <[email protected]> wrote: > On Mon, Mar 21, 2016 at 4:11 PM, <[email protected]> wrote: >> I think I got that much down: >> >> function macroexpand(ex::Expr) >> if ex.head == :module >> Expr(:module, ex.args[1], ex.args[2], macroexpand(ex.args[3])) >> else >> macroexpand(ex) >> end >> end > > Seems that this will infinitely recurse? > >> >> >> the issue is that now I want to resolve all imports and such in the module >> so that when I expand it, I get properly qualified names for the macros. >> >> so if I had >> >> module M >> >> include("X.jl") >> import X: @y, @z >> >> f(x) = X.@y(3) >> >> end >> >> It would still be able to find X.@y. >> Evaluating the include/import myself would be kind of risky since someone >> could clobber a module name in my global namespace (of the program that's >> running to macroexpand this stuff). >> Is there a way to sandbox it?
And as I said, you should eval into the new module, not the one your own toplevel interpreter is running in. > > You are looking for a way to sandbox the whole julia runtime. I don't > think it's currently possible. Also note that macroexpansion is also > calling arbitrary code. > >> >> >> On Monday, March 21, 2016 at 1:00:01 PM UTC-7, Yichao Yu wrote: >>> >>> On Mon, Mar 21, 2016 at 3:57 PM, <[email protected]> wrote: >>> > So there's no way to macroexpand the module in the module scope itself? >>> > I don't mind evaluating the module, but how do I then dump out the >>> > macroexpanded version of it? >>> > >>> > If there's a way to "clear" global scope then it would also be possible >>> > to >>> > eval the module, expand in global scope, clean global scope, >>> > rinse/repeat on >>> > next module. >>> > Is there a way to do that instead? >>> > >>> >>> If you want to just repeat what the global interpreter is doing, you >>> can parse the module, create the module yourself, then macroexpand, >>> print and evaluate each statement. >>> >>> > >>> > On Monday, March 21, 2016 at 11:55:47 AM UTC-7, Tim Holy wrote: >>> >> >>> >> Interesting. julia's `macroexpand` function doesn't seem to work for >>> >> expressions inside a module: >>> >> >>> >> julia> macroexpand( :(module M @time(1+1) end)) >>> >> :(module M >>> >> eval(x) = begin # none, line 1: >>> >> top(Core).eval(M,x) >>> >> end >>> >> eval(m,x) = begin # none, line 1: >>> >> top(Core).eval(m,x) >>> >> end # none, line 1: >>> >> @time 1 + 1 >>> >> end) >>> >> >>> >> which is the same thing you get back if you omit the `macroexpand`. >>> >> >>> >> Try commenting out the module declaration and see if you like it >>> >> better. >>> >> >>> >> Best, >>> >> --Tim >>> >> >>> >> On Monday, March 21, 2016 11:15:56 AM [email protected] wrote: >>> >> > The MacroExpandJL package seems promising, but maybe I'm not able to >>> >> > get >>> >> > it >>> >> > to work. After updating syntax to match julia 0.4, >>> >> > MacroExpandJL.macroexpand_jl(STDOUT, :(module M function f(x) 1+@m(2) >>> >> > end >>> >> > end)) >>> >> > module M >>> >> > begin # line 1: >>> >> > function f(x) # line 1: >>> >> > 1 + @m 2 >>> >> > end >>> >> > endend >>> >> > >>> >> > Notice how the @m 2 is still there. Also, why is everything wrapped >>> >> > in >>> >> > an >>> >> > extra do block inside the module? Is this a printing issue, because >>> >> > that >>> >> > expression doesn't have one. >>> >> > >>> >> > How would I go about evaluating a module and it's macros, macro >>> >> > expanding >>> >> > the whole thing, and then dumping it out? @eval seems like, name >>> >> > wise, >>> >> > it >>> >> > should do this but it doesn't. >>> >> > Do you first eval() the module, then @eval the module? That didn't >>> >> > work >>> >> > for >>> >> > me either. >>> >> > >>> >> > Predefining a macro and then trying to evaluate: >>> >> > > macro m(x) 1 end >>> >> > > @eval(:(module M function f(x) @m 2 end end)) >>> >> > : >>> >> > :(module M >>> >> > >>> >> > eval(x) = begin # none, line 1: >>> >> > top(Core).eval(M,x) >>> >> > end >>> >> > eval(m,x) = begin # none, line 1: >>> >> > top(Core).eval(m,x) >>> >> > end # none, line 1: >>> >> > function f(x) # none, line 1: >>> >> > @m 2 >>> >> > end >>> >> > end) >>> >> > >>> >> > Also doesn't work. >>> >> > >>> >> > On Monday, March 21, 2016 at 7:54:59 AM UTC-7, Tim Holy wrote: >>> >> > > On Monday, March 21, 2016 09:34:19 AM Stefan Karpinski wrote: >>> >> > > > Tim, I'm assuming that module must assume that no macros are >>> >> > > > defined >>> >> > > >>> >> > > *and* >>> >> > > >>> >> > > > then used within the module body. If that does occur, the only >>> >> > > > way >>> >> > > > to do >>> >> > > > macro expansion correctly is to evaluate the module since the >>> >> > > > module >>> >> > > > definition can depend on arbitrary previously evaluated code. >>> >> > > >>> >> > > Probably true. I haven't played with it in a long time, but it's >>> >> > > possible >>> >> > > you >>> >> > > could load the module (so the macros are defined) and then parse >>> >> > > the >>> >> > > file...but >>> >> > > I can't remember if that works. >>> >> > > >>> >> > > Best, >>> >> > > --Tim >>> >> > > >>> >> > > > On Sun, Mar 20, 2016 at 9:00 PM, Tim Holy <[email protected] >>> >> > > >>> >> > > <javascript:>> wrote: >>> >> > > > > It probably needs updating, but >>> >> > > > > https://github.com/timholy/MacroExpandJL.jl >>> >> > > > > might help. It lets you macroexpand a whole source file. >>> >> > > > > >>> >> > > > > Best, >>> >> > > > > --Tim >>> >> > > > > >>> >> > > > > On Sunday, March 20, 2016 08:53:49 PM Yichao Yu wrote: >>> >> > > > > > On Sun, Mar 20, 2016 at 8:26 PM, <[email protected] >>> >> > > > > > <javascript:>> >>> >> > > >>> >> > > wrote: >>> >> > > > > > > Hi all, >>> >> > > > > > > >>> >> > > > > > > I'd like to be able to load in a module, then macroexpand >>> >> > > > > > > the >>> >> > > >>> >> > > whole >>> >> > > >>> >> > > > > thing, >>> >> > > > > >>> >> > > > > > > then print out the macroexpanded version. >>> >> > > > > > > >>> >> > > > > > > This should be a full, recursive macroexpand. >>> >> > > > > > > >>> >> > > > > > > I've noticed there is a function called macroexpand that >>> >> > > > > > > normally >>> >> > > >>> >> > > does >>> >> > > >>> >> > > > > > > what >>> >> > > > > > > >>> >> > > > > > > i want: >>> >> > > > > > >> macro m(x) 1 end >>> >> > > > > > > >>> >> > > > > > > .. >>> >> > > > > > > >>> >> > > > > > >> @m(2) >>> >> > > > > > > >>> >> > > > > > > 1 >>> >> > > > > > > >>> >> > > > > > >> macroexpand(:(1 + @m(2))) >>> >> > > > > > >> >>> >> > > > > > > :(1 + 1) >>> >> > > > > > > >>> >> > > > > > > so that is fine and dandy, but inside a module this doesn't >>> >> > > > > > > seem >>> >> > > >>> >> > > to >>> >> > > >>> >> > > > > work: >>> >> > > > > > >> macroexpand(:( >>> >> > > > > > >> >>> >> > > > > > > module M >>> >> > > > > > > macro m(x) 1 end >>> >> > > > > > > x = 1 + @m(2) >>> >> > > > > > > end >>> >> > > > > > > )) >>> >> > > > > > > : >>> >> > > > > > > :(module M >>> >> > > > > > > : >>> >> > > > > > > eval(x) = begin # none, line 2: >>> >> > > > > > > top(Core).eval(M,x) >>> >> > > > > > > >>> >> > > > > > > end >>> >> > > > > > > >>> >> > > > > > > eval(m,x) = begin # none, line 2: >>> >> > > > > > > top(Core).eval(m,x) >>> >> > > > > > > >>> >> > > > > > > end # none, line 3: >>> >> > > > > > > $(Expr(:macro, :(m(x)), quote # none, line 3: >>> >> > > > > > > 1 >>> >> > > > > > > >>> >> > > > > > > end)) # none, line 4: >>> >> > > > > > > x = 1 + @m(2) >>> >> > > > > > > end) >>> >> > > > > > > >>> >> > > > > > > As you can see in the second to last line, @m(2) is not >>> >> > > > > > > expanded, >>> >> > > >>> >> > > and >>> >> > > >>> >> > > > > I'm >>> >> > > > > >>> >> > > > > > > confused as to why that is. >>> >> > > > > > > >>> >> > > > > > > Ideally, this macroexpanding of a module would allow me to >>> >> > > > > > > also >>> >> > > > > > > resolve >>> >> > > > > > > imports and includes properly, so I could just slurp up a >>> >> > > > > > > file >>> >> > > > > > > and >>> >> > > > > > > dump >>> >> > > > > > > out >>> >> > > > > > > the macroexpanded version. >>> >> > > > > > >>> >> > > > > > TL;DR this is generally not possible without evaluating the >>> >> > > > > > whole >>> >> > > > > > module. >>> >> > > > > > >>> >> > > > > > Macros are executed at parse time and therefore resolved in >>> >> > > > > > global >>> >> > > > > > scope (since local scope doesn't even exist yet) or in >>> >> > > > > > another >>> >> > > > > > word >>> >> > > > > > module scope. >>> >> > > > > > Therefore when doing macro expansion in a new module, the >>> >> > > > > > macros >>> >> > > >>> >> > > needs >>> >> > > >>> >> > > > > > to be resolved in the new module and since there's no way to >>> >> > > > > > statically know what macros are available in a module you >>> >> > > > > > can't >>> >> > > > > > do >>> >> > > > > > that without evaluating the module. >>> >> > > > > > >>> >> > > > > > > Thank you! >>> >> > > > > > > >>> >> > > > > > > Vishesh >>> >> >>> >
