aboutsummaryrefslogtreecommitdiff
path: root/node_modules/montage/core/selector/semantics.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/montage/core/selector/semantics.js')
-rw-r--r--node_modules/montage/core/selector/semantics.js392
1 files changed, 392 insertions, 0 deletions
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 @@
1/* <copyright>
2 This file contains proprietary software owned by Motorola Mobility, Inc.<br/>
3 No rights, expressed or implied, whatsoever to this software are provided by Motorola Mobility, Inc. hereunder.<br/>
4 (c) Copyright 2011 Motorola Mobility, Inc. All Rights Reserved.
5 </copyright> */
6
7var AbstractSemantics = require("./abstract-semantics").AbstractSemantics;
8
9var empty = {}; // used for getting properties of falsy objects
10
11var Semantics = exports.Semantics = AbstractSemantics.create(AbstractSemantics, {
12
13 operators: {
14 value: {
15
16 // from highest to lowest precedence
17
18 // unary
19 not: function (a) {
20 return !a;
21 },
22
23 // function calls
24 startsWith: function (a, b) {
25 return a.length >= b.length &&
26 this.equals(a.slice(0, b.length), b);
27 },
28 endsWith: function (a, b) {
29 return a.length >= b.length &&
30 this.equals(a.slice(a.length - b.length, a.length), b);
31 },
32
33 // algebra
34
35 // exponential
36 pow: function (a, b) {
37 return Math.pow(a, b);
38 },
39
40 // multiplicative
41 mul: function (a, b) {
42 return a * b;
43 },
44 div: function (a, b) {
45 return a / b;
46 },
47 mod: function (a, b) {
48 return a % b;
49 },
50
51 // arithmetic
52 add: function (a, b) {
53 return a + b;
54 },
55 sub: function (a, b) {
56 return a - b;
57 },
58
59 // transitive relations
60 lessThan: function (a, b) {
61 return Semantics.compare(a, b) < 0;
62 },
63 lessThanOrEquals: function (a, b) {
64 return Semantics.compare(a, b) <= 0;
65 },
66 greaterThan: function (a, b) {
67 return Semantics.compare(a, b) > 0;
68 },
69 greaterThanOrEquals: function (a, b) {
70 return Semantics.compare(a, b) >= 0;
71 },
72
73 // equivalence relations
74 equals: function (a, b) {
75 if (a == null || b == null) {
76 return a === b;
77 } else if (a.equals) {
78 return a.equals(b);
79 } else if (b.equals) {
80 return b.equals(a);
81 } else {
82 return a === b;
83 }
84 },
85 notEquals: function (a, b) {
86 return !this.equals(a, b);
87 },
88
89 // logical ('and' and 'or' are evaluators for the short-circuiting)
90
91 xor: function (a, b) {
92 return a !== b;
93 },
94
95 // collection operators
96
97 contains: function (collection, value) { // pertains to strings
98 return collection.indexOf(value) !== -1;
99 },
100 has: function (collection, value) { // pertains to other collections
101 return collection.indexOf(value) !== -1;
102 },
103
104 slice: function (collection, start, stop) {
105 return collection.slice(start, stop);
106 },
107 // TODO rewrite to accept length then from value
108 sliceFrom: function (collection, value, length) {
109 var start = collection.indexOf(value);
110 if (start !== -1) {
111 length = Math.min(collection.length - start, length);
112 return collection.slice(start, start + length);
113 } else {
114 return [];
115 }
116 }
117
118 }
119 },
120
121 evaluators: {
122 value: {
123
124 // properties
125 get: function (evaluateObject, evaluateKey, parents) {
126
127 // construct remaining path
128 var remainingPath = [];
129 parents = parents.parents;
130 while (parents) {
131 if (parents.syntax.type !== 'get')
132 break;
133 remainingPath.push(parents.syntax.args[1].value);
134 parents = parents.parents;
135 }
136 if (remainingPath.length === 0) {
137 remainingPath = null;
138 } else {
139 remainingPath = remainingPath.join(".");
140 }
141
142 return function (value, parameters, visitor) {
143 var object = evaluateObject(value, parameters, visitor);
144 var key = evaluateKey(value, parameters, visitor);
145 var result = (object || empty)[key];
146 if (visitor) {
147 visitor(object, key, result, remainingPath);
148 }
149 return result;
150 };
151 },
152
153 // logical
154 and: function (a, b) {
155 return function (value, parameters) {
156 return a(value, parameters) && b(value, parameters);
157 };
158 },
159 or: function (a, b) {
160 return function (value, parameters) {
161 return a(value, parameters) || b(value, parameters);
162 };
163 },
164
165 // ternary conditional
166 'if': function (guard, consequent, alternate) {
167 return function (value, parameters) {
168 var flag = guard(value, parameters);
169 if (flag === true) {
170 return consequent(value, parameters);
171 } else if (flag === false) {
172 return alternate(value, parameters);
173 } else {
174 throw new Error("Expected true or false, got: " + JSON.stringify(flag));
175 }
176 };
177 },
178
179 it: function (a, b) {
180 return function (value, parameters) {
181 return b(a(value, parameters), parameters);
182 }
183 },
184
185 one: function (a, b) {
186 return function (value, parameters) {
187 var object = a(value, parameters)[0]; // handle other collections
188 return b(object, parameters);
189 };
190 },
191 only: function (a, b) {
192 return function (value, parameters) {
193 var objects = a(value, parameters); // handle other collections
194 if (objects.length !== 1)
195 return false;
196 return b(objects[0], parameters);
197 };
198 },
199 filter: function (a, b) {
200 return function (value, parameters) {
201 return a(value, parameters)
202 .filter(function (object) {
203 return b(object, parameters);
204 });
205 };
206 },
207 every: function (a, b) {
208 return function (value, parameters) {
209 return a(value, parameters)
210 .every(function (object) {
211 return b(object, parameters);
212 });
213 };
214 },
215 some: function (a, b) {
216 return function (value, parameters) {
217 return a(value, parameters)
218 .some(function (object) {
219 return b(object, parameters);
220 });
221 };
222 },
223 map: function (a, b) {
224 return function (value, parameters) {
225