Explorar el Código

MPIDE-28: generator: 🐎: tweak for speed & clarity

* pass preceding events down to remove local states in hopes of getting closer to being Tail Call Optimizable (TCO)
Kyle P Davis hace 10 años
padre
commit
0ad8d3e40e
Se han modificado 1 ficheros con 14 adiciones y 18 borrados
  1. 14 18
      src/lib/generator/modellang.es6

+ 14 - 18
src/lib/generator/modellang.es6

@@ -9,11 +9,10 @@ module.exports = class Generator {
 		this.triggers = parsed.triggers;
 	}
 
-	//TODO: try to tweak for Tail Recursion Optimization (we can use Babel to fix it up for browsers)
-	*generate(obj, scope=1, n=0, i=0) {
+	*generate(obj, scope=1, pre=[], gen=0, idx=0) {
 		let min = obj.scope && typeof obj.scope.min === "number" ? obj.scope.min : 1;
 		let max = obj.scope && typeof obj.scope.max === "number" ? obj.scope.max : scope;
-		//console.log(`t=${obj.type}	id=${obj.id || `...${obj.body.length}`}	n=${n}	i=${i}	s=${scope}	min=${min}	max=${max}`);
+		//console.log(`t=${obj.type}	id=${obj.id || `...${obj.body.length}`}	gen=${gen}	idx=${idx}	s=${scope}	min=${min}	max=${max}`);
 
 		let id = null;
 		switch (obj.type) {
@@ -29,32 +28,29 @@ module.exports = class Generator {
 				/* falls through */
 			case "System": // or Behavior
 				if (!obj.body) throw new Error(`Unexpected empty ${obj.type}`);
-				id = `${obj.id}_${n + 1}of${max}`;
+				id = `${obj.id}_${gen + 1}of${max}`;
 				/* falls through */
 			case "Sequence":
 			case "Group":
 			case "Alternation":
-				let outs = [];
-				if (i === 0) {
+				let outs = [...pre];
+				if (idx === 0) {
+					if (gen === 0 && min === 0) yield outs; // if first item in first generation and optional output empty case
 					if (id !== null) outs.push(id); // add to trace unless structural only (e.g., sequences)
-					if (n === 0 && min === 0) yield []; // if first item in first generation and optional output empty case
 				}
-				if (i < obj.body.length) {
+				if (idx < obj.body.length) {
 					if (obj.type !== "Alternation") {
-						for (let evts of this.generate(obj.body[i], scope, 0, 0)) {
-							for (let nextEvts of this.generate(obj, scope, n, i + 1)) {
-								yield outs.concat(evts, nextEvts);
-							}
+						for (let evts of this.generate(obj.body[idx], scope, outs, 0, 0)) {
+							yield* this.generate(obj, scope, evts, gen, idx + 1);
 						}
 					} else { // Alternation
-						yield* this.generate(obj.body[i], scope, 0, 0);
-						yield* this.generate(obj, scope, n, i + 1);
+						yield* this.generate(obj.body[idx], scope, outs, 0, 0);
+						yield* this.generate(obj, scope, outs, gen, idx + 1);
 					}
 				} else {
-					if (n >= min - 1 && obj.type !== "Alternation") yield outs;
-					if (n < max - 1) {
-						for (let nextEvts of this.generate(obj, scope, n + 1, 0))
-							yield outs.concat(nextEvts);
+					if (gen >= min - 1 && obj.type !== "Alternation") yield outs;
+					if (gen < max - 1) {
+						yield* this.generate(obj, scope, outs, gen + 1, 0);
 					}
 				}
 				break;