Re: New haxe stagging (nemerle like) macro available on github

Posted by Heinz Hölzer-2 on
URL: http://haxe.1354130.n2.nabble.com/New-haxe-stagging-nemerle-like-macro-available-on-github-tp6954481p6966421.html

I'm not sure if there are limitations. The good thing about this approach is that you can write the complete macro class inside of your Builder class.
One Limitation is that you can only use full qualified types inside of your macro, because there is currently no way to get the current imports from the context,
that would be a nice feature. Something like Context.localImports() is needed. A slower alternative would be to extract all Types of an Expr, get the full qualified types with Context.typeof() and create the import statements based on them.  

By the way, I added some new features:

1) Added ExprRequire, so you can use your macros also with using.
2) You can return either a string from your macro or an Expr, more flexibility.
3) Recursive conversion and type check of constant arguments accepting also Expr and ExprRequire as Leafs.

This is really nice, take a look at this example:
 // macro definition
typedef MyMacros = haxe.macro.MacroType < (scuts.MacroBuilder.build(
function testMe (a:ExprRequire<Int>, b:{a: Int, b:ExprRequire<Void->Void>}) {
    trace(b.a); // traces an Int
    return "{}";
}
))>;
// usage
MyMacros.testMe(1, 1); -> Argument b should be of Type {a:Int,b:ExprRequire<Void->Void>,}
MyMacros.testMe(1, {a:2, b:5}); //  Int should be Void -> Void
MyMacros.testMe(1, {a:2, b:function () return 1}); //  Void -> Int should be Void -> Void

All errors point to the correct source code position.

best,
h

Am 04.11.2011 22:25, schrieb sledorze:
oh that's very nice, I have not tried it yet but my own recent trials make me think that this approach may be better.
Do you oversee some limitations?


2011/11/4 Heinz Hölzer-2 [via Haxe] <[hidden email]>
I added some improvements to my version. You can now use haxe code to build your expression string inside of the macro definition.

the following macro

function times2 ( i:Int, expr) {
    var e = "{";
    for (_ in 0...i) {
      e += "$expr;";
    }
    e += "}";
    return e;
  }

translates to this:

@:macro public static function times2(i:Int,expr:haxe.macro.Expr):haxe.macro.Expr {

    var e = try {
      scuts.macro.Parse.parse(
        (function ()
                    {
                        var e = "{";
                        for (_ in 0 ... i) {
                            e += "$expr;";
                        };
                        e += "}";
                        return e;
                    })(), {i:i,expr:expr,});
    } catch (error:Dynamic) {
      haxe.macro.Context.error(error.message, error.pos);
    }
    return e;
  }

You can also pass an array of expressions to your macro, the conversion is done automatically.
You can also add a special context variable to the parameters, which gets not translated to a macro parameter.
I'm not sure if this is already to much, it should be an easy interface to some useful functions:

function makeList ( values:Array<haxe.macro.Expr>, tp, ctx:scuts.MacroContext ) {
    var e = "{ var a:Array<$tp> = [];";
    for (v in values) {
      e += "a.push(" + ctx.exprToString(v) + ");";
    }
    e += "a; }";
   
    return e;
  }

translates to this

@:macro public static function makeList(__values:haxe.macro.Expr,tp:haxe.macro.Expr):haxe.macro.Expr {
        var ctx:scuts.MacroContext = scuts.MacroBuilder.MacroContextImp;
        var values = switch (__values.expr) { case EArrayDecl(v): v; default: throw 'assert';};

    var e = try {
      scuts.macro.Parse.parse(
        (function ()
                    {
                        var e = "{ var a:Array<$tp> = [];";
                        for (v in values) {
                            e += "a.push(" + ctx.exprToString(v) + ");";
                        };
                        e += "a; }";
                        return e;
                    })(), {values:values,tp:tp,});
    } catch (error:Dynamic) {
      haxe.macro.Context.error(error.message, error.pos);
    }
    return e;
  }

you can find the related classes here:

Example Usage: http://code.google.com/p/scuts/source/browse/src/samples/13_MacroBuilder/Main.hx
Source Tree: http://code.google.com/p/scuts/source/browse/src

best,
h

Am 02.11.2011 19:13, schrieb sledorze:
I like your approach not requiering to write real macros code..
the most like usual code they get, the more macros usage will spread.. :)

2011/11/2 Heinz Hölzer-2 [via Haxe] <[hidden email]>
I just changed binding to this:

typedef MyMacros = haxe.macro.MacroType<(scuts.MacroBuilder.build(
  function fori (init, until, change, body)
    "{ $init; while ($until) { $body; $change;} }",
  function times5 (expr)
    "{ $expr; $expr; $expr; $expr; $expr;}",
  function times (i, expr)
    "{ for (_ in 0...$i) $expr; }",
  function myFunction (paramType, ret)
    "function (p:$paramType):$paramType { return $ret + p;}",
  function arrayContains (arr, elem)
    "{ var found = false; for (a in $arr) { if (a == $elem) { found = true; break;} } found; }"
   
  function castedArray ($typeParam, elem)
    "{ var a:Array<$typeParam> = []; for (e in $arr)a:Array<$typeParam>, elem:$typeParam) a.push(elem)"
))>;



Am 02.11.2011 17:20, schrieb sledorze:
how do you bind the identifiers? by appearance order?

2011/11/2 Heinz Hölzer-2 [via Haxe] <[hidden email]>

Hi Stephane,

