Compare commits

...

2 Commits

Author SHA1 Message Date
Juraj Kirchheim
bc9f7460c2 Better, I guess. 2021-03-14 14:25:36 +01:00
Juraj Kirchheim
043df0f47d Try a more deterministic approach to build cache. 2021-03-14 14:11:35 +01:00
3 changed files with 81 additions and 121 deletions

View File

@@ -17,18 +17,18 @@ typedef BuildContextN = {
typedef BuildContext = { typedef BuildContext = {
pos:Position, var pos(default, never):Position;
type:Type, var type(default, never):Type;
usings:Array<TypePath>, var usings(default, never):Array<TypePath>;
name:String, var name(default, never):String;
} }
typedef BuildContext2 = {>BuildContext, typedef BuildContext2 = {>BuildContext,
type2:Type, var type2(default, never):Type;
} }
typedef BuildContext3 = {>BuildContext2, typedef BuildContext3 = {>BuildContext2,
type3:Type, var type3(default, never):Type;
} }
class BuildCache { class BuildCache {
@@ -36,29 +36,20 @@ class BuildCache {
@:persistent static var cache = new Map(); @:persistent static var cache = new Map();
static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition, ?normalizer:Type->Type) { static public function getType3(name, ?types, ?pos:Position, build:BuildContext3->TypeDefinition, ?normalizer:Type->Type) {
if (types == null) return _getTypeN(name, 3, switch types {
switch Context.getLocalType() { case null: null;
case TInst(_.toString() == name => true, [t1, t2, t3]): case v: [types.t1, types.t2, types.t3];
types = { t1: t1, t2: t2, t3: t3 }; }, pos, ctx -> build({
default:
throw 'assert';
}
var t1 = types.t1.toComplexType(),
t2 = types.t2.toComplexType(),
t3 = types.t2.toComplexType();
return getType(name, (macro : { t1: $t1, t2: $t2, t3: $t3 } ).toType(), pos, function (ctx) return build({
type: types.t1,
type2: types.t2,
type3: types.t3,
pos: ctx.pos, pos: ctx.pos,
name: ctx.name, type: ctx.types[0],
usings: ctx.usings type2: ctx.types[1],
type3: ctx.types[2],
usings: ctx.usings,
name: ctx.name
}), normalizer); }), normalizer);
} }
static public function getTypeN(name, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) { static function _getTypeN(name, length, ?types, ?pos:Position, build:BuildContextN->TypeDefinition, ?normalizer:Type->Type) {
if (pos == null) if (pos == null)
pos = Context.currentPos(); pos = Context.currentPos();
@@ -67,50 +58,37 @@ class BuildCache {
switch Context.getLocalType() { switch Context.getLocalType() {
case TInst(_.toString() == name => true, params): case TInst(_.toString() == name => true, params):
types = params; types = params;
default: case t:
throw 'assert'; pos.error('expected $name but found ${t.toString()}');
} }
var compound = ComplexType.TAnonymous([for (i in 0...types.length) { if (length != -1 && types.length != length)
name: 't$i', pos.error('expected $length parameter${if (length == 1) '' else 's'}');
pos: pos,
kind: FVar(switch types[i] {
case TInst(_.get().kind => KExpr(e), _):
TPath('tink.macro.ConstParam'.asTypePath([TPExpr(e)]));
case t: t.toComplex();
}),
}]).toType();
return getType(name, compound, pos, function (ctx) return build({ var forName =
types: types, switch cache[name] {
pos: ctx.pos, case null: cache[name] = new Group(name);
name: ctx.name, case v: v;
usings: ctx.usings
}), normalizer);
}
static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition, ?normalizer:Type->Type) {
if (types == null)
switch Context.getLocalType() {
case TInst(_.toString() == name => true, [t1, t2]):
types = { t1: t1, t2: t2 };
default:
throw 'assert';
} }
var t1 = types.t1.toComplexType(), var ret = forName.get(types, pos.sanitize(), build, normalizer);
t2 = types.t2.toComplexType(); ret.getFields();// workaround for https://github.com/HaxeFoundation/haxe/issues/7905
return ret;
return getType(name, (macro : { t1: $t1, t2: $t2 } ).toType(), pos, function (ctx) return build({
type: types.t1,
type2: types.t2,
pos: ctx.pos,
name: ctx.name,
usings: ctx.usings
}), normalizer);
} }
static public function getParams(name:String, ?pos:Position) static public function getType2(name, ?types, ?pos:Position, build:BuildContext2->TypeDefinition, ?normalizer:Type->Type)
return _getTypeN(name, 2, switch types {
case null: null;
case v: [types.t1, types.t2];
}, pos, ctx -> build({
pos: ctx.pos,
type: ctx.types[0],
type2: ctx.types[1],
usings: ctx.usings,
name: ctx.name
}), normalizer);
static public function getParams(name:String, ?pos:Position, ?count:Int)
return return
switch Context.getLocalType() { switch Context.getLocalType() {
case TInst(_.toString() == name => true, v): case TInst(_.toString() == name => true, v):
@@ -131,70 +109,50 @@ class BuildCache {
}); });
static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition, ?normalizer:Type->Type) { static public function getType(name, ?type, ?pos:Position, build:BuildContext->TypeDefinition, ?normalizer:Type->Type) {
return _getTypeN(name, 1, switch type {
if (type == null) case null: null;
type = getParam(name, pos).sure(); case v: [v];
}, pos, ctx -> build({
var forName = pos: ctx.pos,
switch cache[name] { type: ctx.types[0],
case null: cache[name] = new Group(name, normalizer); usings: ctx.usings,
case v: v; name: ctx.name
} }), normalizer);
var ret = forName.get(type, pos.sanitize(), build);
ret.getFields();// workaround for https://github.com/HaxeFoundation/haxe/issues/7905
return ret;
} }
} }
private typedef Entry = { private class Group {//TODO: this is somewhat obsolete
name:String,
}
private class Group {
var name:String; var name:String;
var counter = 0;
var entries:TypeMap<Entry>;
public function new(name, ?normalizer) { public function new(name) {
this.name = name; this.name = name;
this.entries = new TypeMap(normalizer);
} }
public function get(type:Type, pos:Position, build:BuildContext->TypeDefinition):Type { public function get(types:Array<Type>, pos:Position, build:BuildContextN->TypeDefinition, ?normalizer):Type {
function make(path:String) { types = types.map(switch normalizer {
var usings = []; case null: function (t) return Context.follow(t);
var def = build({ case f: f;
pos: pos, });
type: type,
usings: usings,
name: path.split('.').pop()
});
entries.set(type, { name: path } ); var retName = name + '_' + Context.signature(Sisyphus.exactParams(types));
Context.defineModule(path, [def], usings);
return Context.getType(path); return switch retName.definedType() {
case Some(v): v;
case None:
var usings = [];
var path = name.split('.');
var ret = build({
pos: pos,
types: types,
usings: usings,
name: retName.split('.').pop(),
});
Context.defineModule(retName, [ret], usings);
Context.getType(retName);
} }
function doMake()
while (true)
switch '$name${counter++}' {
case _.definedType() => Some(_):
case v:
return make(v);
}
return
switch entries.get(type) {
case null:
doMake();
case v:
switch v.name.definedType() {
case Some(v): v;
default: doMake();
}
}
} }
} }

