refactor label handling into AsyncEmbeddedScript
This commit is contained in:
@@ -6,7 +6,9 @@ import haxe.macro.Context;
|
|||||||
import haxe.macro.PositionTools;
|
import haxe.macro.PositionTools;
|
||||||
import sys.io.File;
|
import sys.io.File;
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
|
using kiss.Helpers;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
import kiss.Kiss;
|
import kiss.Kiss;
|
||||||
import kiss.Prelude;
|
import kiss.Prelude;
|
||||||
import kiss.cloner.Cloner;
|
import kiss.cloner.Cloner;
|
||||||
@@ -20,10 +22,10 @@ typedef AsyncCommand = (AsyncEmbeddedScript, Continuation) -> Void;
|
|||||||
**/
|
**/
|
||||||
class AsyncEmbeddedScript {
|
class AsyncEmbeddedScript {
|
||||||
private var instructions:Array<AsyncCommand> = null;
|
private var instructions:Array<AsyncCommand> = null;
|
||||||
public var instructionPointersByLine:Map<Int,Int> = [];
|
|
||||||
private var breakPoints:Map<Int, () -> Bool> = [];
|
private var breakPoints:Map<Int, () -> Bool> = [];
|
||||||
private var onBreak:AsyncCommand = null;
|
private var onBreak:AsyncCommand = null;
|
||||||
public var lastInstructionPointer = 0;
|
private var lastInstructionPointer = -1;
|
||||||
|
private var labels:Map<String,Int> = [];
|
||||||
|
|
||||||
public function setBreakHandler(handler:AsyncCommand) {
|
public function setBreakHandler(handler:AsyncCommand) {
|
||||||
onBreak = handler;
|
onBreak = handler;
|
||||||
@@ -50,7 +52,7 @@ class AsyncEmbeddedScript {
|
|||||||
return instructions.length;
|
return instructions.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function runInstruction(instructionPointer:Int, withBreakPoints = true) {
|
private function runInstruction(instructionPointer:Int, withBreakPoints = true) {
|
||||||
lastInstructionPointer = instructionPointer;
|
lastInstructionPointer = instructionPointer;
|
||||||
if (instructions == null)
|
if (instructions == null)
|
||||||
resetInstructions();
|
resetInstructions();
|
||||||
@@ -78,6 +80,26 @@ class AsyncEmbeddedScript {
|
|||||||
runInstruction(0, withBreakPoints);
|
runInstruction(0, withBreakPoints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function skipToInstruction(ip:Int) {
|
||||||
|
for (cIdx in lastInstructionPointer+1... ip) {
|
||||||
|
// TODO add an optional cc argument to runInstruction
|
||||||
|
// TODO use that chain together the unskippable instructions prior to running the requested ip
|
||||||
|
}
|
||||||
|
// TODO remember whether breakpoints were requested
|
||||||
|
runInstruction(ip);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function skipToNextLabel() {
|
||||||
|
var labelPointers = [for (ip in labels) ip];
|
||||||
|
labelPointers.sort(Reflect.compare);
|
||||||
|
for (ip in labelPointers) {
|
||||||
|
if (ip > lastInstructionPointer) {
|
||||||
|
skipToInstruction(ip);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if macro
|
#if macro
|
||||||
public static function build(dslHaxelib:String, dslFile:String, scriptFile:String):Array<Field> {
|
public static function build(dslHaxelib:String, dslFile:String, scriptFile:String):Array<Field> {
|
||||||
// trace('AsyncEmbeddedScript.build $dslHaxelib $dslFile $scriptFile');
|
// trace('AsyncEmbeddedScript.build $dslHaxelib $dslFile $scriptFile');
|
||||||
@@ -89,7 +111,15 @@ class AsyncEmbeddedScript {
|
|||||||
var classFields = []; // Kiss.build() will already include Context.getBuildFields()
|
var classFields = []; // Kiss.build() will already include Context.getBuildFields()
|
||||||
|
|
||||||
var commandList:Array<Expr> = [];
|
var commandList:Array<Expr> = [];
|
||||||
var mappedIndexList:Array<Expr> = [];
|
var labelsList:Array<Expr> = [];
|
||||||
|
|
||||||
|
k.macros["label"] = (wholeExp:ReaderExp, args:Array<ReaderExp>, k:KissState) -> {
|
||||||
|
wholeExp.checkNumArgs(1, 1, '(label <label>)');
|
||||||
|
var label = Prelude.symbolNameValue(args[0]);
|
||||||
|
labelsList.push(macro labels[$v{label}] = $v{commandList.length});
|
||||||
|
|
||||||
|
wholeExp.expBuilder().callSymbol("cc", []);
|
||||||
|
};
|
||||||
|
|
||||||
if (dslHaxelib.length > 0) {
|
if (dslHaxelib.length > 0) {
|
||||||
dslFile = Path.join([Prelude.libPath(dslHaxelib), dslFile]);
|
dslFile = Path.join([Prelude.libPath(dslHaxelib), dslFile]);
|
||||||
@@ -109,10 +139,7 @@ class AsyncEmbeddedScript {
|
|||||||
#if debug
|
#if debug
|
||||||
expr = macro { trace($v{exprString}); $expr; };
|
expr = macro { trace($v{exprString}); $expr; };
|
||||||
#end
|
#end
|
||||||
|
|
||||||
if (expr != null) {
|
if (expr != null) {
|
||||||
mappedIndexList.push(macro instructionPointersByLine[$v{nextExp.pos.line}] = $v{commandList.length});
|
|
||||||
|
|
||||||
commandList.push(macro function(self, cc) {
|
commandList.push(macro function(self, cc) {
|
||||||
$expr;
|
$expr;
|
||||||
});
|
});
|
||||||
@@ -139,7 +166,7 @@ class AsyncEmbeddedScript {
|
|||||||
args: [],
|
args: [],
|
||||||
expr: macro {
|
expr: macro {
|
||||||
this.instructions = [$a{commandList}];
|
this.instructions = [$a{commandList}];
|
||||||
$b{mappedIndexList};
|
$b{labelsList};
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
@@ -33,9 +33,4 @@
|
|||||||
(method :Void update [:Float elapsed]
|
(method :Void update [:Float elapsed]
|
||||||
(#when debug
|
(#when debug
|
||||||
(when FlxG.keys.justPressed.N
|
(when FlxG.keys.justPressed.N
|
||||||
(doFor [idx label] (enumerate labels)
|
(skipToNextLabel))))
|
||||||
(when (> label lastInstructionPointer)
|
|
||||||
(doFor =>labelName labelIdx labelsByName
|
|
||||||
(when (= labelIdx label) (trace "SKIPPING TO $labelName")))
|
|
||||||
(runInstruction (dictGet instructionPointersByLine label))
|
|
||||||
(break))))))
|
|
@@ -4,36 +4,19 @@
|
|||||||
(collectBlocks preload (#when (StringTools.contains kissFile className) (cc)))
|
(collectBlocks preload (#when (StringTools.contains kissFile className) (cc)))
|
||||||
(collectBlocks cleanup (#when (StringTools.contains kissFile className) (cc)))
|
(collectBlocks cleanup (#when (StringTools.contains kissFile className) (cc)))
|
||||||
|
|
||||||
(prop :Map<String,Int> labelsByName (new Map))
|
|
||||||
(prop :Array<Int> labels [])
|
|
||||||
|
|
||||||
(defMacroVar _labelNames [])
|
|
||||||
(defMacroVar _labelLines [])
|
|
||||||
(defReaderMacro "LABEL " [stream]
|
|
||||||
(_labelNames.push (stream.expect "label name" ->(stream.takeLine)))
|
|
||||||
(_labelLines.push (- .line (stream.position) 1))
|
|
||||||
`(cc))
|
|
||||||
|
|
||||||
(defMacro end []
|
(defMacro end []
|
||||||
(let [labelSetters
|
`{
|
||||||
(for [label idx] (zipThrow _labelNames _labelLines)
|
(method doPreload [:Void->Void cc]
|
||||||
`{
|
(set isLoading true)
|
||||||
(dictSet labelsByName ,label ,idx)
|
(collectedBlocks preload)
|
||||||
(labels.push ,idx)
|
(set isLoading false)
|
||||||
})]
|
(cc))
|
||||||
`{
|
(method doCleanup []
|
||||||
(method doPreload [:Void->Void cc]
|
(director.cleanup)
|
||||||
(set isLoading true)
|
(set lastInstructionPointer -2)
|
||||||
(collectedBlocks preload)
|
(collectedBlocks cleanup))
|
||||||
(set isLoading false)
|
(doCleanup)
|
||||||
,@labelSetters
|
})
|
||||||
(cc))
|
|
||||||
(method doCleanup []
|
|
||||||
(director.cleanup)
|
|
||||||
(set lastInstructionPointer -2)
|
|
||||||
(collectedBlocks cleanup))
|
|
||||||
(doCleanup)
|
|
||||||
}))
|
|
||||||
|
|
||||||
(defReaderMacro &bof "" [stream] `(#when (StringTools.contains kissFile className) (doPreload cc)))
|
(defReaderMacro &bof "" [stream] `(#when (StringTools.contains kissFile className) (doPreload cc)))
|
||||||
(defReaderMacro &eof "" [stream] `(#when (StringTools.contains kissFile className) (end)))
|
(defReaderMacro &eof "" [stream] `(#when (StringTools.contains kissFile className) (end)))
|
Reference in New Issue
Block a user