Skip to content

Commit

Permalink
[lang0] add an extra pass -- defineMod before executeMod
Browse files Browse the repository at this point in the history
  • Loading branch information
xieyuheng committed Apr 3, 2024
1 parent 00533c4 commit 6c03ce8
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 36 deletions.
1 change: 0 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

> 支持直接递归函数与相互递归函数,不能判断等价的地方就不判断。
[lang0] add an extra pass -- `defineMod` before `executeMod`
[lang0] `equivalent` -- `FnRecursive`
[lang0] `doAp` should not apply a `FnRecursive` when the `arg` is `NotYet`
[lang0] `defineMod` -- check occor to create `FnRecursive` instead of `Fn`
Expand Down
50 changes: 50 additions & 0 deletions src/lang0/run/define.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import * as Exps from "../exp/index.js"
import { formatExp } from "../format/formatExp.js"
import { modDefine, modFind } from "../mod/index.js"
import type { Mod } from "../mod/Mod.js"
import type { Define, Stmt } from "../stmt/Stmt.js"
import { importOne } from "./importOne.js"

export function define(mod: Mod, stmt: Stmt): null {
switch (stmt["@kind"]) {
case "Define": {
assertAllNamesDefined(mod, stmt)

modDefine(mod, stmt.name, {
mod,
name: stmt.name,
exp: stmt.exp,
})

return null
}

case "Import": {
for (const entry of stmt.entries) {
importOne(mod, stmt.path, entry)
}

return null
}

default: {
return null
}
}
}

function assertAllNamesDefined(mod: Mod, stmt: Define): void {
const freeNames = Exps.freeNames(new Set([stmt.name]), stmt.exp)

for (const name of freeNames) {
if (modFind(mod, name) === undefined) {
throw new Error(
[
`I find undefined name: ${name}`,
` defining: ${stmt.name}`,
` body: ${formatExp(stmt.exp)}`,
].join("\n"),
)
}
}
}
15 changes: 15 additions & 0 deletions src/lang0/run/defineMod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { Mod } from "../mod/index.js"
import { define } from "./define.js"

export function defineMod(mod: Mod): boolean {
if (mod.isDefined) {
return false
}

for (const stmt of mod.stmts) {
define(mod, stmt)
}

mod.isDefined = true
return true
}
37 changes: 2 additions & 35 deletions src/lang0/run/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@ import { evaluate } from "../evaluate/index.js"
import * as Exps from "../exp/index.js"
import { type Exp } from "../exp/index.js"
import { formatExp } from "../format/formatExp.js"
import { modDefine, modFind } from "../mod/index.js"
import { modFind } from "../mod/index.js"
import type { Mod } from "../mod/Mod.js"
import { readback, ReadbackCtx } from "../readback/index.js"
import type { Define, Stmt } from "../stmt/Stmt.js"
import { importOne } from "./importOne.js"

export function execute(mod: Mod, stmt: Stmt): null | string {
switch (stmt["@kind"]) {
Expand All @@ -34,23 +33,7 @@ export function execute(mod: Mod, stmt: Stmt): null | string {
return formatExp(exp)
}

case "Define": {
assertAllNamesDefined(mod, stmt)

modDefine(mod, stmt.name, {
mod,
name: stmt.name,
exp: stmt.exp,
})

return null
}

case "Import": {
for (const entry of stmt.entries) {
importOne(mod, stmt.path, entry)
}

default: {
return null
}
}
Expand All @@ -75,19 +58,3 @@ function assertNotEqual(mod: Mod, left: Exp, right: Exp): void {
)
}
}

function assertAllNamesDefined(mod: Mod, stmt: Define): void {
const freeNames = Exps.freeNames(new Set([stmt.name]), stmt.exp)

for (const name of freeNames) {
if (modFind(mod, name) === undefined) {
throw new Error(
[
`I find undefined name: ${name}`,
` defining: ${stmt.name}`,
` body: ${formatExp(stmt.exp)}`,
].join("\n"),
)
}
}
}
2 changes: 2 additions & 0 deletions src/lang0/run/importOne.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { modDefine, modFind, modResolve } from "../mod/index.js"
import type { Mod } from "../mod/Mod.js"
import type { ImportEntry } from "../stmt/Stmt.js"
import { executeMod } from "./executeMod.js"
import { defineMod } from "./defineMod.js"

export function importOne(mod: Mod, path: string, entry: ImportEntry): void {
const url = modResolve(mod, path)
Expand All @@ -14,6 +15,7 @@ export function importOne(mod: Mod, path: string, entry: ImportEntry): void {
throw new Error(`Mod is not loaded: ${path}`)
}

defineMod(found.mod)
executeMod(found.mod)

const { name, rename } = entry
Expand Down
2 changes: 2 additions & 0 deletions src/lang0/run/run.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { executeMod } from "./executeMod.js"
import { defineMod } from "./defineMod.js"
import { load } from "./load.js"

export async function run(url: URL): Promise<void> {
const mod = await load(url, new Map())
defineMod(mod)
executeMod(mod)
}

0 comments on commit 6c03ce8

Please sign in to comment.