PageRenderTime 46ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/node_modules/montage/node_modules/frb/compile-evaluator.js

https://github.com/huan-nba/Test
JavaScript | 310 lines | 263 code | 46 blank | 1 comment | 18 complexity | 1ea2fd74a8e1a75c761e8933fa3b95b0 MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-SA-4.0, 0BSD
  1. var Object = require("collections/shim-object");
  2. var Map = require("collections/map");
  3. var SortedSet = require("collections/sorted-set");
  4. var Operators = require("./operators");
  5. var Scope = require("./scope");
  6. module.exports = compile;
  7. function compile(syntax) {
  8. return compile.semantics.compile(syntax);
  9. }
  10. var compilers = {
  11. literal: function (syntax) {
  12. return function () {
  13. return syntax.value;
  14. };
  15. },
  16. value: function (syntax) {
  17. return function (scope) {
  18. return scope.value;
  19. };
  20. },
  21. parameters: function (syntax) {
  22. return function (scope) {
  23. return scope.parameters;
  24. };
  25. },
  26. element: function (syntax) {
  27. return function (scope) {
  28. return scope.document.getElementById(syntax.id);
  29. };
  30. },
  31. component: function (syntax) {
  32. return function (scope) {
  33. return scope.components.getObjectByLabel(syntax.label);
  34. };
  35. },
  36. tuple: function (syntax) {
  37. var argEvaluators = syntax.args.map(this.compile, this);
  38. return function (scope) {
  39. return argEvaluators.map(function (evaluateArg) {
  40. return evaluateArg(scope);
  41. });
  42. };
  43. },
  44. record: function (syntax) {
  45. var args = syntax.args;
  46. var argEvaluators = {};
  47. for (var name in args) {
  48. argEvaluators[name] = this.compile(args[name]);
  49. }
  50. return function (scope) {
  51. var object = {};
  52. for (var name in argEvaluators) {
  53. object[name] = argEvaluators[name](scope);
  54. }
  55. return object;
  56. };
  57. }
  58. };
  59. var argCompilers = {
  60. mapBlock: function (evaluateCollection, evaluateRelation) {
  61. return function (scope) {
  62. return evaluateCollection(scope)
  63. .map(function (value) {
  64. return evaluateRelation(scope.nest(value));
  65. });
  66. };
  67. },
  68. filterBlock: function (evaluateCollection, evaluatePredicate) {
  69. return function (scope) {
  70. return evaluateCollection(scope)
  71. .filter(function (value) {
  72. return evaluatePredicate(scope.nest(value));
  73. });
  74. };
  75. },
  76. someBlock: function (evaluateCollection, evaluatePredicate) {
  77. return function (scope) {
  78. return evaluateCollection(scope)
  79. .some(function (value) {
  80. return evaluatePredicate(scope.nest(value));
  81. });
  82. };
  83. },
  84. everyBlock: function (evaluateCollection, evaluatePredicate) {
  85. return function (scope) {
  86. return evaluateCollection(scope)
  87. .every(function (value) {
  88. return evaluatePredicate(scope.nest(value));
  89. });
  90. };
  91. },
  92. sortedBlock: function (evaluateCollection, evaluateRelation) {
  93. return function (scope) {
  94. return evaluateCollection(scope)
  95. .sorted(Function.by(function (value) {
  96. return evaluateRelation(scope.nest(value));
  97. }));
  98. };
  99. },
  100. sortedSetBlock: function (evaluateCollection, evaluateRelation) {
  101. return function (scope) {
  102. function map(x) {
  103. return evaluateRelation(scope.nest(x));
  104. }
  105. function contentCompare(x, y) {
  106. return Object.compare(map(x), map(y));
  107. }
  108. function contentEquals(x, y) {
  109. return Object.equals(map(x), map(y));
  110. }
  111. return new SortedSet(
  112. evaluateCollection(scope),
  113. contentEquals,
  114. contentCompare
  115. );
  116. };
  117. },
  118. groupBlock: function (evaluateCollection, evaluateRelation) {
  119. return function (scope) {
  120. return evaluateCollection(scope)
  121. .group(function (value) {
  122. return evaluateRelation(scope.nest(value));
  123. });
  124. };
  125. },
  126. groupMapBlock: function (evaluateCollection, evaluateRelation) {
  127. return function (scope) {
  128. return new Map(evaluateCollection(scope)
  129. .group(function (value) {
  130. return evaluateRelation(scope.nest(value));
  131. }));
  132. };
  133. },
  134. minBlock: function (evaluateCollection, evaluateRelation) {
  135. return function (scope) {
  136. return evaluateCollection(scope)
  137. .min(Function.by(function (value) {
  138. return evaluateRelation(scope.nest(value));
  139. }))
  140. };
  141. },
  142. maxBlock: function (evaluateCollection, evaluateRelation) {
  143. return function (scope) {
  144. return evaluateCollection(scope)
  145. .max(Function.by(function (value) {
  146. return evaluateRelation(scope.nest(value));
  147. }))
  148. };
  149. },
  150. parent: function (evaluateExpression) {
  151. return function (scope) {
  152. return evaluateExpression(scope.parent);
  153. };
  154. },
  155. "with": function (evaluateContext, evaluateExpression) {
  156. return function (scope) {
  157. return evaluateExpression(scope.nest(evaluateContext(scope)));
  158. };
  159. },
  160. "if": function (evaluateCondition, evaluateConsequent, evaluateAlternate) {
  161. return function (scope) {
  162. var condition = evaluateCondition(scope);
  163. if (condition == null) return;
  164. if (condition) {
  165. return evaluateConsequent(scope);
  166. } else {
  167. return evaluateAlternate(scope);
  168. }
  169. }
  170. },
  171. not: function (evaluateValue) {
  172. return function (scope) {
  173. return !evaluateValue(scope);
  174. };
  175. },
  176. and: function (evaluateLeft, evaluateRight) {
  177. return function (scope) {
  178. return evaluateLeft(scope) && evaluateRight(scope);
  179. };
  180. },
  181. or: function (evaluateLeft, evaluateRight) {
  182. return function (scope) {
  183. return evaluateLeft(scope) || evaluateRight(scope);
  184. };
  185. },
  186. "default": function (evaluateLeft, evaluateRight) {
  187. return function (scope) {
  188. var result = evaluateLeft(scope);
  189. if (result == null) { // implies "iff === null or undefined"
  190. result = evaluateRight(scope);
  191. }
  192. return result;
  193. }
  194. },
  195. defined: function (evaluate) {
  196. return function (scope) {
  197. var value = evaluate(scope);
  198. return value != null; // implies exactly !== null or undefined
  199. };
  200. },
  201. // TODO rename to evaluate
  202. path: function (evaluateObject, evaluatePath) {
  203. return function (scope) {
  204. var value = evaluateObject(scope);
  205. var path = evaluatePath(scope);
  206. var parse = require("./parse");
  207. try {
  208. var syntax = parse(path);
  209. var evaluate = compile(syntax);
  210. return evaluate(scope.nest(value));
  211. } catch (exception) {
  212. }
  213. }
  214. }
  215. };
  216. var operators = Object.clone(Operators, 1);
  217. Object.addEach(operators, {
  218. property: function (object, key) {
  219. return object[key];
  220. },
  221. get: function (collection, key) {
  222. return collection.get(key);
  223. },
  224. mapContent: Function.identity,
  225. rangeContent: Function.identity,
  226. view: function (collection, start, length) {
  227. return collection.slice(start, start + length);
  228. }
  229. });
  230. var semantics = compile.semantics = {
  231. compilers: compilers,
  232. argCompilers: argCompilers,
  233. operators: operators,
  234. compile: function (syntax) {
  235. var compilers = this.compilers;
  236. var argCompilers = this.argCompilers;
  237. var operators = this.operators;
  238. if (compilers.hasOwnProperty(syntax.type)) {
  239. return compilers[syntax.type].call(this, syntax);
  240. } else if (argCompilers.hasOwnProperty(syntax.type)) {
  241. var argEvaluators = syntax.args.map(this.compile, this);
  242. return argCompilers[syntax.type].apply(null, argEvaluators);
  243. } else {
  244. if (!operators.hasOwnProperty(syntax.type)) {
  245. operators[syntax.type] = function (object) {
  246. var args = Array.prototype.slice.call(arguments, 1);
  247. if (!object[syntax.type])
  248. throw new TypeError("Can't call " + JSON.stringify(syntax.type) + " of " + object);
  249. return object[syntax.type].apply(object, args);
  250. };
  251. }
  252. var operator = operators[syntax.type];
  253. var argEvaluators = syntax.args.map(this.compile, this);
  254. return function (scope) {
  255. var args = argEvaluators.map(function (evaluateArg) {
  256. return evaluateArg(scope);
  257. });
  258. if (!args.every(Operators.defined))
  259. return;
  260. return operator.apply(null, args);
  261. };
  262. }
  263. }
  264. };