Snippets

YellowAfterlife eoryG: Untitled snippet

Created by VadimD last modified
package;
import haxe.macro.Context;
import haxe.macro.Expr;

@:build(ArrayObject.build(GameCtxImpl)) @:doc @:nativeGen enum GameCtx { }
@:build(ArrayObject.build(GameCtx)) abstract GameCtxImpl(Array<Dynamic>) {
	static var sizeof:Int;
	public inline function new() {
		this = SfTools.raw("ds_list_create")();
	}
	private inline function get(i:GameCtx) return this[i.getIndex()];
	private inline function set(i:GameCtx, v) this[i.getIndex()] = v;
	//
	public var bock:Int;
}
@:noCompletion
class ArrayObject {
	public static function build(type:Expr):Array<Field> {
		if (type.expr.match(EConst(CIdent("null")))) type = null;
		switch (Context.getLocalType()) {
			case TEnum(_, _): return buildEnum(type);
			case TAbstract(_, _): return buildAbstract(type);
			default: {
				Context.error("ArrayObject must be applied to abstract or enum.", Context.currentPos());
				return null;
			}
		}
	}
	private static function buildEnum(tx:Expr):Array<Field> {
		var fields = Context.getBuildFields();
		var pos = Context.currentPos();
		switch (tx.expr) {
			case EConst(CIdent(s)): switch (Context.getType(s)) {
				case TAbstract(_.get() => t, _): {
					for (f in t.impl.get().statics.get())
					if (f.name != "sizeof") switch (f.kind) {
						case FVar(AccNormal, AccNormal), FVar(AccCall, AccCall): {
							fields.push({
								name: f.name,
								kind: FVar(null, null),
								pos: pos
							});
						};
						default:
					}
				};
				default:
			};
			default:
		}
		return fields;
	}
	private static function buildAbstract(indexType:Expr):Array<Field> {
		var fields:Array<Field> = Context.getBuildFields();
		//
		var nextIndex:Int = 0;
		var sizeField:Field = null;
		var fieldIt = -1;
		while (++fieldIt < fields.length) {
			var field:Field = fields[fieldIt];
			var fname = field.name;
			if (fname == "sizeof") {
				sizeField = field;
				continue;
			}
			var fpos = field.pos;
			switch (field.kind) {
				case FVar(t, null): {
					field.kind = FProp("get", "set", t);
					for (it in 0 ... 2) {
						var set = it > 0, ix:Expr, nimpl:Expr;
						if (indexType != null) {
							ix = { expr: EField(indexType, fname), pos: fpos };
						} else ix = { expr: EConst(CInt(Std.string(nextIndex))), pos: fpos };
						if (set) {
							nimpl = macro { set($ix, v); return v; };
						} else nimpl = macro return get($ix);
						var nfunc:Function = {
							args: set ? [{ name: "v", type: t }] : [],
							ret: t, expr: nimpl
						};
						var nfield:Field = {
							name: (set ? "set_" : "get_") + fname,
							access: [APrivate, AInline],
							kind: FFun(nfunc),
							pos: fpos,
						};
						fields.insert(fieldIt + it + 1, nfield);
					} // for (it)
					nextIndex += 1;
				}; // case FVar
				default:
			} // switch (field.kind)
		} // for (field in fields)
		//
		if (sizeField != null) switch (sizeField.kind) {
			case FVar(t, _): {
				sizeField.kind = FVar(t, {
					expr: EConst(CInt(Std.string(nextIndex))),
					pos: sizeField.pos,
				});
				if (sizeField.access.indexOf(AInline) < 0) sizeField.access.push(AInline);
			};
			default:
		}
		//
		return fields;
	}
}
class Game {
	static inline function main() {
		new GameCtxImpl();
	}
}

@:build(ArrayObject.build(GameCtxImpl)) @:doc @:nativeGen enum GameCtx { }
@:build(ArrayObject.build(GameCtx)) abstract GameCtxImpl(Array<Dynamic>) {
	static var sizeof:Int;
	public inline function new() {
		this = [];
	}
	private inline function get(i:GameCtx) return this[i.getIndex()];
	private inline function set(i:GameCtx, v) this[i.getIndex()] = v;
	//
	public var bock:Int;
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.