Macro Question

61 views
Skip to first unread message

Keith McDonald

unread,
Aug 16, 2014, 5:55:35 PM8/16/14
to haxe...@googlegroups.com
I am new to macros and am currently trying to figure something out.

If I use a build macro am I able to deal with a Map? (something along the lines of)

var testMap = new Map<String, Int>();
testMap.set('test', 4);
var fields:Array<Field> = Context.getBuildFields();
fields.push({
                   name: "directory",
                    doc: "",
                    access: [Access.APublic, Access.AStatic, Access.AInline],
                    kind: FieldType.FVar(macro:Map, macro testMap),
                    pos: Context.currentPos()
                });

I am attempting to build a simple directory structure to my assets (because apparently flash does not allow filesystem calls per se).

Any help would be greatly appreciated.
Thanks


Simon Krajewski

unread,
Aug 16, 2014, 6:03:49 PM8/16/14
to haxe...@googlegroups.com
You can't just use `macro testMap` because all that does is reify the
identifier "testMap". Keep in mind that you're working with expressions,
so what you need is an expression that initializes your map.

For maps it makes sense to generate its initialization syntax: [ key1 =>
value1, key2 => value2]. Iterate over your testMap.keys() and build an
array with the key => value things, then use `macro $a{thatArray}`.

Simon

Keith McDonald

unread,
Aug 16, 2014, 6:37:44 PM8/16/14
to haxe...@googlegroups.com
Thanks for the quick response.

I understand most of what was said.

How does one generate an expression out of key => value

Pretend I have a really simple example. My map has "key1" => "value1" and "key2" => "value2". So I create an array. The first item in the array will be an expression representing "key1" => "value1". What is the syntax to create such an expression? A string like "key1 => value1" is just a literal which isn't an expression I am assuming. The syntax is a little bewildering at the start and I am just trying to get my head around it.

Also - can I make an expression out of something a little more complicated like "key1" => ["key3" => "value3", "key4" => "value4"]

Thanks again.

Simon Krajewski

unread,
Aug 16, 2014, 6:47:10 PM8/16/14
to haxe...@googlegroups.com
Am 17.08.2014 00:37, schrieb Keith McDonald:
> Thanks for the quick response.
>
> I understand most of what was said.
>
> How does one generate an expression out of key => value
>
> Pretend I have a really simple example. My map has "key1" => "value1"
> and "key2" => "value2". So I create an array. The first item in the
> array will be an expression representing "key1" => "value1". What is
> the syntax to create such an expression? A string like "key1 =>
> value1" is just a literal which isn't an expression I am assuming. The
> syntax is a little bewildering at the start and I am just trying to
> get my head around it.

Speaking in ExprDef it's EBinop(OpArrow, EConst(String("key1")),
EConst(String("value1"))), so => is a binary operator like + and -. It's
much simpler with reification because you can just use `macro $eKey =>
$eValue` where both eKey and eValue are Expr. If you only have strings
or other basic types, you can use `$v{yourString}` to get an expression
out of it. See http://haxe.org/manual/macro-reification-expression.html
for more information on reification.

> Also - can I make an expression out of something a little more
> complicated like "key1" => ["key3" => "value3", "key4" => "value4"]

Anything you can write in syntax you can generate from macros, so yes.

Simon

Keith McDonald

unread,
Aug 16, 2014, 8:23:29 PM8/16/14
to haxe...@googlegroups.com
Ok - last question (after having looked at the macro documentation again)..
I've decided I will start out a little simpler (and still be able to do what I would like).

Would you be able to provide a simple example (with syntax) for building an array of strings

Lets say I have 2 string variables: text1 and text2 and would like to return an array where array[0] = value of text1 variable and array[1] = value of text2 variable

I believe $v{text1} creates an expression out of the string variable text1
I believe $v{text2} creates an expression out of the sting variable text2
Do I make an expression similar to

var expression = macro $a{[$v{text1},$v{text2}]};


        var fields:Array<Field> = Context.getBuildFields();
        fields.push({
                    name: "directory",
                    doc: "",
                    access: [Access.APublic, Access.AStatic, Access.AInline],
                    kind: FieldType.FVar(macro:Array<String>,expression ),
                    pos: Context.currentPos()
                });

I think this is close but it says "inline variable initialization must be a constant value". Am I constructing the array expression inappropriately?

Thanks

Keith McDonald

unread,
Aug 16, 2014, 9:36:13 PM8/16/14
to haxe...@googlegroups.com
I think I got it.

var expression = macro $a { ["1", "2"] };

     
var fields:Array<Field> = Context.getBuildFields();
        fields.push({
                    name: "directory",
                    doc: "",
                    access: [Access.APublic, Access.AStatic],

Simon Krajewski

unread,
Aug 17, 2014, 4:10:34 AM8/17/14
to haxe...@googlegroups.com
That's actually an entirely different error which the typer throws while
typing your macro result. Inline variables can only be initialized to
constant expressions because they inline their expression at
access-site. If we allowed arrays and other things there you would get a
new array instance each time to access your field in the code. This then
leads to weird behavior like `yourField == yourField` always being false
because it becomes `[] == []`.

Try losing the `Access.AInline`, the code looks good otherwise.

Simon

Keith McDonald

unread,
Aug 17, 2014, 4:17:27 AM8/17/14
to haxe...@googlegroups.com
I managed to get it working if I create an array like so

var expression = macro $a { ["1", "2"] };

However, I am having issues if I create an array via new then push some items onto it. Say I have

var test = new Array<String>();
test.push("aa");
test.push("bb");

How would I turn this array (test) into an expression? What syntax would I use?

Thanks

Simon Krajewski

unread,
Aug 17, 2014, 4:21:11 AM8/17/14
to haxe...@googlegroups.com
Disclaimer: Email coding

```
var exprs = [];
for (key in test.keys()) {
exprs.push(macro $v{key} => $v{test[key]});
}
var e = macro $a{exprs};
```

Alternatively using array comprehension:

```
var exprs = [for (key in test.keys()) macro $v{key} => $v{test[key]}];
var e = macro $a{exprs};
```

Simon

Luca

unread,
Aug 17, 2014, 1:11:44 PM8/17/14
to haxe...@googlegroups.com
Why stop there?

var e = macro $a{[for (key in test.keys()) macro $v{key} => $v{test[key]}]}; 
Reply all
Reply to author
Forward
0 new messages