UNPKG

tcl-js

Version:

tcl-js is a tcl intepreter written completely in Typescript. It is meant to replicate the tcl-sh interpreter as closely as possible.

98 lines (95 loc) 3 kB
import { INUMBER, IOP1, IOP2, IOP3, IVAR, IFUNCALL, IEXPR, IMEMBER } from './instruction'; export default function expressionToString(tokens, toJS) { var nstack = []; var n1, n2, n3; var f; for (var i = 0; i < tokens.length; i++) { var item = tokens[i]; var type = item.type; if (type === INUMBER) { if (typeof item.value === 'number' && item.value < 0) { nstack.push('(' + item.value + ')'); } else { nstack.push(escapeValue(item.value)); } } else if (type === IOP2) { n2 = nstack.pop(); n1 = nstack.pop(); f = item.value; if (toJS) { if (f === '^') { nstack.push('Math.pow(' + n1 + ', ' + n2 + ')'); } else if (f === 'and') { nstack.push('(!!' + n1 + ' && !!' + n2 + ')'); } else if (f === 'or') { nstack.push('(!!' + n1 + ' || !!' + n2 + ')'); } else if (f === '||') { nstack.push('(String(' + n1 + ') + String(' + n2 + '))'); } else if (f === '==') { nstack.push('(' + n1 + ' === ' + n2 + ')'); } else if (f === '!=') { nstack.push('(' + n1 + ' !== ' + n2 + ')'); } else { nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); } } else { nstack.push('(' + n1 + ' ' + f + ' ' + n2 + ')'); } } else if (type === IOP3) { n3 = nstack.pop(); n2 = nstack.pop(); n1 = nstack.pop(); f = item.value; if (f === '?') { nstack.push('(' + n1 + ' ? ' + n2 + ' : ' + n3 + ')'); } else { throw new Error('invalid Expression'); } } else if (type === IVAR) { nstack.push(item.value); } else if (type === IOP1) { n1 = nstack.pop(); f = item.value; if (f === '-' || f === '+') { nstack.push('(' + f + n1 + ')'); } else if (toJS) { if (f === 'not') { nstack.push('(' + '!' + n1 + ')'); } else if (f === '!') { nstack.push('fac(' + n1 + ')'); } else { nstack.push(f + '(' + n1 + ')'); } } else if (f === '!') { nstack.push('(' + n1 + '!)'); } else { nstack.push('(' + f + ' ' + n1 + ')'); } } else if (type === IFUNCALL) { var argCount = item.value; var args = []; while (argCount-- > 0) { args.unshift(nstack.pop()); } f = nstack.pop(); nstack.push(f + '(' + args.join(', ') + ')'); } else if (type === IMEMBER) { n1 = nstack.pop(); nstack.push(n1 + '.' + item.value); } else if (type === IEXPR) { nstack.push('(' + expressionToString(item.value, toJS) + ')'); } else { throw new Error('invalid Expression'); } } if (nstack.length > 1) { throw new Error('invalid Expression (parity)'); } return String(nstack[0]); } function escapeValue(v) { if (typeof v === 'string') { return JSON.stringify(v).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029'); } return v; }