COMMUNITY

Assigning generated TAnonymous variables in macro context

macro

(Luke) #1

Hello all!

I am attempting to assign values to generated member variables for a generated TAnonymous struct in macro context, and I am having difficulty finding a solution.

Firstly, I should introduce what I am trying to do.

I have a series of documents I use to write my interactive story, and I am generating code based on what the story is. This means that all of my story assets are compiled into the game which makes loading stories far quicker and easier.

In one such document, I have the following scenario:

# Start

~ Cultism has sought to wreak havoc upon humanity.

These two lines in my current Haxe macro code generates this:

intro.block();

intro.overlay("Cultism has sought to wreak havoc upon humanity.");

Each “Block” is a part of a conversation, which means if I want to go to that part of the conversation I need to know at which point in the file this block begins.

So this code was born:

var blocks = getBlockNames(fullPath);
var blockStructs = TAnonymous([ for (b in blocks) { 
		name: b,
		pos: Context.currentPos(),
		meta: [ { 
			name: ":optional",
			pos: Context.currentPos()
		} ],
		kind: FVar(macro: Int)  
	}
]);

I realised I couldn’t assign a variable to TAnonymous, which makes sense since it’s a declaration and not a variable assignment in the haxe generated code at compile time.

So I tried the following to get the values (these values are indices which are determined by where each block exists in the conversation):

procedures.push (macro { $i{blockInstance}.$i{blockName} = $i{name}.block(); });

In the above context, blockInstance is the name of the anonymous structure generated earlier; blockName is the name of each block, which in the example given at the top is start; and name is the name of the instance of the conversation being created. The block call returns an integer which represents where the block is in the file, but I can’t seem to pull this off.

The above example code generates the following error:

d:\Business\IT\Internal\Games\Ancient Atlantis\Sources/macros/ConvoBuilder.hx:149: characters 50-59 : Missing ;
d:\Business\IT\Internal\Games\Ancient Atlantis\Sources/macros/ConvoBuilder.hx:149: characters 61-62 : Unexpected =

How would you assign variables in this context? I realise Haxe can’t really access member variables like what I have done above, but is there a solution that would allow me to assign variables that are not known until macro time?


(Valentin Lemière) #2

Not sure if this is exactly what you’re looking for:

import haxe.macro.Context;
import haxe.macro.Expr;

class Main {
	public static function main() {
		var data = getData();
		trace(data.b1);
		trace(data.b2);
		trace(data.b3);
	}

	static macro function getData() {
		var blocks = ["b1" => 0, "b2" => 7, "b3" => 12];

		var fields = [];
		for (b in blocks.keys()) {
			var e = {
				expr: EConst(CInt(Std.string(blocks[b]))),
				pos: Context.currentPos()
			};

			fields.push({
				field: b,
				expr: e
			});
		}

		return { expr: EObjectDecl(fields), pos: Context.currentPos() };
	}
}

You don’t need to construct the type, it can be inferred just like if you wrote var a = { i: 7 };.


(Luke) #3

Adapting your answer into my code has allowed me to assign the values.

Thank you for that.

I’m really starting to like using Haxe Macros.