Try to be smarter about when bouncing initialization.
This commit is contained in:
@@ -25,20 +25,20 @@ class Constructor {
|
|||||||
var owner:ClassBuilder;
|
var owner:ClassBuilder;
|
||||||
var meta:Metadata;
|
var meta:Metadata;
|
||||||
public var isPublic:Null<Bool>;
|
public var isPublic:Null<Bool>;
|
||||||
|
|
||||||
public function new(owner:ClassBuilder, f:Function, ?isPublic:Null<Bool> = null, ?pos:Position, ?meta:Metadata) {
|
public function new(owner:ClassBuilder, f:Function, ?isPublic:Null<Bool> = null, ?pos:Position, ?meta:Metadata) {
|
||||||
this.nuStatements = [];
|
this.nuStatements = [];
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
this.isPublic = isPublic;
|
this.isPublic = isPublic;
|
||||||
this.pos = pos.sanitize();
|
this.pos = pos.sanitize();
|
||||||
|
|
||||||
this.onGenerateHooks = [];
|
this.onGenerateHooks = [];
|
||||||
this.args = [];
|
this.args = [];
|
||||||
this.beforeArgs = [];
|
this.beforeArgs = [];
|
||||||
this.afterArgs = [];
|
this.afterArgs = [];
|
||||||
this.meta = meta;
|
this.meta = meta;
|
||||||
|
|
||||||
this.oldStatements =
|
this.oldStatements =
|
||||||
if (f == null) [];
|
if (f == null) [];
|
||||||
else {
|
else {
|
||||||
for (i in 0...f.args.length) {
|
for (i in 0...f.args.length) {
|
||||||
@@ -49,15 +49,15 @@ class Constructor {
|
|||||||
}
|
}
|
||||||
beforeArgs.push(a);
|
beforeArgs.push(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (f.expr == null) [];
|
if (f.expr == null) [];
|
||||||
else
|
else
|
||||||
switch (f.expr.expr) {
|
switch (f.expr.expr) {
|
||||||
case EBlock(exprs): exprs;
|
case EBlock(exprs): exprs;
|
||||||
default: oldStatements = [f.expr];
|
default: oldStatements = [f.expr];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
superCall =
|
superCall =
|
||||||
if (oldStatements.length == 0) [].toBlock();
|
if (oldStatements.length == 0) [].toBlock();
|
||||||
else switch oldStatements[0] {
|
else switch oldStatements[0] {
|
||||||
case macro super($a{_}): oldStatements.shift();
|
case macro super($a{_}): oldStatements.shift();
|
||||||
@@ -68,43 +68,69 @@ class Constructor {
|
|||||||
public function getArgList():Array<FunctionArg>
|
public function getArgList():Array<FunctionArg>
|
||||||
return beforeArgs.concat(args).concat(afterArgs);
|
return beforeArgs.concat(args).concat(afterArgs);
|
||||||
|
|
||||||
public function addStatement(e:Expr, ?prepend)
|
public function addStatement(e:Expr, ?prepend)
|
||||||
if (prepend)
|
if (prepend)
|
||||||
this.nuStatements.unshift(e)
|
this.nuStatements.unshift(e)
|
||||||
else
|
else
|
||||||
this.nuStatements.push(e);
|
this.nuStatements.push(e);
|
||||||
|
|
||||||
public function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
public function addArg(name:String, ?t:ComplexType, ?e:Expr, ?opt = false)
|
||||||
args.push( { name : name, opt : opt || e != null, type : t, value: e } );
|
args.push( { name : name, opt : opt || e != null, type : t, value: e } );
|
||||||
|
|
||||||
public function init(name:String, pos:Position, with:FieldInit, ?options:{ ?prepend:Bool, ?bypass:Bool }) {
|
public function init(name:String, pos:Position, with:FieldInit, ?options:{ ?prepend:Bool, ?bypass:Bool }) {
|
||||||
if (options == null)
|
if (options == null)
|
||||||
options = {};
|
options = {};
|
||||||
var e =
|
var e =
|
||||||
switch with {
|
switch with {
|
||||||
case Arg(t, noPublish):
|
case Arg(t, noPublish):
|
||||||
if (noPublish != true)
|
if (noPublish != true)
|
||||||
publish();
|
publish();
|
||||||
args.push( { name : name, opt : false, type : t } );
|
args.push( { name : name, opt : false, type : t } );
|
||||||
name.resolve(pos);
|
name.resolve(pos);
|
||||||
case OptArg(e, t, noPublish):
|
case OptArg(e, t, noPublish):
|
||||||
if (noPublish != true)
|
if (noPublish != true)
|
||||||
publish();
|
publish();
|
||||||
args.push( { name : name, opt : true, type : t, value: e } );
|
args.push( { name : name, opt : true, type : t, value: e } );
|
||||||
name.resolve(pos);
|
name.resolve(pos);
|
||||||
case Value(e): e;
|
case Value(e): e;
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmp = MacroApi.tempName();
|
var tmp = MacroApi.tempName();
|
||||||
var member = owner.memberByName(name).sure();
|
var member = owner.memberByName(name).sure();
|
||||||
|
|
||||||
if (options.bypass && member.kind.match(FProp(_, 'never' | 'set', _, _))) {
|
|
||||||
|
|
||||||
member.addMeta(':isVar');
|
|
||||||
|
|
||||||
|
var metaBypass = false;
|
||||||
|
var bypass = switch options.bypass {
|
||||||
|
case null:
|
||||||
|
switch member.kind {
|
||||||
|
case FProp(_, 'default' | 'null', _):
|
||||||
|
false;
|
||||||
|
#if haxe4
|
||||||
|
case FProp('default', 'never', _):
|
||||||
|
member.isFinal = true;
|
||||||
|
case FProp(_, 'set', _):
|
||||||
|
member.addMeta(':isVar');
|
||||||
|
metaBypass = true;
|
||||||
|
#end
|
||||||
|
case FProp(_):
|
||||||
|
true;
|
||||||
|
case FFun(_):
|
||||||
|
pos.error('cannot rebind function');
|
||||||
|
default: false;
|
||||||
|
}
|
||||||
|
case v: v;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.bypass && member.kind.match(FProp(_, 'never' | 'set', _, _))) {
|
||||||
|
|
||||||
|
member.addMeta(':isVar');
|
||||||
|
switch member.kind {
|
||||||
|
case FProp(get, set, _):
|
||||||
|
member.pos.warning('$get,$set');
|
||||||
|
default:
|
||||||
|
}
|
||||||
addStatement((function () {
|
addStatement((function () {
|
||||||
var fields = [for (f in (macro this).typeof().sure().getClass().fields.get()) f.name => f];
|
var fields = [for (f in (macro this).typeof().sure().getClass().fields.get()) f.name => f];
|
||||||
|
|
||||||
function setDirectly(t:TypedExpr) {
|
function setDirectly(t:TypedExpr) {
|
||||||
var direct = null;
|
var direct = null;
|
||||||
function seek(t:TypedExpr) {
|
function seek(t:TypedExpr) {
|
||||||
@@ -112,15 +138,15 @@ class Constructor {
|
|||||||
case TField({ expr: TConst(TThis) }, FInstance(_, _, f)) if (f.get().name == name): direct = t;
|
case TField({ expr: TConst(TThis) }, FInstance(_, _, f)) if (f.get().name == name): direct = t;
|
||||||
default: t.iter(seek);
|
default: t.iter(seek);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
seek(t);
|
seek(t);
|
||||||
if (direct == null) pos.error('nope');
|
if (direct == null) pos.error('nope');
|
||||||
var direct = Context.storeTypedExpr(direct);
|
var direct = Context.storeTypedExpr(direct);
|
||||||
return macro @:pos(pos) $direct = $e;
|
return macro @:pos(pos) $direct = $e;
|
||||||
}
|
}
|
||||||
|
|
||||||
return switch fields[name] {
|
return switch fields[name] {
|
||||||
case null:
|
case null:
|
||||||
pos.error('this direct initialization causes the compiler to do really weird things');
|
pos.error('this direct initialization causes the compiler to do really weird things');
|
||||||
case f:
|
case f:
|
||||||
switch f.kind {
|
switch f.kind {
|
||||||
@@ -138,24 +164,30 @@ class Constructor {
|
|||||||
pos.error('not implemented');
|
pos.error('not implemented');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).bounce(), options.prepend);
|
}).bounce(), options.prepend);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
addStatement(macro @:pos(pos) this.$name = $e, options.prepend);
|
addStatement(
|
||||||
|
if (metaBypass)
|
||||||
|
macro @:pos(pos) @:bypassAccessor this.$name = $e
|
||||||
|
else
|
||||||
|
macro @:pos(pos) this.$name = $e,
|
||||||
|
options.prepend
|
||||||
|
);
|
||||||
}
|
}
|
||||||
public inline function publish()
|
public inline function publish()
|
||||||
if (isPublic == null)
|
if (isPublic == null)
|
||||||
isPublic = true;
|
isPublic = true;
|
||||||
|
|
||||||
function toBlock()
|
function toBlock()
|
||||||
return [superCall]
|
return [superCall]
|
||||||
.concat(nuStatements)
|
.concat(nuStatements)
|
||||||
.concat(oldStatements)
|
.concat(oldStatements)
|
||||||
.toBlock(pos);
|
.toBlock(pos);
|
||||||
|
|
||||||
public function onGenerate(hook)
|
public function onGenerate(hook)
|
||||||
this.onGenerateHooks.push(hook);
|
this.onGenerateHooks.push(hook);
|
||||||
|
|
||||||
public function toHaxe():Field {
|
public function toHaxe():Field {
|
||||||
var f:Function = {
|
var f:Function = {
|
||||||
args: this.beforeArgs.concat(this.args).concat(this.afterArgs),
|
args: this.beforeArgs.concat(this.args).concat(this.afterArgs),
|
||||||
|
Reference in New Issue
Block a user