kopia lustrzana https://github.com/backface/turtlestitch
rodzic
75849a59a2
commit
723c232f3d
|
@ -2357,3 +2357,4 @@ ______
|
||||||
1411225
|
1411225
|
||||||
-------
|
-------
|
||||||
* Threads: Evaluator optimizations (reducing the stack size for reporters)
|
* Threads: Evaluator optimizations (reducing the stack size for reporters)
|
||||||
|
* Threads: Full TCO (tail-call-elimination), now Snap! *is* Scheme :-)
|
||||||
|
|
102
threads.js
102
threads.js
|
@ -564,12 +564,14 @@ Process.prototype.doReport = function (block) {
|
||||||
this.popContext();
|
this.popContext();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.context.expression === 'expectReport') {
|
if (this.context) {
|
||||||
// pop off inserted top-level exit context
|
if (this.context.expression === 'expectReport') {
|
||||||
this.popContext();
|
// pop off inserted top-level exit context
|
||||||
} else {
|
this.popContext();
|
||||||
// un-tag and preserve original caller
|
} else {
|
||||||
this.context.tag = null;
|
// un-tag and preserve original caller
|
||||||
|
this.context.tag = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.pushContext(block.inputs()[0], outer);
|
this.pushContext(block.inputs()[0], outer);
|
||||||
};
|
};
|
||||||
|
@ -831,7 +833,6 @@ Process.prototype.evaluate = function (
|
||||||
caller = this.context.parentContext,
|
caller = this.context.parentContext,
|
||||||
exit,
|
exit,
|
||||||
runnable,
|
runnable,
|
||||||
extra,
|
|
||||||
parms = args.asArray(),
|
parms = args.asArray(),
|
||||||
i,
|
i,
|
||||||
value;
|
value;
|
||||||
|
@ -845,17 +846,11 @@ Process.prototype.evaluate = function (
|
||||||
outer,
|
outer,
|
||||||
context.receiver
|
context.receiver
|
||||||
);
|
);
|
||||||
extra = new Context(runnable, 'doYield');
|
this.context.parentContext = runnable;
|
||||||
|
|
||||||
// Note: if the context's expression is a ReporterBlockMorph,
|
|
||||||
// the extra context gets popped off immediately without taking
|
|
||||||
// effect (i.e. it doesn't yield within evaluating a stack of
|
|
||||||
// nested reporters)
|
|
||||||
|
|
||||||
if (context.expression instanceof ReporterBlockMorph) {
|
if (context.expression instanceof ReporterBlockMorph) {
|
||||||
this.context.parentContext = extra;
|
// auto-"warp" nested reporters
|
||||||
} else {
|
this.readyToYield = (Date.now() - this.lastYield > this.timeout);
|
||||||
this.context.parentContext = runnable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// assign parameters if any were passed
|
// assign parameters if any were passed
|
||||||
|
@ -1062,7 +1057,6 @@ Process.prototype.evaluateCustomBlock = function () {
|
||||||
parms = args.asArray(),
|
parms = args.asArray(),
|
||||||
runnable,
|
runnable,
|
||||||
exit,
|
exit,
|
||||||
extra,
|
|
||||||
i,
|
i,
|
||||||
value,
|
value,
|
||||||
outer;
|
outer;
|
||||||
|
@ -1081,8 +1075,7 @@ Process.prototype.evaluateCustomBlock = function () {
|
||||||
outer.receiver
|
outer.receiver
|
||||||
);
|
);
|
||||||
runnable.isCustomBlock = true;
|
runnable.isCustomBlock = true;
|
||||||
extra = new Context(runnable, 'doYield');
|
this.context.parentContext = runnable;
|
||||||
this.context.parentContext = extra;
|
|
||||||
|
|
||||||
// passing parameters if any were passed
|
// passing parameters if any were passed
|
||||||
if (parms.length > 0) {
|
if (parms.length > 0) {
|
||||||
|
@ -1104,40 +1097,43 @@ Process.prototype.evaluateCustomBlock = function () {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runnable.expression instanceof CommandBlockMorph) {
|
// tag return target
|
||||||
// insert a reporter exit tag for the
|
if (this.context.expression.definition.type !== 'command') {
|
||||||
// CALL SCRIPT primitive variant
|
if (caller) {
|
||||||
if (this.context.expression.definition.type !== 'command') {
|
// tag caller, so "report" can catch it later
|
||||||
if (caller) {
|
caller.tag = 'exit';
|
||||||
// tag caller, so "report" can catch it later
|
|
||||||
caller.tag = 'exit';
|
|
||||||
} else {
|
|
||||||
// top-level context, insert a tagged exit context
|
|
||||||
// which "report" can catch later
|
|
||||||
exit = new Context(
|
|
||||||
runnable.parentContext,
|
|
||||||
'expectReport',
|
|
||||||
outer,
|
|
||||||
outer.receiver
|
|
||||||
);
|
|
||||||
exit.tag = 'exit';
|
|
||||||
runnable.parentContext = exit;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// tag all "stop this block" blocks with the current
|
// top-level context, insert a tagged exit context
|
||||||
// procedureCount as exitTag, and mark all "report" blocks
|
// which "report" can catch later
|
||||||
// as being inside a custom command definition
|
exit = new Context(
|
||||||
runnable.expression.tagExitBlocks(this.procedureCount, true);
|
runnable.parentContext,
|
||||||
|
'expectReport',
|
||||||
// tag the caller with the current procedure count, so
|
outer,
|
||||||
// "stop this block" blocks can catch it, but only
|
outer.receiver
|
||||||
// if the caller hasn't been tagged already
|
);
|
||||||
if (caller && !caller.tag) {
|
exit.tag = 'exit';
|
||||||
caller.tag = this.procedureCount;
|
runnable.parentContext = exit;
|
||||||
}
|
}
|
||||||
|
// auto-"warp" nested reporters
|
||||||
|
this.readyToYield = (Date.now() - this.lastYield > this.timeout);
|
||||||
|
} else {
|
||||||
|
// tag all "stop this block" blocks with the current
|
||||||
|
// procedureCount as exitTag, and mark all "report" blocks
|
||||||
|
// as being inside a custom command definition
|
||||||
|
runnable.expression.tagExitBlocks(this.procedureCount, true);
|
||||||
|
|
||||||
|
// tag the caller with the current procedure count, so
|
||||||
|
// "stop this block" blocks can catch it, but only
|
||||||
|
// if the caller hasn't been tagged already
|
||||||
|
if (caller && !caller.tag) {
|
||||||
|
caller.tag = this.procedureCount;
|
||||||
|
}
|
||||||
|
// yield commands unless explicitly "warped"
|
||||||
|
if (!this.isAtomic) {
|
||||||
|
this.readyToYield = true;
|
||||||
}
|
}
|
||||||
runnable.expression = runnable.expression.blockSequence();
|
|
||||||
}
|
}
|
||||||
|
runnable.expression = runnable.expression.blockSequence();
|
||||||
};
|
};
|
||||||
|
|
||||||
// Process variables primitives
|
// Process variables primitives
|
||||||
|
@ -2920,12 +2916,10 @@ Context.prototype.continuation = function () {
|
||||||
} else if (this.parentContext) {
|
} else if (this.parentContext) {
|
||||||
cont = this.parentContext;
|
cont = this.parentContext;
|
||||||
} else {
|
} else {
|
||||||
return new Context(null, 'doStop');
|
return new Context(null, 'doYield');
|
||||||
}
|
|
||||||
if (cont.expression === 'expectReport') {
|
|
||||||
return cont.continuation();
|
|
||||||
}
|
}
|
||||||
cont = cont.copyForContinuation();
|
cont = cont.copyForContinuation();
|
||||||
|
cont.tag = null;
|
||||||
cont.isContinuation = true;
|
cont.isContinuation = true;
|
||||||
return cont;
|
return cont;
|
||||||
};
|
};
|
||||||
|
|
Ładowanie…
Reference in New Issue