Skip to content

Commit

Permalink
Added methods and this keyword
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel Berezin committed Jun 8, 2019
1 parent f2459a6 commit 0b7e72c
Show file tree
Hide file tree
Showing 10 changed files with 101 additions and 22 deletions.
2 changes: 1 addition & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ module.exports = {
},
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "commonjs"
"sourceType": "module"
},
"rules": {
"no-console": 0
Expand Down
4 changes: 2 additions & 2 deletions cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ const processOptions = args =>
.map(arg => {
const match = optionRegex.exec(arg)
if (match) {
const [_, option, value] = match
const [, option, value] = match
if (!value) {
options[option] = !options[option]
} else {
Expand All @@ -105,4 +105,4 @@ const main = argv => {
}
}

return main(process.argv)
main(process.argv)
10 changes: 5 additions & 5 deletions docs/browser.e9f8be96.js

Large diffs are not rendered by default.

20 changes: 13 additions & 7 deletions errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ class LoxError {
}
}

class RuntimeError extends LoxError {
constructor(msg, token) {
super(
`${nullable(token.lexeme && `at "${token.lexeme}": `)}${msg}`,
token.startCoordinates,
token.endCoordinates
)
}
}

class ReturnError {
constructor(val) {
this.value = val
Expand All @@ -33,12 +43,7 @@ const parseError = (msg, token) => {
}
}

const runtimeError = (msg, token) =>
new LoxError(
`${nullable(token.lexeme && `at "${token.lexeme}": `)}${msg}`,
token.startCoordinates,
token.endCoordinates
)
const runtimeError = (msg, token) => new RuntimeError(msg, token)

const formatLoxError = (e, code) => {
if (e instanceof LoxError) {
Expand All @@ -55,8 +60,9 @@ const formatLoxError = (e, code) => {
const postErrorSection = code.substring(e.endCoordinates.index, postErrorStart)

// Print Critical Code
const errorType = e instanceof RuntimeError ? 'Runtime Error' : 'Parse Error'
return {
oneLiner: `Parse Error: ${e.toString()} at ${e.endCoordinates.line}:${e.endCoordinates.col +
oneLiner: `${errorType}: ${e.toString()} at ${e.endCoordinates.line}:${e.endCoordinates.col +
1}`,
preErrorSection,
errorSection,
Expand Down
3 changes: 3 additions & 0 deletions examples/classExample.lox
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
class Lox {
breakfast() {
print "Toast";
this.hello = "toast";
return this.hello;
}
}

Expand All @@ -16,6 +18,7 @@ var loxInstance = Lox();

loxInstance.category = "Breakfast";
print loxInstance.category;
print loxInstance.breakfast();

print Lox();

Expand Down
42 changes: 42 additions & 0 deletions examples/linkedList.lox
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Linked List via Classes
class Link {}

fun newLink (value, next) {
var link = Link();
link.value = value;
link.next = next;
link.append
return link;
}

var ll = newLink(1, newLink(2, newLink(3, nil)));

fun traverse(n, fn) {
fn(n);
if (n.next != nil) {
return traverse(n.next, fn);
}
return n;
}

fun printList(list) {
fun printNode (n) {
print n.value;
}
traverse(list, printNode);
}

fun append(list, newNode) {
fun walk (n) {}
var end = traverse(list, walk);
end.next = newNode;
return end;
}

print "list:";
printList(ll);

append(ll, newLink(40, nil));

print "list:";
printList(ll);
30 changes: 24 additions & 6 deletions interpreter.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
Get,
Set,
Var,
This,
Grouping,
Return,
While,
Expand Down Expand Up @@ -57,15 +58,22 @@ class LoxCallable {
return null
}

bind(instance) {
const env = new Environment(this.closure)
env.set({ lexeme: 'this' }, instance)
return new LoxCallable(this.declaration, env)
}

toString() {
return `<${this.declaration.name.lexeme}()>`
}
}

class LoxClass extends LoxCallable {
constructor(name) {
constructor(name, methods) {
super()
this.name = name
this.methods = methods
}

call() {
Expand All @@ -85,11 +93,11 @@ class LoxInstance {

get(token) {
const name = token.lexeme
if (this.fields.has(name)) {
return this.fields.get(name)
}
if (this.fields.has(name)) return this.fields.get(name)

throw runtimeError(`Undefined property ${name}`, token)
if (this.klass.methods.has(name)) return this.klass.methods.get(name).bind(this)

throw runtimeError(`Undefined property "${name}"`, token)
// return null
}

Expand Down Expand Up @@ -126,6 +134,7 @@ class Interpreter {
else if (expr instanceof Class) return this.visitClass(expr)
else if (expr instanceof Get) return this.visitGet(expr)
else if (expr instanceof Set) return this.visitSet(expr)
else if (expr instanceof This) return this.visitThis(expr)
else if (expr instanceof Logical) return this.visitLogical(expr)
else if (expr instanceof Call) return this.visitCall(expr)
else if (expr instanceof While) return this.visitWhile(expr)
Expand Down Expand Up @@ -200,7 +209,12 @@ class Interpreter {
visitClass(stmt) {
// We set the name before initializing it so classes can self-reference
this.environment.set(stmt.name, null)
const klass = new LoxClass(stmt.name.lexeme)
const methods = new Map()
for (let method of stmt.methods) {
const fun = new LoxCallable(method, this.environment)
methods.set(method.name.lexeme, fun)
}
const klass = new LoxClass(stmt.name.lexeme, methods)
this.environment.assign(stmt.name, klass)
return null
}
Expand All @@ -225,6 +239,10 @@ class Interpreter {
return object.set(expr.name, val)
}

visitThis(expr) {
return this.environment.get({ name: expr.keyword })
}

visitBlock(expr) {
this.interpretBlock(expr.statements, new Environment(this.environment))
return null
Expand Down
2 changes: 1 addition & 1 deletion loxfmt.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,4 @@ const main = argv => {
}
}

return main(process.argv)
main(process.argv)
3 changes: 3 additions & 0 deletions parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const {
Class,
Get,
Set,
This,
Grouping,
Return,
LoxFunction,
Expand Down Expand Up @@ -262,6 +263,7 @@ class Parser {
call() {
let expr = this.primary()
while (true) {
//eslint-disable-line
if (this.match(token.LEFT_PAREN)) {
expr = this.finishCall(expr)
} else if (this.match(token.DOT)) {
Expand Down Expand Up @@ -291,6 +293,7 @@ class Parser {
if (this.match(token.TRUE)) return new Literal(true)
if (this.match(token.NIL)) return new Literal(null)
if (this.match(token.NUMBER, token.STRING)) return new Literal(this.previous().literal)
if (this.match(token.THIS)) return new This(this.previous())
if (this.match(token.IDENTIFIER)) return new Var(this.previous())

if (this.match(token.LEFT_PAREN)) {
Expand Down
7 changes: 7 additions & 0 deletions types.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ class Return {
}
}

class This {
constructor(keyword) {
this.keyword = keyword
}
}

class Class {
constructor(name, methods) {
this.name = name
Expand Down Expand Up @@ -137,6 +143,7 @@ module.exports = {
Literal,
Return,
Logical,
This,
LoxFunction,
Grouping,
Condition,
Expand Down

0 comments on commit 0b7e72c

Please sign in to comment.