From 13ae16997d4bbca14e255d5989d1c44a76eac72c Mon Sep 17 00:00:00 2001 From: Valerio Virgillito Date: Wed, 16 May 2012 15:23:48 -0700 Subject: montage v.0.10 integration Signed-off-by: Valerio Virgillito --- node_modules/montage/core/selector/semantics.js | 392 ++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 node_modules/montage/core/selector/semantics.js (limited to 'node_modules/montage/core/selector/semantics.js') diff --git a/node_modules/montage/core/selector/semantics.js b/node_modules/montage/core/selector/semantics.js new file mode 100644 index 00000000..49446e2c --- /dev/null +++ b/node_modules/montage/core/selector/semantics.js @@ -0,0 +1,392 @@ +/* + This file contains proprietary software owned by Motorola Mobility, Inc.
+ No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.
+ (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved. +
*/ + +var AbstractSemantics = require("./abstract-semantics").AbstractSemantics; + +var empty = {}; // used for getting properties of falsy objects + +var Semantics = exports.Semantics = AbstractSemantics.create(AbstractSemantics, { + + operators: { + value: { + + // from highest to lowest precedence + + // unary + not: function (a) { + return !a; + }, + + // function calls + startsWith: function (a, b) { + return a.length >= b.length && + this.equals(a.slice(0, b.length), b); + }, + endsWith: function (a, b) { + return a.length >= b.length && + this.equals(a.slice(a.length - b.length, a.length), b); + }, + + // algebra + + // exponential + pow: function (a, b) { + return Math.pow(a, b); + }, + + // multiplicative + mul: function (a, b) { + return a * b; + }, + div: function (a, b) { + return a / b; + }, + mod: function (a, b) { + return a % b; + }, + + // arithmetic + add: function (a, b) { + return a + b; + }, + sub: function (a, b) { + return a - b; + }, + + // transitive relations + lessThan: function (a, b) { + return Semantics.compare(a, b) < 0; + }, + lessThanOrEquals: function (a, b) { + return Semantics.compare(a, b) <= 0; + }, + greaterThan: function (a, b) { + return Semantics.compare(a, b) > 0; + }, + greaterThanOrEquals: function (a, b) { + return Semantics.compare(a, b) >= 0; + }, + + // equivalence relations + equals: function (a, b) { + if (a == null || b == null) { + return a === b; + } else if (a.equals) { + return a.equals(b); + } else if (b.equals) { + return b.equals(a); + } else { + return a === b; + } + }, + notEquals: function (a, b) { + return !this.equals(a, b); + }, + + // logical ('and' and 'or' are evaluators for the short-circuiting) + + xor: function (a, b) { + return a !== b; + }, + + // collection operators + + contains: function (collection, value) { // pertains to strings + return collection.indexOf(value) !== -1; + }, + has: function (collection, value) { // pertains to other collections + return collection.indexOf(value) !== -1; + }, + + slice: function (collection, start, stop) { + return collection.slice(start, stop); + }, + // TODO rewrite to accept length then from value + sliceFrom: function (collection, value, length) { + var start = collection.indexOf(value); + if (start !== -1) { + length = Math.min(collection.length - start, length); + return collection.slice(start, start + length); + } else { + return []; + } + } + + } + }, + + evaluators: { + value: { + + // properties + get: function (evaluateObject, evaluateKey, parents) { + + // construct remaining path + var remainingPath = []; + parents = parents.parents; + while (parents) { + if (parents.syntax.type !== 'get') + break; + remainingPath.push(parents.syntax.args[1].value); + parents = parents.parents; + } + if (remainingPath.length === 0) { + remainingPath = null; + } else { + remainingPath = remainingPath.join("."); + } + + return function (value, parameters, visitor) { + var object = evaluateObject(value, parameters, visitor); + var key = evaluateKey(value, parameters, visitor); + var result = (object || empty)[key]; + if (visitor) { + visitor(object, key, result, remainingPath); + } + return result; + }; + }, + + // logical + and: function (a, b) { + return function (value, parameters) { + return a(value, parameters) && b(value, parameters); + }; + }, + or: function (a, b) { + return function (value, parameters) { + return a(value, parameters) || b(value, parameters); + }; + }, + + // ternary conditional + 'if': function (guard, consequent, alternate) { + return function (value, parameters) { + var flag = guard(value, parameters); + if (flag === true) { + return consequent(value, parameters); + } else if (flag === false) { + return alternate(value, parameters); + } else { + throw new Error("Expected true or false, got: " + JSON.stringify(flag)); + } + }; + }, + + it: function (a, b) { + return function (value, parameters) { + return b(a(value, parameters), parameters); + } + }, + + one: function (a, b) { + return function (value, parameters) { + var object = a(value, parameters)[0]; // handle other collections + return b(object, parameters); + }; + }, + only: function (a, b) { + return function (value, parameters) { + var objects = a(value, parameters); // handle other collections + if (objects.length !== 1) + return false; + return b(objects[0], parameters); + }; + }, + filter: function (a, b) { + return function (value, parameters) { + return a(value, parameters) + .filter(function (object) { + return b(object, parameters); + }); + }; + }, + every: function (a, b) { + return function (value, parameters) { + return a(value, parameters) + .every(function (object) { + return b(object, parameters); + }); + }; + }, + some: function (a, b) { + return function (value, parameters) { + return a(value, parameters) + .some(function (object) { + return b(object, parameters); + }); + }; + }, + map: function (a, b) { + return function (value, parameters) { + return a(value, parameters) + .map(function (object) { + return b(object, parameters); + }); + }; + }, + + sorted: function (collection, by, descending) { + var semantics = this; + return function (value, parameters) { + var order = descending() ? -1 : 1; + return collection(value, parameters) + .map(function (item) { + return { + by: by(item, parameters), + value: item + }; + }) + .sort(function (a, b) { + return semantics.compare(a.by, b.by) * order; + }) + .map(function (pair) { + return pair.value; + }) + } + }, + + // reductions + sum: function (collection, modify) { + var self = this; + return function (value, parameters) { + var value = self.sum(collection(value, parameters)); + return modify(value, parameters); + }; + }, + count: function (collection, modify) { + var self = this; + return function (value, parameters) { + var value = self.count(collection(value, parameters)); + return modify(value, parameters); + }; + }, + average: function (collection, modify) { + var self = this; + return function (value, parameters) { + var value = self.average(collection(value, parameters)); + return modify(value, parameters); + }; + }, + unique: function (collection, modify) { + var self = this; + return function (value, parameters) { + var value = self.unique(collection(value, parameters)); + return modify(value, parameters); + }; + }, + flatten: function (collection, modify) { + var self = this; + return function (value, parameters) { + var value = self.flatten(collection(value, parameters)); + return modify(value, parameters); + }; + } + + } + }, + + compile: { + value: function (syntax, parents) { + var self = this; + var child = { + syntax: syntax, + parents: parents + }; + if (syntax.type === 'array') { + var terms = syntax.terms.map(function (term) { + return self.compile(term, child); + }); + return function (value, parameters) { + return terms.map(function (term) { + return term(value, parameters); + }); + }; + } else { + return AbstractSemantics.compile.call(self, syntax, parents); + } + } + }, + + compare: { + value: function (a, b) { + if (typeof a !== typeof b) + return 0; + if (a === b) + return 0; + if (typeof a === "number") + return a - b; + if (typeof a === "string") + return a < b ? -1 : 1; + if (Array.isArray(a)) { + if (!Array.isArray(b)) + return 0; + var length = Math.min(a.length, b.length); + for (var i = 0; i < length; i++) { + var comparison = this.compare(a[i], b[i]); + if (comparison) + return comparison; + } + return a.length - b.length; + } + if (typeof a.compare === "function") + return a.compare(b); + if (typeof b.compare === "function") + return -b.compare(a); + if (typeof a.lessThan === "function" && typeof a.equals === "function") + return a.equals(b) ? 0 : a.lessThan(b) ? -1 : 1; + return 0; + } + }, + + count: { + value: function (collection) { + if (typeof collection.count === "function") { + return collection.count(); + } else { + return collection.length; + } + } + }, + + sum: { + value: function (collection) { + return collection.reduce(function (a, b) { + return a + b; + }, 0); + } + }, + + average: { + value: function (collection) { + return this.sum(collection) / this.count(collection); + } + }, + + unique: { + value: function (collection) { + var unique = []; + collection.forEach(function (value) { + if (unique.every(function (uniqueValue) { + return Semantics.compare(value, uniqueValue) !== 0; + })) { + unique.push(value); + } + }); + return unique; + } + }, + + flatten: { + value: function (table) { + return table.reduce(function (flat, row) { + return flat.concat(row); + }, []) + } + } + +}); + -- cgit v1.2.3