cleaning up
This commit is contained in:
parent
ac5787e2fb
commit
9720731afb
@ -1,25 +1,27 @@
|
|||||||
package engine.macros;
|
package engine.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
import haxe.macro.Expr;
|
import haxe.macro.Expr;
|
||||||
import haxe.macro.Context;
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Type;
|
||||||
import haxe.macro.Expr.Field;
|
import haxe.macro.Expr.Field;
|
||||||
|
import haxe.macro.Expr.Function;
|
||||||
|
import haxe.macro.Expr.Access;
|
||||||
|
|
||||||
private typedef CVarMetadata = {
|
private typedef CVarMetadata = {
|
||||||
name: Expr,
|
name:Expr,
|
||||||
type: String,
|
type:String,
|
||||||
value: Expr,
|
value:Expr,
|
||||||
flags: Expr,
|
flags:Expr,
|
||||||
help: Expr,
|
help:Expr,
|
||||||
?callback: Expr
|
?callback:Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConVarDecorators {
|
class ConVarDecorators {
|
||||||
static function extractCVarMetadata(params:Array<Expr>):CVarMetadata {
|
static function extractCVarMetadata(params:Array<Expr>):CVarMetadata {
|
||||||
var metadata:CVarMetadata = null;
|
if (params == null || params.length == 0) return null;
|
||||||
|
|
||||||
switch (params[0].expr) {
|
var metadata:CVarMetadata = {
|
||||||
case EObjectDecl(fields):
|
|
||||||
metadata = {
|
|
||||||
name: macro "",
|
name: macro "",
|
||||||
type: "CString",
|
type: "CString",
|
||||||
value: macro 0,
|
value: macro 0,
|
||||||
@ -28,18 +30,25 @@ class ConVarDecorators {
|
|||||||
callback: macro null
|
callback: macro null
|
||||||
};
|
};
|
||||||
|
|
||||||
for (field in fields) {
|
switch (params[0].expr) {
|
||||||
switch (field.field) {
|
case EObjectDecl(fields):
|
||||||
case "name": metadata.name = field.expr;
|
var fieldMap = [
|
||||||
case "type": metadata.type = switch(field.expr.expr) {
|
"name" => function(expr) metadata.name = expr,
|
||||||
|
"type" => function(expr) metadata.type = switch (expr.expr) {
|
||||||
case EConst(CString(s)): s;
|
case EConst(CString(s)): s;
|
||||||
case _: "CString";
|
case _: "CString";
|
||||||
}
|
},
|
||||||
case "value": metadata.value = field.expr;
|
"value" => function(expr) metadata.value = expr,
|
||||||
case "flags": metadata.flags = field.expr;
|
"flags" => function(expr) metadata.flags = expr,
|
||||||
case "help": metadata.help = field.expr;
|
"help" => function(expr) metadata.help = expr,
|
||||||
case "callback": metadata.callback = field.expr;
|
"callback" => function(expr) metadata.callback = expr
|
||||||
case _:
|
];
|
||||||
|
|
||||||
|
for (field in fields) {
|
||||||
|
if (fieldMap.exists(field.field)) {
|
||||||
|
fieldMap[field.field](field.expr);
|
||||||
|
} else {
|
||||||
|
Context.error("Unexpected field: " + field.field, field.expr.pos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case _:
|
case _:
|
||||||
@ -47,64 +56,57 @@ class ConVarDecorators {
|
|||||||
return metadata;
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static macro function build():Array<Field> {
|
// Process command fields
|
||||||
var fields = Context.getBuildFields();
|
private static function processCommandField(field:Field, cmdMeta:MetadataEntry, extraFields:Array<Field>):Void {
|
||||||
var pos = Context.currentPos();
|
if (!isFieldKind(field, "FFun")) {
|
||||||
|
Context.error("The @:concmd metadata can only be applied to functions", field.pos);
|
||||||
for (field in fields) {
|
return;
|
||||||
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 pos = Context.currentPos();
|
||||||
var cvarName = switch(meta.name.expr) {
|
var functionReference = getFunctionFromField(field);
|
||||||
case EConst(CString(s)): s;
|
if (functionReference == null) return;
|
||||||
case _: field.name;
|
|
||||||
};
|
var name = cmdMeta.params.length > 0 ? getStringFromExpr(cmdMeta.params[0]) ?? field.name : field.name;
|
||||||
|
var functionExpression = macro function(args:Array<String>) ${functionReference.expr};
|
||||||
|
|
||||||
var initExpr = macro {
|
var initExpr = macro {
|
||||||
var cvar = $i{field.name} = engine.ConVar.registerCVar(
|
var cmd = engine.ConVar.registerCCmd($v{name}, $functionExpression);
|
||||||
|
cmd;
|
||||||
|
};
|
||||||
|
|
||||||
|
var initName = "__init__cmd_" + name;
|
||||||
|
extraFields.push(createStaticInitField(initName, initExpr, pos));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process convar fields
|
||||||
|
private static function processConVarField(field:Field, cvarMeta:MetadataEntry, extraFields:Array<Field>):Void {
|
||||||
|
if (!isFieldKind(field, "FVar")) {
|
||||||
|
Context.error("The @:convar metadata can only be applied to variables", field.pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var pos = Context.currentPos();
|
||||||
|
var meta = extractCVarMetadata(cvarMeta.params);
|
||||||
|
if (meta == null) {
|
||||||
|
Context.error("Metadata extraction failed for field: " + field.name, field.pos);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var cvarName = getStringFromMetaExpr(meta.name) ?? field.name;
|
||||||
|
var fieldName = field.name;
|
||||||
|
var isStatic = hasAccess(field, AStatic);
|
||||||
|
|
||||||
|
var varType = getVarType(field);
|
||||||
|
|
||||||
|
if (isStatic) {
|
||||||
|
// Handle static fields
|
||||||
|
var staticInitExpr = macro {
|
||||||
|
var cvar = $i{fieldName} = engine.ConVar.registerCVar(
|
||||||
${meta.name},
|
${meta.name},
|
||||||
${Context.parse('engine.enums.console.CVarType.' + meta.type, pos)},
|
${Context.parse('engine.enums.console.CVarType.' + meta.type, pos)},
|
||||||
${meta.value},
|
${meta.value},
|
||||||
${Context.parse('engine.enums.console.CVarFlag.' + switch(meta.flags.expr) {
|
${Context.parse('engine.enums.console.CVarFlag.' + switch (meta.flags.expr) {
|
||||||
case EConst(CString(s)): s;
|
case EConst(CString(s)): s;
|
||||||
case _: "FCVAR_NONE";
|
case _: "FCVAR_NONE";
|
||||||
}, pos)},
|
}, pos)},
|
||||||
@ -112,25 +114,153 @@ class ConVarDecorators {
|
|||||||
${meta.callback ?? macro null}
|
${meta.callback ?? macro null}
|
||||||
);
|
);
|
||||||
trace($v{"Registered CVar: "} + $e{meta.name});
|
trace($v{"Registered CVar: "} + $e{meta.name});
|
||||||
cvar; // Return the CVar reference
|
cvar;
|
||||||
};
|
};
|
||||||
|
|
||||||
fields.push({
|
extraFields.push(createStaticInitField("__init__" + cvarName, staticInitExpr, pos));
|
||||||
name: "__init__" + cvarName,
|
} else {
|
||||||
|
// Handle instance fields
|
||||||
|
updateFieldInitialValue(field, macro null);
|
||||||
|
|
||||||
|
var instanceInitExpr = macro {
|
||||||
|
if (Reflect.field(this, $v{fieldName}) == null) {
|
||||||
|
Reflect.setField(this, $v{fieldName}, 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});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ensureConstructorWithInit(extraFields, instanceInitExpr, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Utility functions
|
||||||
|
private static function isFieldKind(field:Field, kind:String):Bool {
|
||||||
|
return switch (field.kind) {
|
||||||
|
case FFun(_) if (kind == "FFun"): true;
|
||||||
|
case FVar(_, _) if (kind == "FVar"): true;
|
||||||
|
case FProp(_, _, _, _) if (kind == "FProp"): true;
|
||||||
|
case _: false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getFunctionFromField(field:Field):Function {
|
||||||
|
return switch (field.kind) {
|
||||||
|
case FFun(f): f;
|
||||||
|
case _: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getVarType(field:Field):ComplexType {
|
||||||
|
return switch (field.kind) {
|
||||||
|
case FVar(t, _): t;
|
||||||
|
case _: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function updateFieldInitialValue(field:Field, expr:Expr):Void {
|
||||||
|
switch (field.kind) {
|
||||||
|
case FVar(t, _): field.kind = FVar(t, expr);
|
||||||
|
case _:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getStringFromExpr(expr:Expr):String {
|
||||||
|
return switch (expr.expr) {
|
||||||
|
case EConst(CString(s)): s;
|
||||||
|
case _: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function getStringFromMetaExpr(expr:Expr):String {
|
||||||
|
return switch (expr.expr) {
|
||||||
|
case EConst(CString(s)): s;
|
||||||
|
case _: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function hasAccess(field:Field, access:Access):Bool {
|
||||||
|
return field.access != null && field.access.indexOf(access) >= 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function createStaticInitField(name:String, initExpr:Expr, pos:Position):Field {
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
access: [AStatic],
|
access: [AStatic],
|
||||||
kind: FVar(null, initExpr),
|
kind: FVar(null, initExpr),
|
||||||
pos: pos,
|
pos: pos,
|
||||||
doc: null,
|
doc: null,
|
||||||
meta: [{
|
meta: [{ name: ":keep", params: [], pos: pos }]
|
||||||
name: ":keep",
|
};
|
||||||
params: [],
|
}
|
||||||
pos: pos
|
|
||||||
}]
|
private static function ensureConstructorWithInit(fields:Array<Field>, initExpr:Expr, pos:Position):Void {
|
||||||
});
|
var cls = Context.getLocalClass().get();
|
||||||
|
var hasSuperClass = cls.superClass != null;
|
||||||
|
|
||||||
|
var constructor = Lambda.find(fields, function(f) return f.name == "new");
|
||||||
|
if (constructor == null) {
|
||||||
|
constructor = {
|
||||||
|
name: "new",
|
||||||
|
access: [APublic],
|
||||||
|
kind: FFun({
|
||||||
|
args: [],
|
||||||
|
expr: if (hasSuperClass) macro {
|
||||||
|
super();
|
||||||
|
$initExpr;
|
||||||
|
} else macro {
|
||||||
|
$initExpr;
|
||||||
|
},
|
||||||
|
ret: null
|
||||||
|
}),
|
||||||
|
pos: pos,
|
||||||
|
meta: []
|
||||||
|
};
|
||||||
|
fields.push(constructor);
|
||||||
|
} else {
|
||||||
|
switch (constructor.kind) {
|
||||||
|
case FFun(f):
|
||||||
|
switch(f.expr.expr) {
|
||||||
|
case EBlock(exprs):
|
||||||
|
exprs.push(initExpr);
|
||||||
|
case _:
|
||||||
|
f.expr = macro {
|
||||||
|
${f.expr};
|
||||||
|
$initExpr;
|
||||||
|
}
|
||||||
|
}
|
||||||
case _:
|
case _:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return fields;
|
|
||||||
|
public static macro function build():Array<Field> {
|
||||||
|
var fields = Context.getBuildFields();
|
||||||
|
var extraFields:Array<Field> = [];
|
||||||
|
|
||||||
|
for (field in fields) {
|
||||||
|
if (field.meta == null) continue;
|
||||||
|
|
||||||
|
var cmdMeta = Lambda.find(field.meta, function(m) return m.name == ":concmd");
|
||||||
|
var cvarMeta = Lambda.find(field.meta, function(m) return m.name == ":convar");
|
||||||
|
|
||||||
|
if (cmdMeta != null) {
|
||||||
|
processCommandField(field, cmdMeta, extraFields);
|
||||||
|
} else if (cvarMeta != null && cvarMeta.params.length > 0) {
|
||||||
|
processConVarField(field, cvarMeta, extraFields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields.concat(extraFields);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
@ -26,6 +26,7 @@ class Console extends Sprite {
|
|||||||
public var cAutoComp:TextField;
|
public var cAutoComp:TextField;
|
||||||
|
|
||||||
public static var consoleInstance:Console;
|
public static var consoleInstance:Console;
|
||||||
|
|
||||||
@:convar({
|
@:convar({
|
||||||
name: "mat_consolebg",
|
name: "mat_consolebg",
|
||||||
type: "CString",
|
type: "CString",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user