Skip to content

Commit

Permalink
Refactor for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
bpetermann committed Apr 1, 2024
1 parent 3898112 commit da53007
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 26 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ npm run test
The following command executes the benchmark test contained in the book, the recursive Fibonacci function from above with the input of 40... ugh, it takes long, like really, really long... like not even comparable to the Java implementation in the book.
Making this implementation more efficient is also a future task.

Update : Still slow as hell, but switching from forEach to for loops resulted in a 25% performance improvement in the benchmark test.

```js
npm run benchmark
```
4 changes: 2 additions & 2 deletions benchmark.lox
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ fun fib(n) {
}

var before = clock();
fib(40);
fib(35);
var after = clock();
var time = (after - before) / 1000;

print "🧪 execute fibonacci 40 times in...";
print "🧪 execute fibonacci 35 times in...";
print time + " s";
25 changes: 16 additions & 9 deletions lib/Interpreter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ export class Interpreter
}

private interpretStmt(statements: Array<Statement>): void {
statements.forEach((stmt) => this.execute(stmt));
for (let i = 0; i < statements.length; i++) {
this.execute(statements[i]);
}
}

private interpretExpr(expression: Expression): string {
Expand All @@ -57,7 +59,9 @@ export class Interpreter
try {
this.environment = env;

statements.forEach((stmt) => this.execute(stmt));
for (let i = 0; i < statements.length; i++) {
this.execute(statements[i]);
}
} finally {
this.environment = previous;
}
Expand Down Expand Up @@ -120,7 +124,10 @@ export class Interpreter
const callee = this.evaluate(expr.callee);

const args: Array<NullableObj> = [];
expr.args.forEach((arg) => args.push(this.evaluate(arg)));

for (let i = 0; i < expr.args.length; i++) {
args.push(this.evaluate(expr.args[i]));
}

if (!this.isCallable(callee)) {
throw new RuntimeError(
Expand Down Expand Up @@ -320,15 +327,15 @@ export class Interpreter

const methods: Map<string, LoxFunction> = new Map();

stmt.methods.forEach((method) => {
for (let i = 0; i < stmt.methods.length; i++) {
const func = new LoxFunction(
method.name.lexeme,
method.func,
stmt.methods[i].name.lexeme,
stmt.methods[i].func,
this.environment,
method.name.lexeme === 'init'
stmt.methods[i].name.lexeme === 'init'
);
methods.set(method.name.lexeme, func);
});
methods.set(stmt.methods[i].name.lexeme, func);
}

const klass = new LoxClass(stmt.name.lexeme, superclass, methods);

Expand Down
6 changes: 3 additions & 3 deletions lib/LoxFunction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ export class LoxFunction implements LoxCallable {
call(interpreter: Interpreter, args: NullableObj[]): NullableObj {
const environment = new Environment(this.closure);

this.declaration.params.forEach((p, i) =>
environment.define(p.lexeme, args[i])
);
for (let i = 0; i < this.declaration.params.length; i++) {
environment.define(this.declaration.params[i].lexeme, args[i]);
}

try {
interpreter.executeBlock(this.declaration.body, environment);
Expand Down
31 changes: 19 additions & 12 deletions lib/Resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,25 @@ export class Resolver implements Expr.Visitor<void>, Stmt.Visitor<void> {
constructor(private readonly interpreter: Interpreter) {}

resolve(input: Stmt.Stmt | Expr.Expr | Array<Stmt.Stmt>): void {
Array.isArray(input)
? input.forEach((s) => this.resolve(s))
: input.accept(this);
if (Array.isArray(input)) {
for (let i = 0; i < input.length; i++) {
this.resolve(input[i]);
}
} else {
input.accept(this);
}
}

private resolveFunction(func: Expr.Function, type: FunctionType): void {
const enclosingFunction = this.currentFunction;
this.currentFunction = type;

this.beginScope();
func.params.forEach((param) => {
this.declare(param);
this.define(param);
});
for (let i = 0; i < func.params.length; i++) {
this.declare(func.params[i]);
this.define(func.params[i]);
}

this.resolve(func.body);
this.endScope();
this.currentFunction = enclosingFunction;
Expand Down Expand Up @@ -108,13 +113,13 @@ export class Resolver implements Expr.Visitor<void>, Stmt.Visitor<void> {
this.beginScope();
this.scopes.peek().set('this', true);

stmt.methods.forEach((method) => {
for (let i = 0; i < stmt.methods.length; i++) {
let declaration = FunctionType.METHOD;
if (method.name.lexeme === 'init') {
if (stmt.methods[i].name.lexeme === 'init') {
declaration = FunctionType.INITIALIZER;
}
this.resolveFunction(method.func, declaration);
});
this.resolveFunction(stmt.methods[i].func, declaration);
}

this.endScope();
if (stmt.superclass) this.endScope();
Expand Down Expand Up @@ -200,7 +205,9 @@ export class Resolver implements Expr.Visitor<void>, Stmt.Visitor<void> {
visitCallExpr(expr: Expr.Call): void {
this.resolve(expr.callee);

expr.args.forEach((arg) => this.resolve(arg));
for (let i = 0; i < expr.args.length; i++) {
this.resolve(expr.args[i]);
}
}

visitGetExpr(expr: Expr.Get): void {
Expand Down

0 comments on commit da53007

Please sign in to comment.