your post inspired me to add such functionality to scuts, i'm currently
working on changes and improvements, it's not perfect but currently it
works like this:

------------------------------------------------------------------------------------------------------------------------------
package ;

// no need to write real macro code directly, just add some expressions
to the "namespace" MyMacros:

typedef MyMacros = haxe.macro.MacroType<(scuts.meta.MacroBuilder.build(
   fori <= "{ $init; while ($until) { $body; $inc;} }",
   times5 <= "{ $expr; $expr; $expr; $expr; $expr;}",
   myFunction <= "function (p:$paramType):$paramType { return $ret + p;}",
   arrayContains <= "{ var found = false; for (a in $arr) { if (a ==
$elem) { found = true; break;} } found; }"
))>;



class Main
{
     static function main ()
     {

     // and use them

     MyMacros.times5(trace("hi"));
     var i = 0;
     MyMacros.fori(i = 0, i < 10,  trace(i), i++);
     trace(i);
     // Types can be passed directly


     trace(MyMacros.myFunction(String, "hello ")("Peter"));
     // or as String (useful for type parameters)
     trace(MyMacros.myFunction("String", "hello ")("Peter")); // hello Peter

     trace(MyMacros.arrayContains([1, 2, 3], 1));
     }

}

Main.hx:19: hi
Main.hx:19: hi
Main.hx:19: hi
Main.hx:19: hi
Main.hx:19: hi
Main.hx:21: 0
Main.hx:21: 1
Main.hx:21: 2
Main.hx:21: 3
Main.hx:21: 4
Main.hx:21: 5
Main.hx:21: 6
Main.hx:21: 7
Main.hx:21: 8
Main.hx:21: 9
Main.hx:22: 10
Main.hx:26: hello Peter
Main.hx:28: hello Peter
Main.hx:30: true

----------------------------------------------------------------------

My Parser class tries to replace types and expressions, both of them can
be provided as different types.

I will commit the changes later, but don't expect perfect code at this
point ;)

Am 02.11.2011 09:58, schrieb sledorze:

> I make this new post to introduce a new macro (introducing it in a question
> thread did not make sense) :
>
> whith it you can write that:
>
> import com.mindrocks.macros.Stagged;
> using com.mindrocks.macros.Stagged;
> import haxe.macro.Expr;
>
> class StaggedTestMacros {
>
>    @:macro public static function forExample(init : Expr, cond : Expr, inc :
> Expr, body : Expr) : Expr return
>      "{
>        %init;
>        function oneTime() {
>          if (%cond) {
>            %body;
>            %inc;
>            oneTime();
>          }
>        }
>        oneTime();
>      }".stagged()
>
> }
>
> %identifier being replace by the related expression passed as parameter.
> and use it like that into another file:
>
> import StaggedTestMacros;
>
> ...
> {
>      var i;
>      StaggedTestMacros.forExample(i = 0, i<  10, i++, trace(i));
>
>      trace("final i " + i);
> }
>
> You can mix it with the format macro and get something close to nemerle meta
> programming for functions.
>
> available from this still-missnamed repo:
> https://github.com/sledorze/haxeExtensionBuilder
>
> I'm open to improvments.
>
> Enjoy!
> Stephane
>
>
> --
> View this message in context: http://haxe.1354130.n2.nabble.com/New-haxe-stagging-nemerle-like-macro-available-on-github-tp6954481p6954481.html
> Sent from the Haxe mailing list archive at Nabble.com.
>


--
haXe - an open source web programming language
http://haxe.org



If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/New-haxe-stagging-nemerle-like-macro-available-on-github-tp6954481p6955671.html
To unsubscribe from New haxe stagging (nemerle like) macro available on github, click here.



--
Stéphane Le Dorze
Tel: <a href="tel:%2B33%20%280%29%206%2008%20%C2%A076%2070%2015" value="<a href="tel:%2B33608767015" value="+33608767015" target="_blank">+33608767015" target="_blank">+33 (0) 6 08  76 70 15




View this message in context: Re: New haxe stagging (nemerle like) macro available on github

Sent from the Haxe mailing list archive at Nabble.com.




--
haXe - an open source web programming language
http://haxe.org


If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/New-haxe-stagging-nemerle-like-macro-available-on-github-tp6954481p6956314.html
To unsubscribe from New haxe stagging (nemerle like) macro available on github, click here.



--
Stéphane Le Dorze
Tel: <a href="tel:%2B33%20%280%29%206%2008%20%C2%A076%2070%2015" value="<a href="tel:%2B33608767015" value="+33608767015" target="_blank">+33608767015" target="_blank">+33 (0) 6 08  76 70 15




View this message in context: Re: New haxe stagging (nemerle like) macro available on github
Sent from the Haxe mailing list archive at Nabble.com.




--
haXe - an open source web programming language
http://haxe.org


If you reply to this email, your message will be added to the discussion below:
http://haxe.1354130.n2.nabble.com/New-haxe-stagging-nemerle-like-macro-available-on-github-tp6954481p6963376.html
To unsubscribe from New haxe stagging (nemerle like) macro available on github, click here.



--
Stéphane Le Dorze

http://lambdabrella.blogspot.com/
http://www.linkedin.com/in/stephaneledorze
http://twitter.com/stephaneledorze

Tel: +33 (0) 6 08  76 70 15




View this message in context: Re: New haxe stagging (nemerle like) macro available on github
Sent from the Haxe mailing list archive at Nabble.com.




--
haXe - an open source web programming language
http://haxe.org