Skip to content

Commit

Permalink
evaluate call expression
Browse files Browse the repository at this point in the history
  • Loading branch information
wcho21 committed Dec 21, 2023
1 parent fcc617d commit 077efc3
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 7 deletions.
21 changes: 21 additions & 0 deletions src/evaluator/environment/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,24 @@ describe("get()", () => {
expect(value).toBe(null);
});
});

describe("linked environment", () => {
it("set super environment and get via sub environment", () => {
const superEnv = new Environment();
superEnv.set("foo", 42);
const subEnv = new Environment(superEnv);

const value = subEnv.get("foo");

expect(value).toBe(42);
});

it("get null if not found even in super environment", () => {
const superEnv = new Environment();
const subEnv = new Environment(superEnv);

const value = subEnv.get("foo");

expect(value).toBe(null);
});
});
16 changes: 14 additions & 2 deletions src/evaluator/environment/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,26 @@ export interface EnvironmentType {
}

export default class Environment implements EnvironmentType {
private readonly superEnvironment: Environment | null;
private readonly table: Map<string, any>;

constructor() {
constructor(superEnvironment: Environment | null = null) {
this.superEnvironment = superEnvironment;
this.table = new Map<string, any>;
}

get(name: string): unknown {
return this.table.get(name) ?? null;
// return if found in current environment
const fetched = this.table.get(name);
if (fetched !== undefined) {
return fetched;
}

// return value in super environment
if (this.superEnvironment === null) {
return null;
}
return this.superEnvironment.get(name);
}

set(name: string, value: any): unknown {
Expand Down
20 changes: 20 additions & 0 deletions src/evaluator/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,24 @@ describe("evaluate()", () => {
expect(evaluated).toHaveProperty("environment");
});
});

describe("call expressions", () => {
const cases = [
{
name: "function call with function literal",
input: "ν•¨μˆ˜(λ°”λ‚˜λ‚˜) { λ°”λ‚˜λ‚˜ + 1 }(42)"
},
];

it.each(cases)("evaluate $name", ({ input }) => {
const lexer = new Lexer(input);
const parser = new Parser(lexer);
const program = parser.parseProgram();
const evaluator = new Evaluator();
const environment = new Environment();
const evaluated = evaluator.evaluate(program, environment);

expect(evaluated).toBe(43);
});
});
});
34 changes: 31 additions & 3 deletions src/evaluator/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Program, Block, BranchStatement, Node } from "../parser";
import type { Program, Block, BranchStatement, Node, Expression } from "../parser";
import Environment from "./environment";

// TODO: fix any return type to specific ones (by implement value system)
Expand Down Expand Up @@ -153,6 +153,14 @@ export default class Evaluator {
const body = node.body;
return { parameters, body, environment: env };
}
if (node.type === "call") {
const functionToCall = this.evaluate(node.functionToCall, env);

const callArguments = this.parseCallArguments(node.callArguments, env);

const value = this.evaluateFunctionCall(functionToCall, callArguments);
return value;
}
if (node.type === "assignment") {
const varValue = this.evaluate(node.right, env);

Expand All @@ -176,8 +184,28 @@ export default class Evaluator {
return value;
}

// TODO: uncomment
// const exhaustiveCheck: never = node;
const exhaustiveCheck: never = node;
}

private parseCallArguments(callArguments: Expression[], env: Environment): any[] {
const values = [];
for (const arg of callArguments) {
const value = this.evaluate(arg, env);
values.push(value);
}
return values;
}

private evaluateFunctionCall(functionToCall: any, callArguments: any[]): any {
const functionEnv = new Environment(functionToCall.environment);
for (let i = 0; i < functionToCall.parameters.length; ++i) {
const name = functionToCall.parameters[i].value;
const value = callArguments[i];
functionEnv.set(name, value);
}

const value = this.evaluate(functionToCall.body, functionEnv);
return value;
}
}

Expand Down
8 changes: 6 additions & 2 deletions src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ it("execute λ§Œμ•½ 1 != 1 { 2 } μ•„λ‹ˆλ©΄ { 3 }", () => {
expect(execute("λ§Œμ•½ 1 != 1 { 2 } μ•„λ‹ˆλ©΄ { 3 }")).toBe("3");
});

it("execute assignment", () => {
expect(execute("λ³€μˆ˜1 = 4 λ³€μˆ˜2 = 9 (λ³€μˆ˜2 - λ³€μˆ˜1) * λ³€μˆ˜1")).toBe("20");
it("execute single assignment", () => {
expect(execute("λ³€μˆ˜1 = 4 λ³€μˆ˜1")).toBe("4");
});

it("execute assignment and calculation", () => {
expect(execute("λ³€μˆ˜1 = 4 λ³€μˆ˜2 = 9 ((λ³€μˆ˜1 - λ³€μˆ˜2) * λ³€μˆ˜1)")).toBe("-20");
});

0 comments on commit 077efc3

Please sign in to comment.