massively updated decorator code to support convar and implement

This commit is contained in:
2025-03-11 12:37:43 +01:00
parent 99dc07cd64
commit 2383b5f026
8 changed files with 159 additions and 52 deletions
@@ -0,0 +1,136 @@
package engine.macros;
import haxe.macro.Expr;
import haxe.macro.Context;
import haxe.macro.Expr.Field;
private typedef CVarMetadata = {
name: Expr,
type: String,
value: Expr,
flags: Expr,
help: Expr,
?callback: Expr
}
class ConVarDecorators {
static function extractCVarMetadata(params:Array<Expr>):CVarMetadata {
var metadata:CVarMetadata = null;
switch (params[0].expr) {
case EObjectDecl(fields):
metadata = {
name: macro "",
type: "CString",
value: macro 0,
flags: macro "FCVAR_NONE",
help: macro "",
callback: macro null
};
for (field in fields) {
switch (field.field) {
case "name": metadata.name = field.expr;
case "type": metadata.type = switch(field.expr.expr) {
case EConst(CString(s)): s;
case _: "CString";
}
case "value": metadata.value = field.expr;
case "flags": metadata.flags = field.expr;
case "help": metadata.help = field.expr;
case "callback": metadata.callback = field.expr;
case _:
}
}
case _:
}
return metadata;
}
public static macro function build():Array<Field> {
var fields = Context.getBuildFields();
var pos = Context.currentPos();
for (field in fields) {
var cmdMeta = field.meta != null ? Lambda.find(field.meta, function(m) return m.name == ":concmd") : null;
var cvarMeta = field.meta != null ? Lambda.find(field.meta, function(m) return m.name == ":convar") : null;
if (cmdMeta != null) {
switch field.kind {
case FFun(f):
var name = cmdMeta.params.length > 0 ? switch (cmdMeta.params[0].expr) {
case EConst(CString(s)): s;
case _: field.name;
} : field.name;
var fnExpr = macro function(args:Array<String>) ${f.expr};
var initExpr = macro {
var cmd = engine.ConVar.registerCCmd($v{name}, $fnExpr);
cmd; // Return the command reference
};
// Generate a safe initialization field name
var initName = "__init__" + name;
fields.push({
name: initName,
access: [AStatic],
kind: FVar(null, initExpr),
pos: pos,
doc: null,
meta: [{
name: ":keep",
params: [],
pos: pos
}]
});
case _:
}
} else if (cvarMeta != null && cvarMeta.params.length > 0) {
switch (field.kind) {
case FVar(t, e):
var meta = extractCVarMetadata(cvarMeta.params);
if (meta == null) continue;
// Extract name from metadata expression
var cvarName = switch(meta.name.expr) {
case EConst(CString(s)): s;
case _: field.name;
};
var initExpr = macro {
var cvar = $i{field.name} = engine.ConVar.registerCVar(
${meta.name},
${Context.parse('engine.enums.console.CVarType.' + meta.type, pos)},
${meta.value},
${Context.parse('engine.enums.console.CVarFlag.' + switch(meta.flags.expr) {
case EConst(CString(s)): s;
case _: "FCVAR_NONE";
}, pos)},
${meta.help},
${meta.callback ?? macro null}
);
trace($v{"Registered CVar: "} + $e{meta.name});
cvar; // Return the CVar reference
};
fields.push({
name: "__init__" + cvarName,
access: [AStatic],
kind: FVar(null, initExpr),
pos: pos,
doc: null,
meta: [{
name: ":keep",
params: [],
pos: pos
}]
});
case _:
}
}
}
return fields;
}
}