Software zum Installieren eines Smart-Mirror Frameworks , zum Nutzen von hochschulrelevanten Informationen, auf einem Raspberry-Pi.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

transformer.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. 'use strict';
  2. var nodes = require('./nodes');
  3. var lib = require('./lib');
  4. var sym = 0;
  5. function gensym() {
  6. return 'hole_' + sym++;
  7. } // copy-on-write version of map
  8. function mapCOW(arr, func) {
  9. var res = null;
  10. for (var i = 0; i < arr.length; i++) {
  11. var item = func(arr[i]);
  12. if (item !== arr[i]) {
  13. if (!res) {
  14. res = arr.slice();
  15. }
  16. res[i] = item;
  17. }
  18. }
  19. return res || arr;
  20. }
  21. function walk(ast, func, depthFirst) {
  22. if (!(ast instanceof nodes.Node)) {
  23. return ast;
  24. }
  25. if (!depthFirst) {
  26. var astT = func(ast);
  27. if (astT && astT !== ast) {
  28. return astT;
  29. }
  30. }
  31. if (ast instanceof nodes.NodeList) {
  32. var children = mapCOW(ast.children, function (node) {
  33. return walk(node, func, depthFirst);
  34. });
  35. if (children !== ast.children) {
  36. ast = new nodes[ast.typename](ast.lineno, ast.colno, children);
  37. }
  38. } else if (ast instanceof nodes.CallExtension) {
  39. var args = walk(ast.args, func, depthFirst);
  40. var contentArgs = mapCOW(ast.contentArgs, function (node) {
  41. return walk(node, func, depthFirst);
  42. });
  43. if (args !== ast.args || contentArgs !== ast.contentArgs) {
  44. ast = new nodes[ast.typename](ast.extName, ast.prop, args, contentArgs);
  45. }
  46. } else {
  47. var props = ast.fields.map(function (field) {
  48. return ast[field];
  49. });
  50. var propsT = mapCOW(props, function (prop) {
  51. return walk(prop, func, depthFirst);
  52. });
  53. if (propsT !== props) {
  54. ast = new nodes[ast.typename](ast.lineno, ast.colno);
  55. propsT.forEach(function (prop, i) {
  56. ast[ast.fields[i]] = prop;
  57. });
  58. }
  59. }
  60. return depthFirst ? func(ast) || ast : ast;
  61. }
  62. function depthWalk(ast, func) {
  63. return walk(ast, func, true);
  64. }
  65. function _liftFilters(node, asyncFilters, prop) {
  66. var children = [];
  67. var walked = depthWalk(prop ? node[prop] : node, function (descNode) {
  68. var symbol;
  69. if (descNode instanceof nodes.Block) {
  70. return descNode;
  71. } else if (descNode instanceof nodes.Filter && lib.indexOf(asyncFilters, descNode.name.value) !== -1 || descNode instanceof nodes.CallExtensionAsync) {
  72. symbol = new nodes.Symbol(descNode.lineno, descNode.colno, gensym());
  73. children.push(new nodes.FilterAsync(descNode.lineno, descNode.colno, descNode.name, descNode.args, symbol));
  74. }
  75. return symbol;
  76. });
  77. if (prop) {
  78. node[prop] = walked;
  79. } else {
  80. node = walked;
  81. }
  82. if (children.length) {
  83. children.push(node);
  84. return new nodes.NodeList(node.lineno, node.colno, children);
  85. } else {
  86. return node;
  87. }
  88. }
  89. function liftFilters(ast, asyncFilters) {
  90. return depthWalk(ast, function (node) {
  91. if (node instanceof nodes.Output) {
  92. return _liftFilters(node, asyncFilters);
  93. } else if (node instanceof nodes.Set) {
  94. return _liftFilters(node, asyncFilters, 'value');
  95. } else if (node instanceof nodes.For) {
  96. return _liftFilters(node, asyncFilters, 'arr');
  97. } else if (node instanceof nodes.If) {
  98. return _liftFilters(node, asyncFilters, 'cond');
  99. } else if (node instanceof nodes.CallExtension) {
  100. return _liftFilters(node, asyncFilters, 'args');
  101. } else {
  102. return undefined;
  103. }
  104. });
  105. }
  106. function liftSuper(ast) {
  107. return walk(ast, function (blockNode) {
  108. if (!(blockNode instanceof nodes.Block)) {
  109. return;
  110. }
  111. var hasSuper = false;
  112. var symbol = gensym();
  113. blockNode.body = walk(blockNode.body, function (node) {
  114. // eslint-disable-line consistent-return
  115. if (node instanceof nodes.FunCall && node.name.value === 'super') {
  116. hasSuper = true;
  117. return new nodes.Symbol(node.lineno, node.colno, symbol);
  118. }
  119. });
  120. if (hasSuper) {
  121. blockNode.body.children.unshift(new nodes.Super(0, 0, blockNode.name, new nodes.Symbol(0, 0, symbol)));
  122. }
  123. });
  124. }
  125. function convertStatements(ast) {
  126. return depthWalk(ast, function (node) {
  127. if (!(node instanceof nodes.If) && !(node instanceof nodes.For)) {
  128. return undefined;
  129. }
  130. var async = false;
  131. walk(node, function (child) {
  132. if (child instanceof nodes.FilterAsync || child instanceof nodes.IfAsync || child instanceof nodes.AsyncEach || child instanceof nodes.AsyncAll || child instanceof nodes.CallExtensionAsync) {
  133. async = true; // Stop iterating by returning the node
  134. return child;
  135. }
  136. return undefined;
  137. });
  138. if (async) {
  139. if (node instanceof nodes.If) {
  140. return new nodes.IfAsync(node.lineno, node.colno, node.cond, node.body, node.else_);
  141. } else if (node instanceof nodes.For && !(node instanceof nodes.AsyncAll)) {
  142. return new nodes.AsyncEach(node.lineno, node.colno, node.arr, node.name, node.body, node.else_);
  143. }
  144. }
  145. return undefined;
  146. });
  147. }
  148. function cps(ast, asyncFilters) {
  149. return convertStatements(liftSuper(liftFilters(ast, asyncFilters)));
  150. }
  151. function transform(ast, asyncFilters) {
  152. return cps(ast, asyncFilters || []);
  153. } // var parser = require('./parser');
  154. // var src = 'hello {% foo %}{% endfoo %} end';
  155. // var ast = transform(parser.parse(src, [new FooExtension()]), ['bar']);
  156. // nodes.printNodes(ast);
  157. module.exports = {
  158. transform: transform
  159. };