const AST = require('./ast') const Env = require('./env') module.exports = class Compiler { constructor(env = null) { this.result = '' if (env) { this.env = env } else { this.env = new Env() } } compile(tree) { tree.forEach(node => { this.result += this.compileNode(node) }) return this.result } compileNode(node) { switch (node.constructor) { case AST.Number: case AST.String: return node.value case AST.Identifier: return this.compileNode(this.env.get(node.name)) case AST.Application: if (node.function.constructor === AST.Identifier) { let f = this.env.get(node.function.name) return f(...node.args.map(arg => this.compileNode(arg))) } else if (node.function.constructor === AST.Lambda) { let env = new Env(this.env) node.function.parameters.forEach((param, index) => { env.set(param.name, node.args[index]) }) let compiler = new Compiler(env) return compiler.compileNode(node.function.body) } return '' } } }