123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778 |
- const AST = require('./ast')
- const Env = require('./env')
-
- module.exports = class Evaluator {
- eval(tree, env) {
- this.env = env
-
- let evaluatedTree = []
-
- tree.forEach(node => {
- let evaluatedNode = this.evalNode(node)
-
- if (evaluatedNode) {
- evaluatedTree.push(evaluatedNode)
- }
- })
-
- return evaluatedTree
- }
-
- evalNode(node, env) {
- if (!env) env = this.env
-
- switch (node.constructor) {
- case AST.Boolean:
- case AST.Number:
- case AST.String:
- return node
- case AST.Identifier:
- return env.get(node.name)
- case AST.Definition:
- this.env.set(node.symbol.name, node.value)
- return false
- case AST.LetBinding:
- let innerEnv = new Env(env)
-
- node.bindings.forEach(binding => {
- innerEnv.set(binding.key.name, binding.value)
- })
-
- return this.evalNode(node.body, innerEnv)
- case AST.Conditional:
- let result = this.evalNode(node.condition, env)
-
- if (result.constructor == AST.Boolean && result.value === true) {
- return this.evalNode(node.ifCase, env)
- }
-
- return this.evalNode(node.elseCase, env)
- case AST.Application:
- switch (node.function.constructor) {
- case AST.Identifier:
- return this.evalNode(
- new AST.Application({
- function: env.get(node.function.name),
- args: node.args,
- }),
- )
- case AST.Lambda:
- let innerEnv = new Env(env)
-
- node.function.parameters.forEach((param, index) => {
- innerEnv.set(param.name, node.args[index])
- })
-
- return this.evalNode(node.function.body, innerEnv)
- case Function:
- let args = node.args.map(arg => {
- return this.evalNode(arg)
- })
- args.unshift(this)
- return node.function.call(...args)
- }
- }
-
- return node
- }
- }
|