A templating language that looks like Lisp and compiles to HTML
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.

evaluator.js 1.5KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. const AST = require('./ast')
  2. const Env = require('./env')
  3. module.exports = class Evaluator {
  4. eval(tree, env) {
  5. this.env = env
  6. let evaluatedTree = []
  7. tree.forEach(node => {
  8. let evaluatedNode = this.evalNode(node)
  9. if (evaluatedNode) {
  10. evaluatedTree.push(evaluatedNode)
  11. }
  12. })
  13. return evaluatedTree
  14. }
  15. evalNode(node, env) {
  16. if (!env) env = this.env
  17. switch (node.constructor) {
  18. case AST.Boolean:
  19. case AST.Number:
  20. case AST.String:
  21. return node
  22. case AST.Identifier:
  23. return env.get(node.name)
  24. case AST.Definition:
  25. this.env.set(node.symbol.name, node.value)
  26. return false
  27. case AST.Application:
  28. switch (node.function.constructor) {
  29. case AST.Identifier:
  30. return this.evalNode(
  31. new AST.Application({
  32. function: env.get(node.function.name),
  33. args: node.args,
  34. }),
  35. )
  36. case AST.Lambda:
  37. let innerEnv = new Env(env)
  38. node.function.parameters.forEach((param, index) => {
  39. innerEnv.set(param.name, node.args[index])
  40. })
  41. return this.evalNode(node.function.body, innerEnv)
  42. case Function:
  43. let args = node.args.map(arg => {
  44. return this.evalNode(arg)
  45. })
  46. args.unshift(this)
  47. return node.function.call(...args)
  48. }
  49. }
  50. return node
  51. }
  52. }