View File

@@ -148,11 +148,7 @@ class Sisyphus {
return ( return (
if (isMain) t.pack.concat([t.name]).join('.') if (isMain) t.pack.concat([t.name]).join('.')
else t.module + '.' + t.name else t.module + '.' + t.name
) + switch params { ) + exactParams(params);
case []: '';
case params:
'<${params.map(toExactString).join(', ')}>';
}
} }
static inline function isFinal(c:ClassField) static inline function isFinal(c:ClassField)
@@ -183,6 +179,12 @@ class Sisyphus {
static function exactSig(args:Array<{name:String, opt:Bool, t:Type}>, ret:Type, sep:String) static function exactSig(args:Array<{name:String, opt:Bool, t:Type}>, ret:Type, sep:String)
return '(${[for (a in args) (if (a.opt) '?' else '') + a.name + ':' + toExactString(a.t)].join(', ')})$sep${toExactString(ret)}'; return '(${[for (a in args) (if (a.opt) '?' else '') + a.name + ':' + toExactString(a.t)].join(', ')})$sep${toExactString(ret)}';
static public function exactParams(params:Array<Type>)
return switch params {
case []: '';
case params:
'<${params.map(toExactString).join(', ')}>';
}
static public function toExactString(t:Type) static public function toExactString(t:Type)
return switch t { return switch t {
case TMono(t): t.toString(); case TMono(t): t.toString();

View File

@@ -14,7 +14,7 @@ import haxe.macro.Type.Ref;
class Types { class Types {
static public function definedType(typeName:String) static public function definedType(typeName:String):Option<Type>
return return
try { try {
Some(Context.getType(typeName)); Some(Context.getType(typeName));