diff --git a/environment.js b/environment.js index 833aaf4..8fd06ce 100644 --- a/environment.js +++ b/environment.js @@ -26,6 +26,10 @@ class Environment { this.map.set(name, typeof func === 'function' ? { call: func } : func) } + setBuiltinClass(name, klass) { + this.map.set(name, JSClassToLoxClass(klass)) + } + assign(token, value) { if (!this.map.has(token.lexeme)) { if (this.enclosing) return this.enclosing.assign(token, value) @@ -36,3 +40,24 @@ class Environment { } module.exports = Environment + +// We do all this below the export to avoid a circular dependancy +const { LoxClass } = require('./interpreter') +class FakeInstance { + constructor(call) { + this.call = call + } + bind(instance) { + this.call = this.call.bind(instance) + return this + } +} + +const JSClassToLoxClass = klass => { + const methodNames = Object.getOwnPropertyNames(klass.prototype) + const methods = new Map(methodNames.map(name => [name, new FakeInstance(klass.prototype[name])])) + // TODO: Throw an error if user passes in a constructor + if (methods.has('constructor')) methods.delete('constructor') + const newKlass = new LoxClass(klass.name, methods) + return newKlass +}