Reorg
This commit is contained in:
parent
d45207342c
commit
cd84d74ec7
12 changed files with 581 additions and 569 deletions
73
src/lang/eval/value.ts
Normal file
73
src/lang/eval/value.ts
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
import { Expr, FieldName, ProductPattern, Tag, VariableName } from "../expr";
|
||||
import { ThrownRuntimeError } from "./error";
|
||||
|
||||
export type Value =
|
||||
| { tag: "string", value: string }
|
||||
| { tag: "number", value: number }
|
||||
| { tag: "tag", tag_name: Tag }
|
||||
| { tag: "tagged", tag_name: Tag, value: Value }
|
||||
| { tag: "tuple", values: Value[] }
|
||||
| { tag: "record", fields: Map<FieldName, Value> }
|
||||
| { tag: "closure", closure: Closure }
|
||||
|
||||
export type ValueTag =
|
||||
| "string"
|
||||
| "number"
|
||||
| "tag"
|
||||
| "tagged"
|
||||
| "tuple"
|
||||
| "record"
|
||||
| "closure"
|
||||
|
||||
// Used as a Stack of frames. Basically a linked list.
|
||||
export type Env =
|
||||
| { tag: "nil" }
|
||||
| { tag: "frame", frame: EnvFrame, parent: Env }
|
||||
|
||||
export type EnvFrame = Map<VariableName, Value>;
|
||||
|
||||
export type Closure = {
|
||||
env: Env,
|
||||
parameters: ProductPattern[],
|
||||
body: Expr,
|
||||
}
|
||||
|
||||
export namespace Value {
|
||||
export const string = (value: string): Value => ({ tag: "string", value });
|
||||
export const number = (value: number): Value => ({ tag: "number", value });
|
||||
export const tag = (tag_name: Tag): Value => ({ tag: "tag", tag_name });
|
||||
export const tagged = (tag_name: Tag, value: Value): Value => ({ tag: "tagged", tag_name, value });
|
||||
export const tuple = (values: Value[]): Value => ({ tag: "tuple", values });
|
||||
export const record = (fields: Map<FieldName, Value>): Value => ({ tag: "record", fields });
|
||||
export const closure = (closure: Closure): Value => ({ tag: "closure", closure });
|
||||
}
|
||||
|
||||
export namespace Env {
|
||||
export function nil(): Env {
|
||||
return { tag: "nil" };
|
||||
}
|
||||
|
||||
export function push_frame(env: Env, frame: EnvFrame): Env {
|
||||
return { tag: "frame", frame, parent: env };
|
||||
}
|
||||
|
||||
// may throw `ThrownRuntimeError`
|
||||
export function lookup(env: Env, var_name: VariableName): Value {
|
||||
let cur = env;
|
||||
while (cur.tag !== "nil") {
|
||||
if (cur.frame.has(var_name)) {
|
||||
return cur.frame.get(var_name)!;
|
||||
}
|
||||
cur = cur.parent;
|
||||
}
|
||||
throw ThrownRuntimeError.error({
|
||||
tag: "VariableLookupFailure",
|
||||
name: var_name,
|
||||
});
|
||||
}
|
||||
|
||||
export function frame_insert_mut(frame: EnvFrame, var_name: VariableName, value: Value) {
|
||||
frame.set(var_name, value);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue