"use strict"; module.exports = class Generator { constructor(parsed) { this.systems = parsed.systems; this.behaviors = parsed.behaviors; this.interactions = parsed.interactions; this.triggers = parsed.triggers; } *generate(obj, scope=1, n=0, i=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}`); let id = null; switch (obj.type) { case "Behavior": if (!obj.body) { // Behavior reference let realObj = this.behaviors[obj.id]; if (!realObj || !realObj.body) throw new Error(`Unable to find referenced behavior: ${obj.id}`); Object.defineProperty(obj, "body", { // use real body but keep it hidden (for debugging the AST mainly) value: realObj.body, }); } /* falls through */ case "System": // or Behavior if (!obj.body) throw new Error(`Unexpected empty ${obj.type}`); id = `${obj.id}_${n + 1}of${max}`; /* falls through */ case "Sequence": // or System or Behavior let outs = []; if (i === 0 && id !== null) outs.push(id); if (i < obj.body.length) { for (let evts of this.generate(obj.body[i], scope)) { for (let nextEvts of this.generate(obj, scope, n, i + 1)) { yield outs.concat(evts, nextEvts); } } } else { if (n >= min - 1) yield outs; if (n < max - 1) { for (let nextEvts of this.generate(obj, scope, n + 1, 0)) yield outs.concat(nextEvts); } } break; default: throw new Error(`UNIMPLEMENTED TYPE: ${obj.type}`); } } };