UNPKG

pogo

Version:

A readable, DSL friendly programming language that compiles to JavaScript

163 lines 7.55 kB
(function() { var self = this; var _, codegenUtils; _ = require("underscore"); codegenUtils = require("../terms/codegenUtils"); module.exports = function(terms) { var self = this; var operatorStack, operatorsInDecreasingPrecedenceOrder, operatorTable, createOperatorCall; operatorStack = function() { var operators; operators = []; return { push: function(op, popped) { var self = this; popped = popped || []; if (operators.length === 0) { operators.unshift(op); return popped; } else if (!op.precedence || !operators[0].precedence) { if (!op.precedence) { throw new Error(op.name + " cannot be used with other operators"); } else if (!operators[0].precedence) { throw new Error(operators[0].name + " cannot be used with other operators"); } } else if (op.leftAssociative && op.precedence <= operators[0].precedence) { popped.push(operators.shift()); return self.push(op, popped); } else if (op.precedence < operators[0].precedence) { popped.push(operators.shift()); return self.push(op, popped); } else { operators.unshift(op); return popped; } }, pop: function() { var self = this; return operators; } }; }; operatorsInDecreasingPrecedenceOrder = function(opsString) { var opLines, precedence, operators, gen1_items, gen2_i, line, match, names, assoc, gen3_items, gen4_i, name; opLines = opsString.trim().split(/\n/); precedence = opLines.length + 1; operators = {}; gen1_items = opLines; for (gen2_i = 0; gen2_i < gen1_items.length; ++gen2_i) { line = gen1_items[gen2_i]; match = /\s*((\S+\s+)*)(left|right)/.exec(line); names = match[1].trim().split(/\s+/); assoc = match[3]; --precedence; gen3_items = names; for (gen4_i = 0; gen4_i < gen3_items.length; ++gen4_i) { name = gen3_items[gen4_i]; operators[name] = { name: name, leftAssociative: assoc === "left", precedence: precedence }; } } return operators; }; operatorTable = function() { var table; table = operatorsInDecreasingPrecedenceOrder("\n / * % left\n - + left\n << >> >>> left\n > >= < <= left\n == != left\n & left\n ^^ left\n | left\n :: left\n && @and left\n || @or left\n <- left\n "); return { findOp: function(op) { var self = this; if (table.hasOwnProperty(op)) { return table[op]; } else { return { name: op }; } } }; }(); createOperatorCall = function(name, arguments) { return terms.functionCall(name, arguments); }; return terms.term({ constructor: function(complexExpression) { var self = this; self.arguments = [ complexExpression ]; return self.name = []; }, addOperatorExpression: function(operator, expression) { var self = this; self.name.push(operator); return self.arguments.push(expression); }, expression: function() { var self = this; var operands, operators, applyOperators, n, poppedOps; if (self.arguments.length > 1) { operands = [ self.arguments[0].expression() ]; operators = operatorStack(); applyOperators = function(ops) { var gen5_items, gen6_i, op, right, left, name; gen5_items = ops; for (gen6_i = 0; gen6_i < gen5_items.length; ++gen6_i) { op = gen5_items[gen6_i]; right = operands.shift(); left = operands.shift(); name = terms.variable([ codegenUtils.normaliseOperatorName(op.name) ], { couldBeMacro: false }); operands.unshift(createOperatorCall(name, [ left, right ])); } return void 0; }; for (n = 0; n < self.name.length; ++n) { poppedOps = operators.push(operatorTable.findOp(self.name[n])); applyOperators(poppedOps); operands.unshift(self.arguments[n + 1].expression()); } applyOperators(operators.pop()); return operands[0]; } else { return self.arguments[0].expression(); } }, hashEntry: function() { var self = this; if (self.arguments.length === 1) { return self.arguments[0].hashEntry(); } else { return terms.errors.addTermWithMessage(self, "cannot be used as a hash entry"); } }, definition: function(source, gen7_options) { var self = this; var assignment; assignment = gen7_options !== void 0 && Object.prototype.hasOwnProperty.call(gen7_options, "assignment") && gen7_options.assignment !== void 0 ? gen7_options.assignment : false; var object, parms; if (self.arguments.length > 1) { object = self.arguments[0].expression(); parms = function() { var gen8_results, gen9_items, gen10_i, arg; gen8_results = []; gen9_items = self.arguments.slice(1); for (gen10_i = 0; gen10_i < gen9_items.length; ++gen10_i) { arg = gen9_items[gen10_i]; gen8_results.push(arg.expression().parameter()); } return gen8_results; }(); return terms.definition(terms.fieldReference(object, self.name), source.blockify(parms, []), { assignment: assignment }); } else { return self.arguments[0].definition(source, { assignment: assignment }); } } }); }; }).call(this);