Help with macros

42 views
Skip to first unread message

Franco Salinas

unread,
Oct 27, 2013, 10:34:30 AM10/27/13
to haxe...@googlegroups.com
Hello everyone, I'm new around here and I need some help about macros. I want to do the following:

Given an Array<Array<Int>> where each Int is a static inline variable which takes values between 0-31, for example:

class Class1 {
   
public static inline var A = 0;
   
public static inline var B = 1;
   
public static inline var C = 2;
   
...
}

...

var arr:Array<Array<Int>> = [ [ Class1.A, Class1.B,  Class1.E ], [  Class1.A,  Class1.C,  Class1.D ], ... ];

I want to generate an Array<Int> encoding the prior array like following:

new_array[ i ] = ( 1 << arr[ i ][ 0 ] ) | ( 1 << arr[ i ][ 1 ] ) | ...;

This means:

new_array[ 0 ] = 1|2|16; // = (1<<Class1.A)|(1|Class1.B)|(1<<Class1.E) = (1<<0)|(1<<1)|(1<<5)
new_array
[ 1 ] = 1|4|8; // = (1<<Class1.A)|(1|Class1.C)|(1<<Class1.D) = (1<<0)|(1<<2)|(1<<4)
...

The point is using it like this:
private static inline var _list:Array<Int> = Macros.encodeList( [
   
[ Class1.A, Class1.B, Class1.E ],
   
[ Class1.A, Class1.C, Class1.D ]
 
] );

So far I have this:
@:macro public static function encodeList( list:Array<Array<Expr>> ) : Expr {
 
 
var codes:Array<Int> = [];
 
var index:Int = 0;
 
 
for ( element in list ) {
 
     
for( type in element ) {
         
switch( type.expr ) {
             
case EField( e, field ):
                 
switch( field ) { // I'd like to do this without switch but this works anyway
                     
case "A":
                         codes
[ index ] |= 1 << 0;
                     
case "B":
                         codes
[ index ] |= 1 << 1;
                     
case "C":
                         codes
[ index ] |= 1 << 2;
                     
...
                     
case "LAST":
                         codes
[ index ] |= 1 << 31;
                     
default:
 
                 
}
             
default:
         
}
   
}
   
++index;
 
 
}

 
// Here I should build an expression using the array "codes"


 
}

Well, the point is I don't know how to build the expression. To be honest I don't fully understand the macro system. I don't know if I should return an expression or an Array<Field>. I saw the examples but I don't understand. I hope someone can help me. Thanks

Juraj Kirchheim

unread,
Oct 27, 2013, 10:46:52 AM10/27/13
to haxe...@googlegroups.com
Context.makeExpr will do that. However I believe there was a bug
before 3.0.1. where it didn't always work correctly.

You could also try { expr: EArrayDecl(codes.map(Context.makeExpr)),
pos: Context.currentPos() }.

Regards,
Juraj
> --
> To post to this group haxe...@googlegroups.com
> http://groups.google.com/group/haxelang?hl=en
> ---
> You received this message because you are subscribed to the Google Groups
> "Haxe" group.
> For more options, visit https://groups.google.com/groups/opt_out.

Franco Salinas

unread,
Oct 27, 2013, 12:15:41 PM10/27/13
to haxe...@googlegroups.com
Thanks for your answer. I am working with haxe 2.10 and I tried this (because codes.map() didn't worked):

 @:macro public static function encodeList( list:Array<Array<Expr>> ) : Expr {
   
var codes:Array<Int> = [];


   
...

   
var exprs:Array<Expr> = [];
   
for ( c in codes )
        exprs
.push( Context.makeExpr( c, Context.currentPos() ) );

 
   
return { expr: EArrayDecl( exprs ), pos:Context.currentPos() };
}

But I get "haxe.macro.Expr should be Array<Array<haxe.macro.Expr>>" at line 18 which contains:

private static inline var _list:Array<Int> = Macros.encodeList( [ [ Class1.A, Class1.B, Class1.C ] ] );

Any ideas?
Reply all
Reply to author
Forward
0 new messages