forked from HaxeFoundation/haxe
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
128 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package unit.issues; | ||
|
||
@:genericBuild(unit.issues.misc.Issue3183Macro.buildTuple()) | ||
class MyTuple<Rest> { } | ||
|
||
class Issue3183 extends Test { | ||
function test() { | ||
var t = new MyTuple<String, Int>("foo", 12); | ||
unit.TestType.typedAs(t, (null : MyTuple<String, Int>)); | ||
eq("foo", t.v0); | ||
eq(12, t.v1); | ||
|
||
var t = new MyTuple("foo", 12); | ||
unit.TestType.typedAs(t, (null : MyTuple<String, Int>)); | ||
eq("foo", t.v0); | ||
eq(12, t.v1); | ||
|
||
var t:MyTuple = new MyTuple("foo", 12); | ||
unit.TestType.typedAs(t, (null : MyTuple<String, Int>)); | ||
eq("foo", t.v0); | ||
eq(12, t.v1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
package unit.issues.misc; | ||
|
||
import haxe.macro.Expr; | ||
import haxe.macro.Context; | ||
import haxe.macro.Type; | ||
|
||
using haxe.macro.Tools; | ||
|
||
class Issue3183Macro { | ||
static var tupleMap = new Map(); | ||
|
||
macro static public function buildTuple():ComplexType { | ||
switch(Context.getLocalType()) { | ||
case TInst(c, args): | ||
var arity = args.length; | ||
if (arity == 0) { | ||
var el = Context.getConstructorArguments(); | ||
if (el != null && el.length > 0) { | ||
args = [for (e in el) Context.typeof(e)]; | ||
arity = args.length; | ||
} else { | ||
return null; | ||
} | ||
} | ||
if (!tupleMap.exists(arity)) { | ||
tupleMap[arity] = buildTupleType(c.get(), Context.getBuildFields(), arity); | ||
} | ||
var ct = tupleMap[arity]; | ||
ct.params = [for (t in args) { | ||
switch (t) { | ||
case TInst(_.get().kind => KExpr(e), _): | ||
TPType(Context.typeof(e).toComplexType()); | ||
case _: | ||
TPType(t.toComplexType()); | ||
} | ||
}]; | ||
return TPath(ct); | ||
case _: | ||
return Context.error("Class expected", Context.currentPos()); | ||
} | ||
} | ||
|
||
static function buildTupleType(c:ClassType, fields:Array<Field>, arity:Int) { | ||
var typeParams = []; | ||
var tupleFields = []; | ||
for (i in 0...arity) { | ||
var fieldName = 'v$i'; | ||
var typeParamName = 'T$i'; | ||
var typeParam = { | ||
TPath({ | ||
pack: [], | ||
name: typeParamName, | ||
sub: null, | ||
params: [] | ||
}); | ||
} | ||
typeParams.push({ | ||
name: typeParamName, | ||
constraints: [], | ||
params: [] | ||
}); | ||
var field = (macro class X { | ||
public var $fieldName:$typeParam; | ||
}).fields[0]; | ||
tupleFields.push(field); | ||
} | ||
var constructor = { | ||
name: "new", | ||
pos: c.pos, | ||
access: [APublic, AInline], | ||
kind: FFun({ | ||
ret: null, | ||
expr: macro $b{tupleFields.map(function(field) { | ||
var name = field.name; | ||
return macro this.$name = $i{name}; | ||
})}, | ||
params: [], | ||
args: tupleFields.map(function(field) { | ||
return { | ||
name: field.name, | ||
type: null, | ||
opt: false, | ||
value: null | ||
} | ||
}) | ||
}) | ||
} | ||
var name = c.name + "_" + arity; | ||
var tDef = { | ||
pack: c.pack, | ||
name: name, | ||
pos: c.pos, | ||
kind: TDClass(), | ||
params: typeParams, | ||
fields: fields.concat(tupleFields).concat([constructor]) | ||
} | ||
Context.defineType(tDef); | ||
return { | ||
pack: c.pack, | ||
name: name, | ||
params: [], | ||
sub: null | ||
} | ||
} | ||
} |