-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
212 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import { Rule } from "../rule" | ||
import { Mod } from "./Mod" | ||
import { lookupDefinitionOrFail } from "./lookupDefinitionOrFail" | ||
import { lookupRuleByNodes } from "./lookupRuleByNodes" | ||
|
||
export function lookupRuleByName(mod: Mod, ruleName: string): Rule | undefined { | ||
const [firstName, secondName] = ruleName.split(" ") | ||
|
||
const firstDefinition = lookupDefinitionOrFail(mod, firstName) | ||
const secondDefinition = lookupDefinitionOrFail(mod, secondName) | ||
|
||
return lookupRuleByNodes( | ||
mod, | ||
{ url: firstDefinition.mod.url, name: firstDefinition.name }, | ||
{ url: secondDefinition.mod.url, name: secondDefinition.name }, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,14 @@ | ||
import { Port } from "../port" | ||
import { Rule } from "../rule" | ||
import { Mod } from "./Mod" | ||
import { lookupRule } from "./lookupRule" | ||
import { lookupRuleByNodes } from "./lookupRuleByNodes" | ||
|
||
export function lookupRuleByPorts( | ||
mod: Mod, | ||
first: Port, | ||
second: Port, | ||
): Rule | undefined { | ||
if (first.isPrincipal && second.isPrincipal) { | ||
return lookupRule(mod, first.node, second.node) | ||
return lookupRuleByNodes(mod, first.node, second.node) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,12 @@ | ||
import { PortEntry } from "./Net" | ||
|
||
export function clonePortEntry(entry: PortEntry): PortEntry { | ||
return { ...entry } | ||
return { | ||
...entry, | ||
connection: entry.connection | ||
? { | ||
...entry.connection, | ||
} | ||
: undefined, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,11 @@ | ||
import { PortRecord } from "./Net" | ||
import { clonePortEntry } from "./clonePortEntry" | ||
|
||
export function clonePortRecord(record: PortRecord): PortRecord { | ||
return { ...record } | ||
return Object.fromEntries( | ||
Object.entries(record).map(([name, portEntry]) => [ | ||
name, | ||
clonePortEntry(portEntry), | ||
]), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { Node, formatNode } from "../node" | ||
import { Port } from "../port" | ||
import { Net } from "./Net" | ||
import { createPortFromPortEntry } from "./createPortFromPortEntry" | ||
import { findPortRecordOrFail } from "./findPortRecordOrFail" | ||
|
||
export function findPrincipalPort(net: Net, node: Node): Port { | ||
const portRecord = findPortRecordOrFail(net, node) | ||
for (const portEntry of Object.values(portRecord)) { | ||
if (portEntry.isPrincipal) { | ||
return createPortFromPortEntry(node, portEntry) | ||
} | ||
} | ||
|
||
throw new Error( | ||
[ | ||
`[findPrincipalPort] I expect the node to have a principal port.`, | ||
``, | ||
` node: ${formatNode(node)}`, | ||
].join("\n"), | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { expect, test } from "vitest" | ||
import { Fetcher } from "../../fetcher" | ||
import { Loader } from "../../loader" | ||
import { formatNet } from "../net/formatNet" | ||
import { presentRuleAsNets } from "./presentRuleAsNets" | ||
|
||
test("presentRuleAsNets", async () => { | ||
const text = ` | ||
type Nat -- Type end | ||
node zero | ||
------ | ||
Nat :value! | ||
end | ||
node add1 | ||
Nat :prev | ||
---------- | ||
Nat :value! | ||
end | ||
node add | ||
Nat :target! | ||
Nat :addend | ||
-------- | ||
Nat :return | ||
end | ||
rule zero add | ||
(add)-addend | ||
return-(add) | ||
end | ||
rule add1 add | ||
(add)-addend | ||
(add1)-prev add | ||
add1 return-(add) | ||
end | ||
` | ||
|
||
const fetcher = new Fetcher() | ||
const loader = new Loader({ fetcher }) | ||
const url = new URL("test://presentRuleAsNets") | ||
const mod = await loader.load(url, { text }) | ||
const [initial, final] = presentRuleAsNets(mod, "add1 add") | ||
|
||
expect(formatNet(initial)).toMatchInlineSnapshot(` | ||
"(add1₂)-prev covering-(@input_port_cap₃) | ||
(add1₂)-value!target-(add₃) | ||
(add₃)-addend covering-(@input_port_cap₄) | ||
(add₃)-return covering-(@ouput_port_cap₂)" | ||
`) | ||
|
||
expect(formatNet(final)).toMatchInlineSnapshot(` | ||
"(@input_port_cap₃)-covering!target-(add₄) | ||
(@input_port_cap₄)-covering addend-(add₄) | ||
(@ouput_port_cap₂)-covering!value-(add1₃) | ||
(add₄)-return prev-(add1₃)" | ||
`) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { capNode } from "../cap" | ||
import { compose } from "../compose/compose" | ||
import { connect } from "../connect/connect" | ||
import { createEnv } from "../env/createEnv" | ||
import { Mod, lookupDefinitionOrFail } from "../mod" | ||
import { lookupRuleByName } from "../mod/lookupRuleByName" | ||
import { Net, copyConnectedComponent, createNet } from "../net" | ||
import { deleteNodeEntry } from "../net/deleteNodeEntry" | ||
import { disconnectPort } from "../net/disconnectPort" | ||
import { findPrincipalPort } from "../net/findPrincipalPort" | ||
import { Node } from "../node" | ||
import { createNodeFromDefinition } from "../node/createNodeFromDefinition" | ||
|
||
export function presentRuleAsNets(mod: Mod, ruleName: string): [Net, Net] { | ||
const env = createEnv(mod) | ||
|
||
const rule = lookupRuleByName(mod, ruleName) | ||
if (rule === undefined) { | ||
throw new Error( | ||
[ | ||
`[presentRuleAsNets] I meet undefined rule.`, | ||
``, | ||
` ruleName: ${ruleName}`, | ||
].join("\n"), | ||
) | ||
} | ||
|
||
const [firstName, secondName] = ruleName.split(" ") | ||
|
||
const first = createNodeFromDefinition( | ||
env.net, | ||
lookupDefinitionOrFail(mod, firstName), | ||
) | ||
|
||
const second = createNodeFromDefinition( | ||
env.net, | ||
lookupDefinitionOrFail(mod, secondName), | ||
) | ||
|
||
capNode(mod, env.net, first) | ||
capNode(mod, env.net, second) | ||
|
||
const initial = collectInitialNet(env.net, first, second) | ||
|
||
for (const word of rule.words) { | ||
compose(mod, env, word, { | ||
current: { first, second }, | ||
}) | ||
} | ||
|
||
const final = env.net | ||
|
||
return [initial, final] | ||
} | ||
|
||
function collectInitialNet(net: Net, first: Node, second: Node): Net { | ||
const initial = createNet() | ||
|
||
copyConnectedComponent(net, initial, first) | ||
copyConnectedComponent(net, initial, second) | ||
|
||
const firstPrincipalPort = findPrincipalPort(initial, first) | ||
const firstConnectedPort = disconnectPort(initial, firstPrincipalPort) | ||
if (firstConnectedPort) { | ||
deleteNodeEntry(initial, firstConnectedPort.node) | ||
} | ||
|
||
const secondPrincipalPort = findPrincipalPort(initial, second) | ||
const secondConnectedPort = disconnectPort(initial, secondPrincipalPort) | ||
if (secondConnectedPort) { | ||
deleteNodeEntry(initial, secondConnectedPort.node) | ||
} | ||
|
||
connect(initial, firstPrincipalPort, secondPrincipalPort) | ||
|
||
return initial | ||
} |