diff --git a/TODO.md b/TODO.md index dd67a3d6..e84103eb 100644 --- a/TODO.md +++ b/TODO.md @@ -1,15 +1,17 @@ # half-edge -[half-edge] `PortEntry` -- `connection` through `HalfEdge` +[half-edge] rename `net.activeEdges` to `net.activePortPairs` [half-edge] `Edge` has two `HalfEdge`s -[half-edge] `HalfEdge` should be a kind of `Value` +[half-edge] `HalfEdge` should be a kind of `Value` -- `Port` should quit being a `Value` [half-edge] avoid using `closeAllFreePorts` [half-edge] `@edge` as a builtin to create two `HalfEdge`s +[half-edge] refactor + # docs [docs] add mimor to inet docs diff --git a/src/lang/builtins/connect.ts b/src/lang/builtins/connect.ts index 409f6009..9ae96d74 100644 --- a/src/lang/builtins/connect.ts +++ b/src/lang/builtins/connect.ts @@ -1,5 +1,5 @@ import { ComposeOptions } from "../compose/compose" -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { Env } from "../env" import { unifyTypes } from "../unify/unifyTypes" import { formatValue } from "../value/formatValue" @@ -46,7 +46,7 @@ export function compose(env: Env, options: ComposeOptions): void { ) } - connect(env.net, first, second) + connectPorts(env.net, first, second) if (options.checking) { unifyTypes(env, options.checking.substitution, first.t, second.t) } diff --git a/src/lang/cap/capInputPort.ts b/src/lang/cap/capInputPort.ts index 2d467a1f..c2ed9f8a 100644 --- a/src/lang/cap/capInputPort.ts +++ b/src/lang/cap/capInputPort.ts @@ -1,4 +1,4 @@ -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { Mod } from "../mod" import { Net } from "../net" import { addNode } from "../net/addNode" @@ -23,6 +23,6 @@ export function capInputPort(mod: Mod, net: Net, port: Port): Port { } const capPort = findOutputPorts(net, node)[0] - connect(net, port, capPort) + connectPorts(net, port, capPort) return capPort } diff --git a/src/lang/cap/capOutputPort.ts b/src/lang/cap/capOutputPort.ts index e43c9be8..20f03ba4 100644 --- a/src/lang/cap/capOutputPort.ts +++ b/src/lang/cap/capOutputPort.ts @@ -1,4 +1,4 @@ -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { Mod } from "../mod" import { Net } from "../net" import { addNode } from "../net/addNode" @@ -23,6 +23,6 @@ export function capOutputPort(mod: Mod, net: Net, port: Port): Port { } const capPort = findInputPorts(net, node)[0] - connect(net, port, capPort) + connectPorts(net, port, capPort) return capPort } diff --git a/src/lang/check/checkPortSigns.ts b/src/lang/check/checkPortSigns.ts index 606913de..fb8ac8bd 100644 --- a/src/lang/check/checkPortSigns.ts +++ b/src/lang/check/checkPortSigns.ts @@ -6,7 +6,7 @@ export function checkPortSigns(net: Net, first: Port, second: Port): void { if (first.sign === 1 && second.sign === 1) { throw new Error( [ - `[checkSigns] I expect the two ports to have opposite signs,`, + `[checkPortSigns] I expect the two ports to have opposite signs,`, ` but they all have positive sign.`, ``, ` first port: ${formatPort(net, first)}`, @@ -18,7 +18,7 @@ export function checkPortSigns(net: Net, first: Port, second: Port): void { if (first.sign === -1 && second.sign === -1) { throw new Error( [ - `[checkSigns] I expect the two ports to have opposite signs,`, + `[checkPortSigns] I expect the two ports to have opposite signs,`, ` but they all have negative sign.`, ``, ` first port: ${formatPort(net, first)}`, diff --git a/src/lang/compose/compose.ts b/src/lang/compose/compose.ts index 0d239323..a69a44ac 100644 --- a/src/lang/compose/compose.ts +++ b/src/lang/compose/compose.ts @@ -1,5 +1,5 @@ import { Checking } from "../checking" -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { Env } from "../env" import { appendReport } from "../errors/appendReport" import { Mod } from "../mod" @@ -142,7 +142,7 @@ export function compose( ) } - connect(env.net, value, currentPort) + connectPorts(env.net, value, currentPort) if (options.checking) { unifyTypes(env, options.checking.substitution, value.t, currentPort.t) } diff --git a/src/lang/compose/composeNode.ts b/src/lang/compose/composeNode.ts index 1ea108bd..e843fd61 100644 --- a/src/lang/compose/composeNode.ts +++ b/src/lang/compose/composeNode.ts @@ -1,4 +1,4 @@ -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { Env } from "../env" import { refreshNode } from "../freshen/refreshNode" import { findInputPorts } from "../net/findInputPorts" @@ -39,7 +39,8 @@ export function composeNode( ) } - connect(env.net, value, port) + connectPorts(env.net, value, port) + if (options.checking) { unifyTypes(env, options.checking.substitution, value.t, port.t) } diff --git a/src/lang/compose/findCurrentPortOrFail.ts b/src/lang/compose/findCurrentPortOrFail.ts index 464b83c8..4dca72c6 100644 --- a/src/lang/compose/findCurrentPortOrFail.ts +++ b/src/lang/compose/findCurrentPortOrFail.ts @@ -1,4 +1,5 @@ import { Net } from "../net" +import { findHalfEdgeEntry } from "../net/findHalfEdgeEntry" import { findInputPorts } from "../net/findInputPorts" import { findOutputPorts } from "../net/findOutputPorts" import { findPortEntry } from "../net/findPortEntry" @@ -66,15 +67,31 @@ function findPortInNode( ): Port | undefined { for (const port of findInputPorts(net, node)) { if (port.name === portName) { - const portEntry = findPortEntry(net, port) - return portEntry?.connection?.port + return findCorrespondingPort(net, port) } } for (const port of findOutputPorts(net, node)) { if (port.name === portName) { - const portEntry = findPortEntry(net, port) - return portEntry?.connection?.port + return findCorrespondingPort(net, port) } } } + +function findCorrespondingPort(net: Net, port: Port): Port | undefined { + const portEntry = findPortEntry(net, port) + + if (portEntry === undefined) return + if (portEntry.connection === undefined) return + + const halfEdge = portEntry.connection.halfEdge + const halfEdgeEntry = findHalfEdgeEntry(net, halfEdge) + + if (halfEdgeEntry === undefined) return + + const ohterHalfEdgeEntry = findHalfEdgeEntry(net, halfEdgeEntry.otherHalfEdge) + + if (ohterHalfEdgeEntry === undefined) return + + return ohterHalfEdgeEntry.port +} diff --git a/src/lang/connect/connectHalfEdges.ts b/src/lang/connect/connectHalfEdges.ts new file mode 100644 index 00000000..7db08c5d --- /dev/null +++ b/src/lang/connect/connectHalfEdges.ts @@ -0,0 +1,31 @@ +import { HalfEdge } from "../half-edge" +import { Net } from "../net" +import { deleteHalfEdgeEntry } from "../net/deleteHalfEdgeEntry" +import { findHalfEdgeEntryOrFail } from "../net/findHalfEdgeEntryOrFail" + +export function connectHalfEdges( + net: Net, + firstHalfEdge: HalfEdge, + secondHalfEdge: HalfEdge, +): void { + const firstHalfEdgeEntry = findHalfEdgeEntryOrFail(net, firstHalfEdge) + const secondHalfEdgeEntry = findHalfEdgeEntryOrFail(net, secondHalfEdge) + + const firstOtherHalfEdge = firstHalfEdgeEntry.otherHalfEdge + const secondOtherHalfEdge = secondHalfEdgeEntry.otherHalfEdge + + const firstOtherHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + firstOtherHalfEdge, + ) + const secondOtherHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + secondOtherHalfEdge, + ) + + firstOtherHalfEdgeEntry.otherHalfEdge = secondOtherHalfEdge + secondOtherHalfEdgeEntry.otherHalfEdge = firstOtherHalfEdge + + deleteHalfEdgeEntry(net, firstHalfEdge) + deleteHalfEdgeEntry(net, secondHalfEdge) +} diff --git a/src/lang/connect/connectPortWithHalfEdge.ts b/src/lang/connect/connectPortWithHalfEdge.ts new file mode 100644 index 00000000..8e679573 --- /dev/null +++ b/src/lang/connect/connectPortWithHalfEdge.ts @@ -0,0 +1,42 @@ +import { edgeEqual } from "../edge" +import { HalfEdge } from "../half-edge" +import { Net } from "../net" +import { findHalfEdgeEntryOrFail } from "../net/findHalfEdgeEntryOrFail" +import { findPortRecordOrFail } from "../net/findPortRecordOrFail" +import { Port } from "../port" + +export function connectPortWithHalfEdge( + net: Net, + port: Port, + halfEdge: HalfEdge, +): void { + const portRecord = findPortRecordOrFail(net, port.node) + portRecord[port.name].connection = { halfEdge } + + const halfEdgeEntry = findHalfEdgeEntryOrFail(net, halfEdge) + if (halfEdgeEntry.port !== undefined) { + throw new Error( + `[connectPortWithHalfEdge] halfEdgeEntry is already connected`, + ) + } + + halfEdgeEntry.port = port + + const otherHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + halfEdgeEntry.otherHalfEdge, + ) + + if (otherHalfEdgeEntry.port !== undefined) { + if (port.isPrincipal && otherHalfEdgeEntry.port.isPrincipal) { + const edge = { + first: port, + second: otherHalfEdgeEntry.port, + } + + if (!net.activeEdges.find((activeEdge) => edgeEqual(activeEdge, edge))) { + net.activeEdges.push(edge) + } + } + } +} diff --git a/src/lang/connect/connect.ts b/src/lang/connect/connectPorts.ts similarity index 55% rename from src/lang/connect/connect.ts rename to src/lang/connect/connectPorts.ts index f2d72851..96ad546f 100644 --- a/src/lang/connect/connect.ts +++ b/src/lang/connect/connectPorts.ts @@ -1,11 +1,12 @@ import { checkPortSigns } from "../check/checkPortSigns" import { Net } from "../net" +import { addEdge } from "../net/addEdge" import { findPortEntry } from "../net/findPortEntry" -import { findPortRecordOrFail } from "../net/findPortRecordOrFail" import { Port } from "../port" import { formatPort } from "../port/formatPort" +import { connectPortWithHalfEdge } from "./connectPortWithHalfEdge" -export function connect(net: Net, first: Port, second: Port): void { +export function connectPorts(net: Net, first: Port, second: Port): void { const firstPortEntry = findPortEntry(net, first) if (firstPortEntry?.connection !== undefined) { @@ -14,10 +15,6 @@ export function connect(net: Net, first: Port, second: Port): void { `[connect] The first port is already connected.`, ``, ` first port: ${formatPort(net, first)}`, - ` first connected port: ${formatPort( - net, - firstPortEntry.connection.port, - )}`, ` second port: ${formatPort(net, second)}`, ].join("\n"), ) @@ -32,25 +29,14 @@ export function connect(net: Net, first: Port, second: Port): void { ``, ` first port: ${formatPort(net, first)}`, ` second port: ${formatPort(net, second)}`, - ` second connected port: ${formatPort( - net, - secondPortEntry.connection.port, - )}`, ].join("\n"), ) } checkPortSigns(net, first, second) - const edge = { first, second } + const halfEdges = addEdge(net) - const firstPortRecord = findPortRecordOrFail(net, first.node) - firstPortRecord[first.name].connection = { port: second } - - const secondPortRecord = findPortRecordOrFail(net, second.node) - secondPortRecord[second.name].connection = { port: first } - - if (first.isPrincipal && second.isPrincipal) { - net.activeEdges.push(edge) - } + connectPortWithHalfEdge(net, first, halfEdges.first) + connectPortWithHalfEdge(net, second, halfEdges.second) } diff --git a/src/lang/half-edge/createHalfEdgeId.ts b/src/lang/half-edge/createHalfEdgeId.ts index 5862c587..a9a1d58c 100644 --- a/src/lang/half-edge/createHalfEdgeId.ts +++ b/src/lang/half-edge/createHalfEdgeId.ts @@ -1,6 +1,6 @@ -import { Mod } from "../mod" +import { globalHalfEdgeInfo } from "./globalHalfEdgeInfo" -export function createHalfEdgeId(mod: Mod): string { - const n = mod.halfEdgeCounter++ +export function createHalfEdgeId(): string { + const n = globalHalfEdgeInfo.counter++ return n.toString() } diff --git a/src/lang/half-edge/globalHalfEdgeInfo.ts b/src/lang/half-edge/globalHalfEdgeInfo.ts new file mode 100644 index 00000000..09d08d88 --- /dev/null +++ b/src/lang/half-edge/globalHalfEdgeInfo.ts @@ -0,0 +1,3 @@ +export const globalHalfEdgeInfo = { + counter: 0, +} diff --git a/src/lang/interact/interact.ts b/src/lang/interact/interact.ts index d5adf533..5ee4f523 100644 --- a/src/lang/interact/interact.ts +++ b/src/lang/interact/interact.ts @@ -3,7 +3,9 @@ import { compose } from "../compose/compose" import { Edge } from "../edge" import { Env } from "../env" import { findRuleByPorts } from "../mod/findRuleByPorts" +import { deleteHalfEdgeEntry } from "../net/deleteHalfEdgeEntry" import { deleteNodeEntry } from "../net/deleteNodeEntry" +import { findPortEntryOrFail } from "../net/findPortEntryOrFail" export type InteractOptions = { checking?: Checking @@ -15,6 +17,7 @@ export function interact( options: InteractOptions, ): void { const rule = findRuleByPorts(env.mod, activeEdge.first, activeEdge.second) + if (rule === undefined) return for (const word of rule.words) { @@ -27,6 +30,17 @@ export function interact( }) } + const firstPortEntry = findPortEntryOrFail(env.net, activeEdge.first) + const secondPortEntry = findPortEntryOrFail(env.net, activeEdge.second) + + if (firstPortEntry.connection !== undefined) { + deleteHalfEdgeEntry(env.net, firstPortEntry.connection.halfEdge) + } + + if (secondPortEntry.connection !== undefined) { + deleteHalfEdgeEntry(env.net, secondPortEntry.connection.halfEdge) + } + deleteNodeEntry(env.net, activeEdge.first.node) deleteNodeEntry(env.net, activeEdge.second.node) } diff --git a/src/lang/mod/Mod.ts b/src/lang/mod/Mod.ts index 2fa60ac0..09ae0855 100644 --- a/src/lang/mod/Mod.ts +++ b/src/lang/mod/Mod.ts @@ -16,6 +16,4 @@ export type Mod = { builtins: Map ruleEntries: Map requiredMods: Map - nodeCounters: Map - halfEdgeCounter: number } diff --git a/src/lang/mod/createMod.ts b/src/lang/mod/createMod.ts index 2c026a46..f4a58d34 100644 --- a/src/lang/mod/createMod.ts +++ b/src/lang/mod/createMod.ts @@ -20,8 +20,6 @@ export function createMod(options: { builtins: new Map(), ruleEntries: new Map(), requiredMods: new Map(), - nodeCounters: new Map(), - halfEdgeCounter: 0, } as Mod mod.env = createEnv(mod) diff --git a/src/lang/mod/findRuleByNodes.ts b/src/lang/mod/findRuleByNodes.ts index 6690e388..fa612a98 100644 --- a/src/lang/mod/findRuleByNodes.ts +++ b/src/lang/mod/findRuleByNodes.ts @@ -11,7 +11,8 @@ export function findRuleByNodes( const firstKey = nodeKeyWithoutId(firstNode) const secondKey = nodeKeyWithoutId(secondNode) - const key = `${firstKey} ${secondKey}` - - return mod.ruleEntries.get(key) + return ( + mod.ruleEntries.get(`${firstKey} ${secondKey}`) || + mod.ruleEntries.get(`${secondKey} ${firstKey}`) + ) } diff --git a/src/lang/net/Net.ts b/src/lang/net/Net.ts index 42a32343..14863b8c 100644 --- a/src/lang/net/Net.ts +++ b/src/lang/net/Net.ts @@ -23,7 +23,7 @@ export type Net = { export type HalfEdgeEntry = { id: string port?: Port - otherHalf?: HalfEdge + otherHalfEdge: HalfEdge } export type NodeEntry = { @@ -56,6 +56,5 @@ export type PortEntry = { // interfere with each other. export type Connection = { - // halfEdge: HalfEdge - port: Port + halfEdge: HalfEdge } diff --git a/src/lang/net/addEdge.ts b/src/lang/net/addEdge.ts index 7e789056..0f37f3eb 100644 --- a/src/lang/net/addEdge.ts +++ b/src/lang/net/addEdge.ts @@ -1,17 +1,16 @@ import { HalfEdge } from "../half-edge" import { createHalfEdgeId } from "../half-edge/createHalfEdgeId" -import { Mod } from "../mod" -import { Net } from "../net" +import { HalfEdgeEntry, Net } from "../net" -export function addEdge( - net: Net, - mod: Mod, -): { first: HalfEdge; second: HalfEdge } { - const firstId = createHalfEdgeId(mod) - const first = { id: firstId } +export function addEdge(net: Net): { first: HalfEdge; second: HalfEdge } { + const firstId = createHalfEdgeId() + const first = { id: firstId } as HalfEdgeEntry - const secondId = createHalfEdgeId(mod) - const second = { id: secondId } + const secondId = createHalfEdgeId() + const second = { id: secondId } as HalfEdgeEntry + + first.otherHalfEdge = { id: second.id } + second.otherHalfEdge = { id: first.id } net.halfEdgeEntries.set(firstId, first) net.halfEdgeEntries.set(secondId, second) diff --git a/src/lang/net/addNode.ts b/src/lang/net/addNode.ts index fc2e21f6..3c2c65bb 100644 --- a/src/lang/net/addNode.ts +++ b/src/lang/net/addNode.ts @@ -12,7 +12,7 @@ export function addNode( input: Array, output: Array, ): Node { - const id = createNodeId(mod, name) + const id = createNodeId(name) const node: Node = { "@type": "Value", diff --git a/src/lang/net/allEdges.ts b/src/lang/net/allEdges.ts index 8bdacf33..102c905a 100644 --- a/src/lang/net/allEdges.ts +++ b/src/lang/net/allEdges.ts @@ -1,9 +1,9 @@ import { Edge } from "../edge" import { nodeKey } from "../node/nodeKey" -import { Port } from "../port" import { Net } from "./Net" import { createNodeFromNodeEntry } from "./createNodeFromNodeEntry" import { createPortFromPortEntry } from "./createPortFromPortEntry" +import { findHalfEdgeEntryOrFail } from "./findHalfEdgeEntryOrFail" export function allEdges(net: Net): Array { const edges: Array = [] @@ -14,8 +14,22 @@ export function allEdges(net: Net): Array { for (const portEntry of Object.values(nodeEntry.ports)) { if (portEntry.connection) { - const second = portEntry.connection.port - const first: Port = createPortFromPortEntry(node, portEntry) + const first = createPortFromPortEntry(node, portEntry) + + const halfEdgeEntry = findHalfEdgeEntryOrFail( + net, + portEntry.connection.halfEdge, + ) + + const otherHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + halfEdgeEntry.otherHalfEdge, + ) + + const second = otherHalfEdgeEntry.port + if (second === undefined) { + continue + } const firstOccur = `${nodeKey(node)}-${portEntry.name}` const secondOccur = `${nodeKey(second.node)}-${second.name}` diff --git a/src/lang/net/copyConnectedComponent.ts b/src/lang/net/copyConnectedComponent.ts index 7a34c6a6..86fe023d 100644 --- a/src/lang/net/copyConnectedComponent.ts +++ b/src/lang/net/copyConnectedComponent.ts @@ -1,7 +1,9 @@ import { edgeEqual } from "../edge/edgeEqual" -import { Node } from "../node" +import { Node, nodeKey } from "../node" import { Net } from "./Net" -import { copyNode } from "./copyNode" +import { cloneNodeEntry } from "./cloneNodeEntry" +import { findHalfEdgeEntryOrFail } from "./findHalfEdgeEntryOrFail" +import { findNodeEntryOrFail } from "./findNodeEntryOrFail" import { findPortRecordOrFail } from "./findPortRecordOrFail" import { hasNode } from "./hasNode" @@ -16,11 +18,32 @@ export function copyConnectedComponent( const portRecord = findPortRecordOrFail(net, node) - copyNode(net, component, node) + const entry = findNodeEntryOrFail(net, node) + component.nodeEntries.set(nodeKey(node), cloneNodeEntry(entry)) for (const portEntry of Object.values(portRecord)) { if (portEntry.connection) { - copyConnectedComponent(net, component, portEntry.connection.port.node) + const halfEdgeEntry = findHalfEdgeEntryOrFail( + net, + portEntry.connection.halfEdge, + ) + + const otherHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + halfEdgeEntry.otherHalfEdge, + ) + + component.halfEdgeEntries.set(halfEdgeEntry.id, { + ...halfEdgeEntry, + }) + + component.halfEdgeEntries.set(otherHalfEdgeEntry.id, { + ...otherHalfEdgeEntry, + }) + + if (otherHalfEdgeEntry.port) { + copyConnectedComponent(net, component, otherHalfEdgeEntry.port.node) + } } } diff --git a/src/lang/net/copyNode.ts b/src/lang/net/copyNode.ts deleted file mode 100644 index 47c108a9..00000000 --- a/src/lang/net/copyNode.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Node } from "../node" -import { nodeKey } from "../node/nodeKey" -import { Net } from "./Net" -import { cloneNodeEntry } from "./cloneNodeEntry" -import { findNodeEntryOrFail } from "./findNodeEntryOrFail" - -export function copyNode(source: Net, target: Net, node: Node): void { - const entry = findNodeEntryOrFail(source, node) - target.nodeEntries.set(nodeKey(node), cloneNodeEntry(entry)) -} diff --git a/src/lang/net/deleteHalfEdgeEntry.ts b/src/lang/net/deleteHalfEdgeEntry.ts new file mode 100644 index 00000000..3a5320c2 --- /dev/null +++ b/src/lang/net/deleteHalfEdgeEntry.ts @@ -0,0 +1,6 @@ +import { HalfEdge } from "../half-edge" +import { Net } from "./Net" + +export function deleteHalfEdgeEntry(net: Net, halfEdge: HalfEdge): void { + net.halfEdgeEntries.delete(halfEdge.id) +} diff --git a/src/lang/net/disconnectPort.ts b/src/lang/net/disconnectPort.ts index 96c4b7ae..379242a7 100644 --- a/src/lang/net/disconnectPort.ts +++ b/src/lang/net/disconnectPort.ts @@ -1,19 +1,25 @@ import { Port } from "../port" import { Net } from "./Net" +import { findHalfEdgeEntry } from "./findHalfEdgeEntry" import { findNodeEntry } from "./findNodeEntry" -export function disconnectPort(net: Net, port: Port): Port | undefined { +export function disconnectPort(net: Net, port: Port): void { const nodeEntry = findNodeEntry(net, port.node) if (nodeEntry === undefined) { return undefined } - const connectedPort = nodeEntry.ports[port.name].connection?.port - delete nodeEntry.ports[port.name].connection + const portEntry = nodeEntry.ports[port.name] - if (connectedPort) { - disconnectPort(net, connectedPort) - } + const halfEdge = portEntry.connection?.halfEdge + delete portEntry.connection + + if (halfEdge !== undefined) { + const halfEdgeEntry = findHalfEdgeEntry(net, halfEdge) + if (halfEdgeEntry === undefined) { + throw new Error(`[disconnectPort] Fail to find halfEdgeEntry`) + } - return connectedPort + delete halfEdgeEntry.port + } } diff --git a/src/lang/net/findHalfEdgeEntry.ts b/src/lang/net/findHalfEdgeEntry.ts new file mode 100644 index 00000000..2913e63a --- /dev/null +++ b/src/lang/net/findHalfEdgeEntry.ts @@ -0,0 +1,9 @@ +import { HalfEdge } from "../half-edge" +import { HalfEdgeEntry, Net } from "./Net" + +export function findHalfEdgeEntry( + net: Net, + halfEdge: HalfEdge, +): HalfEdgeEntry | undefined { + return net.halfEdgeEntries.get(halfEdge.id) +} diff --git a/src/lang/net/findHalfEdgeEntryOrFail.ts b/src/lang/net/findHalfEdgeEntryOrFail.ts new file mode 100644 index 00000000..894c4b38 --- /dev/null +++ b/src/lang/net/findHalfEdgeEntryOrFail.ts @@ -0,0 +1,15 @@ +import { HalfEdge } from "../half-edge" +import { HalfEdgeEntry, Net } from "./Net" +import { findHalfEdgeEntry } from "./findHalfEdgeEntry" + +export function findHalfEdgeEntryOrFail( + net: Net, + halfEdge: HalfEdge, +): HalfEdgeEntry { + const halfEdgeEntry = findHalfEdgeEntry(net, halfEdge) + if (halfEdgeEntry === undefined) { + throw new Error(`[findHalfEdgeEntryOrFail] Undefined halfEdgeEntry`) + } + + return halfEdgeEntry +} diff --git a/src/lang/net/findPortEntryOrFail.ts b/src/lang/net/findPortEntryOrFail.ts new file mode 100644 index 00000000..934d2c14 --- /dev/null +++ b/src/lang/net/findPortEntryOrFail.ts @@ -0,0 +1,12 @@ +import { Port } from "../port" +import { Net, PortEntry } from "./Net" +import { findPortEntry } from "./findPortEntry" + +export function findPortEntryOrFail(net: Net, port: Port): PortEntry { + const portEntry = findPortEntry(net, port) + if (portEntry === undefined) { + throw new Error(`[findPortEntryOrFail] Undefined port`) + } + + return portEntry +} diff --git a/src/lang/net/findPortRecordOrFail.ts b/src/lang/net/findPortRecordOrFail.ts index 6d68db7b..cb001aa7 100644 --- a/src/lang/net/findPortRecordOrFail.ts +++ b/src/lang/net/findPortRecordOrFail.ts @@ -8,7 +8,7 @@ export function findPortRecordOrFail(net: Net, node: Node): PortRecord { if (nodeEntry === undefined) { throw new Error( [ - `[findNodePortsOrFail] I can not find node entry for node.`, + `[findPortRecordOrFail] I can not find node entry for node.`, ``, ` node: ${formatNode(net, node)}`, ].join("\n"), diff --git a/src/lang/net/moveConnectedComponent.ts b/src/lang/net/moveConnectedComponent.ts index 9c1943cc..4bc2b90f 100644 --- a/src/lang/net/moveConnectedComponent.ts +++ b/src/lang/net/moveConnectedComponent.ts @@ -1,30 +1,61 @@ -import { Edge } from "../edge" -import { edgeEqual } from "../edge/edgeEqual" -import { Node } from "../node" +import { Edge, edgeEqual } from "../edge" +import { Node, nodeKey } from "../node" import { Net } from "./Net" +import { findHalfEdgeEntryOrFail } from "./findHalfEdgeEntryOrFail" +import { findNodeEntryOrFail } from "./findNodeEntryOrFail" import { findPortRecordOrFail } from "./findPortRecordOrFail" import { hasNode } from "./hasNode" -import { moveNode } from "./moveNode" export function moveConnectedComponent( net: Net, component: Net, node: Node, ): void { + moveNodeEntries(net, component, node) + deleteHalfEdgeEntries(net, component) + moveActiveEdges(net, component) +} + +export function deleteHalfEdgeEntries(net: Net, component: Net): void { + for (const halfEdgeEntry of component.halfEdgeEntries.values()) { + net.halfEdgeEntries.delete(halfEdgeEntry.id) + } +} + +export function moveNodeEntries(net: Net, component: Net, node: Node): void { if (hasNode(component, node)) { return } const portRecord = findPortRecordOrFail(net, node) - moveNode(net, component, node) + const entry = findNodeEntryOrFail(net, node) + component.nodeEntries.set(nodeKey(node), entry) + net.nodeEntries.delete(nodeKey(node)) for (const portEntry of Object.values(portRecord)) { if (portEntry.connection) { - moveConnectedComponent(net, component, portEntry.connection.port.node) + const halfEdgeEntry = findHalfEdgeEntryOrFail( + net, + portEntry.connection.halfEdge, + ) + + const ohterHalfEdgeEntry = findHalfEdgeEntryOrFail( + net, + halfEdgeEntry.otherHalfEdge, + ) + + component.halfEdgeEntries.set(halfEdgeEntry.id, halfEdgeEntry) + component.halfEdgeEntries.set(ohterHalfEdgeEntry.id, ohterHalfEdgeEntry) + + if (ohterHalfEdgeEntry.port) { + moveNodeEntries(net, component, ohterHalfEdgeEntry.port.node) + } } } +} +export function moveActiveEdges(net: Net, component: Net): void { const remainingActiveEdges: Array = [] for (const activeEdge of net.activeEdges) { diff --git a/src/lang/net/moveNode.ts b/src/lang/net/moveNode.ts deleted file mode 100644 index 4f66a096..00000000 --- a/src/lang/net/moveNode.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { Node } from "../node" -import { nodeKey } from "../node/nodeKey" -import { Net } from "./Net" -import { findNodeEntryOrFail } from "./findNodeEntryOrFail" - -export function moveNode(source: Net, target: Net, node: Node): void { - const entry = findNodeEntryOrFail(source, node) - target.nodeEntries.set(nodeKey(node), entry) - source.nodeEntries.delete(nodeKey(node)) -} diff --git a/src/lang/node/createNodeId.ts b/src/lang/node/createNodeId.ts index beb9971c..c1141a3e 100644 --- a/src/lang/node/createNodeId.ts +++ b/src/lang/node/createNodeId.ts @@ -1,12 +1,12 @@ -import { Mod } from "../mod" +import { globalNodeCounters } from "./globalNodeCounters" -export function createNodeId(mod: Mod, name: string): string { - const foundCounter = mod.nodeCounters.get(name) +export function createNodeId(name: string): string { + const foundCounter = globalNodeCounters.get(name) if (foundCounter === undefined) { - mod.nodeCounters.set(name, 0) + globalNodeCounters.set(name, 0) return String(0) } else { - mod.nodeCounters.set(name, foundCounter + 1) + globalNodeCounters.set(name, foundCounter + 1) return String(foundCounter + 1) } } diff --git a/src/lang/node/globalNodeCounters.ts b/src/lang/node/globalNodeCounters.ts new file mode 100644 index 00000000..5d02fd3a --- /dev/null +++ b/src/lang/node/globalNodeCounters.ts @@ -0,0 +1 @@ +export const globalNodeCounters: Map = new Map() diff --git a/src/lang/present/presentRuleAsNets.ts b/src/lang/present/presentRuleAsNets.ts index 39b190e7..a7301f6c 100644 --- a/src/lang/present/presentRuleAsNets.ts +++ b/src/lang/present/presentRuleAsNets.ts @@ -1,6 +1,6 @@ import { capNodeNonPrinciplePorts } from "../cap" import { compose } from "../compose/compose" -import { connect } from "../connect/connect" +import { connectPorts } from "../connect/connectPorts" import { createEnv } from "../env/createEnv" import { Mod, findDefinitionOrFail } from "../mod" import { findRuleByName } from "../mod/findRuleByName" @@ -64,7 +64,7 @@ function collectInitialNet(net: Net, first: Node, second: Node): Net { const firstPrincipalPort = findPrincipalPort(initial, first) const secondPrincipalPort = findPrincipalPort(initial, second) - connect(initial, firstPrincipalPort, secondPrincipalPort) + connectPorts(initial, firstPrincipalPort, secondPrincipalPort) return initial } diff --git a/src/lang/run/collectConnectedPort.ts b/src/lang/run/collectConnectedPort.ts index cc17b9f0..17c48cbf 100644 --- a/src/lang/run/collectConnectedPort.ts +++ b/src/lang/run/collectConnectedPort.ts @@ -1,6 +1,7 @@ import { Net } from "../net" import { deleteNodeEntry } from "../net/deleteNodeEntry" import { disconnectPort } from "../net/disconnectPort" +import { findHalfEdgeEntryOrFail } from "../net/findHalfEdgeEntryOrFail" import { findPortEntry } from "../net/findPortEntry" import { Port } from "../port" import { formatPort } from "../port/formatPort" @@ -10,14 +11,30 @@ export function collectConnectedPort(component: Net, capPort: Port): Port { if (capPortEntry?.connection === undefined) { throw new Error( [ - `[run] I expect the capPort to be connected.`, + `[collectConnectedPort] I expect the capPort to be connected.`, ``, ` capPort: ${formatPort(component, capPort)}`, ].join("\n"), ) } - const connectedPort = capPortEntry.connection.port + const halfEdgeEntry = findHalfEdgeEntryOrFail( + component, + capPortEntry.connection.halfEdge, + ) + + const ohterHalfEdgeEntry = findHalfEdgeEntryOrFail( + component, + halfEdgeEntry.otherHalfEdge, + ) + + const connectedPort = ohterHalfEdgeEntry.port + + if (connectedPort === undefined) { + throw new Error( + `[collectConnectedPort] I expect halfEdgeEntry to have port.`, + ) + } disconnectPort(component, capPort) deleteNodeEntry(component, capPort.node) diff --git a/tests/checking/begin-sign.error.i.err b/tests/checking/begin-sign.error.i.err index 3df596ea..68c41627 100644 --- a/tests/checking/begin-sign.error.i.err +++ b/tests/checking/begin-sign.error.i.err @@ -1,4 +1,4 @@ -[checkSigns] I expect the two ports to have opposite signs, +[checkPortSigns] I expect the two ports to have opposite signs, but they all have positive sign. first port: (sole₁)-value! diff --git a/tests/checking/rule-sign.error.i.err b/tests/checking/rule-sign.error.i.err index b1b33503..d17eb786 100644 --- a/tests/checking/rule-sign.error.i.err +++ b/tests/checking/rule-sign.error.i.err @@ -1,4 +1,4 @@ -[checkSigns] I expect the two ports to have opposite signs, +[checkPortSigns] I expect the two ports to have opposite signs, but they all have positive sign. first port: (@inputPortCap₂)-covering diff --git a/tests/datatype/Nat.test.i.out b/tests/datatype/Nat.test.i.out index 9049e308..3ef82d36 100644 --- a/tests/datatype/Nat.test.i.out +++ b/tests/datatype/Nat.test.i.out @@ -25,10 +25,10 @@ netFromPort (add₁₅)-return (add1₂₅)-prev value-(zero₂₄) (add1₂₄)-prev value-(zero₂₃) end -netFromPort (add1₃₀)-value! +netFromPort (add1₂₉)-value! + (add1₂₉)-prev value-(add1₃₀) (add1₃₀)-prev value-(add1₃₁) - (add1₃₁)-prev value-(add1₂₈) - (add1₂₈)-prev value-(add1₂₄) + (add1₃₁)-prev value-(add1₂₄) (add1₂₄)-prev value-(zero₂₃) end netFromPort (add₂₀)-return @@ -70,10 +70,10 @@ netFromPort (mul₃)-return (add1₄₉)-prev value-(zero₃₉) end netFromPort (add1₅₇)-value! - (add1₅₇)-prev value-(add1₆₀) - (add1₆₀)-prev value-(add1₆₃) - (add1₆₃)-prev value-(add1₆₆) - (add1₆₆)-prev value-(zero₅₁) + (add1₅₇)-prev value-(add1₆₃) + (add1₆₃)-prev value-(add1₆₀) + (add1₆₀)-prev value-(add1₆₆) + (add1₆₆)-prev value-(zero₄₇) end netFromPort (mul₈)-return (mul₈)-target return-(add₄₇) @@ -93,16 +93,16 @@ netFromPort (mul₈)-return (add1₆₈)-prev value-(zero₅₃) (add1₆₇)-prev value-(zero₅₂) end -netFromPort (add1₇₉)-value! - (add1₇₉)-prev value-(add1₈₂) - (add1₈₂)-prev value-(add1₈₅) - (add1₈₅)-prev value-(add1₈₈) +netFromPort (add1₇₈)-value! + (add1₇₈)-prev value-(add1₈₈) (add1₈₈)-prev value-(add1₉₇) - (add1₉₇)-prev value-(add1₉₁) - (add1₉₁)-prev value-(add1₉₄) - (add1₉₄)-prev value-(add1₁₀₀) - (add1₁₀₀)-prev value-(add1₁₀₃) - (add1₁₀₃)-prev value-(zero₇₀) + (add1₉₇)-prev value-(add1₈₁) + (add1₈₁)-prev value-(add1₈₄) + (add1₈₄)-prev value-(add1₉₁) + (add1₉₁)-prev value-(add1₁₀₀) + (add1₁₀₀)-prev value-(add1₉₄) + (add1₉₄)-prev value-(add1₁₀₃) + (add1₁₀₃)-prev value-(zero₆₄) end netFromPort (add1₁₀₇)-value! (add1₁₀₇)-prev value-(add1₁₀₄) @@ -112,8 +112,8 @@ netFromPort (add1₁₁₂)-value! (add1₁₁₂)-prev value-(add1₁₁₃) (add1₁₁₃)-prev value-(zero₇₅) end -netFromPort (add1₁₂₂)-value! - (add1₁₂₂)-prev value-(add1₁₂₃) +netFromPort (add1₁₂₁)-value! + (add1₁₂₁)-prev value-(add1₁₂₃) (add1₁₂₃)-prev value-(add1₁₁₄) (add1₁₁₄)-prev value-(zero₇₇) end