phrase-engine
Version:
Language files on steroids for conversational UIs that aren't boring.
188 lines • 6.46 kB
JavaScript
"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