UNPKG

phrase-engine

Version:

Language files on steroids for conversational UIs that aren't boring.

188 lines 6.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const RefableNode_1 = require("../RefableNode"); const peek_1 = require("../peek"); const mapFilter_1 = require("../mapFilter"); const factories_1 = require("../factories"); const expressionStack_1 = require("../expressionStack"); const PhraseError_1 = require("../PhraseError"); class IfNode extends RefableNode_1.RefableNode { validateNodeName(name) { return name === 'if'; } evalLogic(packet) { const e_stack = []; const l_stack = this.__logic_stack.slice(0); let cur = l_stack.pop(); while (!!cur) { if (expressionStack_1.isOperator(cur)) { if (cur === '!') { let a = e_stack.pop(); e_stack.push((!a)); } else if (cur === '&') { let a = e_stack.pop(); let b = e_stack.pop(); e_stack.push((a && b)); } else if (cur === '|') { let a = e_stack.pop(); let b = e_stack.pop(); e_stack.push((a || b)); } } else { e_stack.push((() => { if (cur in packet.data) { return !!packet.data[cur]; } else { if (cur[0] === '#') { return !!packet.id_render_map[cur.substr(1)]; } else if (cur[0] === '.') { return !!packet.class_render_map[cur.substr(1)]; } else { return false; } } })()); } cur = l_stack.pop(); } return e_stack[0]; } init(root, packet) { this.__implicit = false; if (!root.hasAttribute('condition')) { let err = new PhraseError_1.PhraseError(`A condition must be specified in <if/>`); err.node(root); throw err; } const condition = root.getAttribute('condition'); if (!condition.trim()) { let err = new PhraseError_1.PhraseError(`Condition is empty in <if/>`); err.node(root); throw err; } this.__logic_stack = expressionStack_1.default(condition).reverse(); const type_support = mapFilter_1.default(factories_1.default, [ 'then', 'else' ]); const useful_node = Array(root.childNodes.length) .fill('') .map((_, i) => root.childNodes.item(i)) .filter(node => { if (node.nodeName === 'then' || node.nodeName === 'else') { return true; } else { return false; } }) .sort((a, b) => Number(a.nodeName < b.nodeName)); if (useful_node.length === 2) { this.__then = type_support['then'](useful_node[0], packet); this.__else = type_support['else'](useful_node[1], packet); } else if (useful_node.length === 1) { if (useful_node[0].nodeName === 'then') { this.__then = type_support['then'](useful_node[0], packet); this.__else = peek_1.default(packet.next_stack); } else { this.__then = peek_1.default(packet.next_stack); this.__else = type_support['else'](useful_node[0], packet); } } else if (useful_node.length === 0) { this.__implicit = true; this.__then = type_support['then'](root, packet); this.__else = peek_1.default(packet.next_stack); } else { let err = new PhraseError_1.PhraseError(`Multiple thens or elses in if`); err.node(root); throw err; } this.registararGenerate(root); } eval(packet, branch) { if (this.__implicit) { if (this.evalLogic(packet)) { this.registerRender(packet); return this.__then.eval(packet); } else { return this.__else.eval(packet); } } else { this.registerRender(packet); return this.evalLogic(packet) ? this.__then.eval(packet) : this.__else.eval(packet); } } *gen(packet) { if (this.__implicit) { if (this.evalLogic(packet)) { this.registerRender(packet); yield* this.__then.gen(packet); this.deregisterRender(packet); } else { yield* this.__else.gen(packet); } } else { this.registerRender(packet); yield* this.evalLogic(packet) ? this.__then.gen(packet) : this.__else.gen(packet); this.deregisterRender(packet); } } vars(packet) { if (!this.__vared) { this.__logic_stack .filter(entry => !expressionStack_1.isOperator(entry)) .filter(entry => entry[0] !== '.' && entry[0] !== '#') .forEach(entry => { packet.vars[entry] = packet.vars[entry] || []; packet.vars[entry].push({ type: 'boolean' }); }); this.__then.vars(packet); this.__else.vars(packet); this.__vared = true; } return packet; } count(packet) { let ret; if (this.__implicit) { if (this.evalLogic(packet)) { this.registerRender(packet); ret = this.__then.count(packet); this.deregisterRender(packet); } else { ret = this.__else.count(packet); } } else { this.registerRender(packet); ret = this.evalLogic(packet) ? this.__then.count(packet) : this.__else.count(packet); this.deregisterRender(packet); } return ret; } } exports.IfNode = IfNode; //# sourceMappingURL=IfNode.js.map