import haxe.macro.Context; import haxe.macro.Expr; import haxe.macro.Type; using haxe.macro.Tools; class EitherMacro { static var arityMap = new Map<Int,Bool>(); static function build():ComplexType { return switch (Context.getLocalType()) { case TInst(_.get() => {pack: [], name: "Either"}, params): return buildEitherType(params); default: throw false; } } static function buildEitherType(types:Array<Type>):ComplexType { var pos = Context.currentPos(); var arity = types.length; if (arity < 2) Context.fatalError("Either should only be used with 2 or more type parameters", pos); var name = 'Either_$arity'; if (!arityMap.exists(arity)) { var fromToTypes:Array<ComplexType> = []; var params:Array<TypeParamDecl> = []; for (i in 0...arity) { var name = 'T$i'; fromToTypes.push(TPath({pack: [], name: name})); params.push({name: name}); } Context.defineType({ name: name, pos: pos, pack: [], params: params, kind: TDAbstract(macro : Dynamic, fromToTypes, fromToTypes), fields: [] }); arityMap[arity] = true; } return TPath({pack: [], name: name, params: [for (t in types) TPType(t.toComplexType())]}); } }