Skip to content

Commit e788d4b

Browse files
committed
[lang0] Env should not be a class
1 parent b8cb93f commit e788d4b

File tree

6 files changed

+29
-37
lines changed

6 files changed

+29
-37
lines changed

TODO.md

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
[lang0] `Env` should not be a class
2-
31
[lang1] 支持 `(import)`
42
[lang1] 支持 `(assert-equal)``(assert-not-equal)`
53
[lang1] 直接用 lang0 的测试

src/lang0/actions/doAp.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { envExtend } from "../env/Env.js"
12
import { evaluate } from "../evaluate/index.js"
23
import * as Neutrals from "../neutral/index.js"
34
import * as Values from "../value/index.js"
@@ -8,7 +9,7 @@ export function doAp(target: Value, arg: Value): Value {
89
case "Fn": {
910
return evaluate(
1011
target.mod,
11-
target.env.extend(target.name, arg),
12+
envExtend(target.env, target.name, arg),
1213
target.ret,
1314
)
1415
}

src/lang0/env/Env.ts

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,19 @@
11
import { type Value } from "../value/index.js"
22

3-
export class Env {
4-
values: Map<string, Value>
3+
export type Env = Map<string, Value>
54

6-
constructor(options: { values: Map<string, Value> }) {
7-
this.values = options.values
8-
}
9-
10-
static init(): Env {
11-
return new Env({
12-
values: new Map(),
13-
})
14-
}
5+
export function envEmpty(): Env {
6+
return new Map()
7+
}
158

16-
get names(): Array<string> {
17-
return Array.from(this.values.keys())
18-
}
9+
export function envNames(env: Env): Array<string> {
10+
return Array.from(env.keys())
11+
}
1912

20-
findValue(name: string): undefined | Value {
21-
return this.values.get(name)
22-
}
13+
export function envFindValue(env: Env, name: string): undefined | Value {
14+
return env.get(name)
15+
}
2316

24-
extend(name: string, value: Value): Env {
25-
return new Env({
26-
...this,
27-
values: new Map([...this.values, [name, value]]),
28-
})
29-
}
17+
export function envExtend(env: Env, name: string, value: Value): Env {
18+
return new Map([...env, [name, value]])
3019
}

src/lang0/evaluate/evaluate.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as Actions from "../actions/index.js"
2-
import { type Env } from "../env/index.js"
2+
import { envExtend, envFindValue, type Env } from "../env/index.js"
33
import { type Exp } from "../exp/index.js"
44
import { modFindValue, type Mod } from "../mod/index.js"
55
import { substitutionBindings } from "../substitution/index.js"
@@ -11,7 +11,7 @@ export function evaluate(mod: Mod, env: Env, exp: Exp): Value {
1111
case "Var": {
1212
let value = undefined
1313

14-
value = env.findValue(exp.name)
14+
value = envFindValue(env, exp.name)
1515
if (value !== undefined) return value
1616

1717
value = modFindValue(mod, exp.name)
@@ -33,7 +33,11 @@ export function evaluate(mod: Mod, env: Env, exp: Exp): Value {
3333
case "Let": {
3434
let newEnv = env
3535
for (const binding of substitutionBindings(exp.substitution)) {
36-
newEnv = newEnv.extend(binding.name, evaluate(mod, env, binding.exp))
36+
newEnv = envExtend(
37+
newEnv,
38+
binding.name,
39+
evaluate(mod, env, binding.exp),
40+
)
3741
}
3842

3943
return evaluate(mod, newEnv, exp.body)
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { type Definition } from "../definition/index.js"
2-
import { Env } from "../env/index.js"
2+
import { envEmpty } from "../env/index.js"
33
import { evaluate } from "../evaluate/index.js"
44
import { type Value } from "../value/index.js"
55

@@ -8,6 +8,6 @@ export function evaluateDefinition(definition: Definition): Value {
88
return definition.cache
99
}
1010

11-
definition.cache = evaluate(definition.mod, Env.init(), definition.exp)
11+
definition.cache = evaluate(definition.mod, envEmpty(), definition.exp)
1212
return definition.cache
1313
}

src/lang0/run/execute.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Env } from "../env/index.js"
1+
import { envEmpty } from "../env/index.js"
22
import { equivalent, EquivalentCtx } from "../equivalent/index.js"
33
import { evaluate } from "../evaluate/index.js"
44
import * as Exps from "../exp/index.js"
@@ -29,7 +29,7 @@ export function execute(mod: Mod, stmt: Stmt): void | string {
2929
}
3030

3131
case "Compute": {
32-
const value = evaluate(mod, Env.init(), stmt.exp)
32+
const value = evaluate(mod, envEmpty(), stmt.exp)
3333
const exp = readback(ReadbackCtx.init(), value)
3434
return formatExp(exp)
3535
}
@@ -74,8 +74,8 @@ export function execute(mod: Mod, stmt: Stmt): void | string {
7474
}
7575

7676
function assertEqual(mod: Mod, left: Exp, right: Exp): void {
77-
const leftValue = evaluate(mod, Env.init(), left)
78-
const rightValue = evaluate(mod, Env.init(), right)
77+
const leftValue = evaluate(mod, envEmpty(), left)
78+
const rightValue = evaluate(mod, envEmpty(), right)
7979
if (!equivalent(EquivalentCtx.init(), leftValue, rightValue)) {
8080
throw new Error(
8181
`((fail assert-equal) ${formatExp(left)} ${formatExp(right)})`,
@@ -84,8 +84,8 @@ function assertEqual(mod: Mod, left: Exp, right: Exp): void {
8484
}
8585

8686
function assertNotEqual(mod: Mod, left: Exp, right: Exp): void {
87-
const leftValue = evaluate(mod, Env.init(), left)
88-
const rightValue = evaluate(mod, Env.init(), right)
87+
const leftValue = evaluate(mod, envEmpty(), left)
88+
const rightValue = evaluate(mod, envEmpty(), right)
8989
if (equivalent(EquivalentCtx.init(), leftValue, rightValue)) {
9090
throw new Error(
9191
`((fail assert-not-equal) ${formatExp(left)} ${formatExp(right)})`,

0 commit comments

Comments
 (0)