Skip to content

Commit 1e85518

Browse files
authored
fix: pin parsed the <pin_number> as the x coordinate (#11)
1 parent 2665804 commit 1e85518

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

lib/sexpr/classes/DsnPin.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,34 @@ export class DsnPin extends SxClass {
3737
primitiveSexprs: PrimitiveSExpr[],
3838
): DsnPin {
3939
const pin = new DsnPin()
40-
const strings = primitiveSexprs.filter(
41-
(p) => typeof p === "string",
42-
) as string[]
43-
const numbers = primitiveSexprs.filter(
44-
(p) => typeof p === "number",
45-
) as number[]
46-
if (strings[0]) pin._padstackId = strings[0]
47-
if (strings[1]) pin._pinId = strings[1]
48-
if (numbers[0] !== undefined) pin._x = numbers[0]
49-
if (numbers[1] !== undefined) pin._y = numbers[1]
50-
if (numbers[2] !== undefined) pin._rotation = numbers[2]
40+
// DSN format: (pin <padstack_id> [(rotate <angle>)] <pin_id> <x> <y> [rotation])
41+
// Parse positionally - pin_id can be a number or string
42+
// Filter to only strings and numbers (skip nested arrays like (rotate ...))
43+
const primitives = primitiveSexprs.filter(
44+
(p) => typeof p === "string" || typeof p === "number",
45+
) as (string | number)[]
46+
47+
// Check for inline (rotate ...) expression and extract rotation from it
48+
const rotateExpr = primitiveSexprs.find(
49+
(p) => Array.isArray(p) && p[0] === "rotate",
50+
) as PrimitiveSExpr[] | undefined
51+
if (rotateExpr && typeof rotateExpr[1] === "number") {
52+
pin._rotation = rotateExpr[1]
53+
}
54+
55+
if (primitives[0] !== undefined) pin._padstackId = String(primitives[0])
56+
if (primitives[1] !== undefined) pin._pinId = String(primitives[1])
57+
if (primitives[2] !== undefined && typeof primitives[2] === "number")
58+
pin._x = primitives[2]
59+
if (primitives[3] !== undefined && typeof primitives[3] === "number")
60+
pin._y = primitives[3]
61+
// Only set rotation from primitives if not already set from (rotate ...) expression
62+
if (
63+
pin._rotation === undefined &&
64+
primitives[4] !== undefined &&
65+
typeof primitives[4] === "number"
66+
)
67+
pin._rotation = primitives[4]
5168
return pin
5269
}
5370

tests/sexpr/classes/DsnPin.test.ts

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { DsnPin } from "lib/sexpr"
2+
import { SxClass } from "lib/sexpr/base-classes/SxClass"
23
import { test, expect } from "bun:test"
34

45
test("DsnPin without quotes on padstack ID", () => {
@@ -44,3 +45,54 @@ test("DsnPin with rotation", () => {
4445
"(pin RoundRect[T]Pad_540x640_135.514_um_0.000000_0_source_component_0 1 -500 0 90)",
4546
)
4647
})
48+
49+
test("DsnPin parses numeric pin_id correctly from DSN format", () => {
50+
// Format: (pin <padstack_id> <pin_id> <x> <y>)
51+
// Where pin_id is numeric (12), x is -2525, y is -6350
52+
const pin = DsnPin.fromSexprPrimitives([
53+
"Rect[T]Pad_3150.000000x1000.000000_um",
54+
12,
55+
-2525,
56+
-6350,
57+
])
58+
59+
expect(pin.padstackId).toBe("Rect[T]Pad_3150.000000x1000.000000_um")
60+
expect(pin.pinId).toBe("12")
61+
expect(pin.x).toBe(-2525)
62+
expect(pin.y).toBe(-6350)
63+
expect(pin.rotation).toBeUndefined()
64+
})
65+
66+
test("DsnPin parses inline (rotate ...) expression correctly", () => {
67+
// Format: (pin <padstack_id> (rotate <angle>) <pin_id> <x> <y>)
68+
const pin = DsnPin.fromSexprPrimitives([
69+
"Round[T]Pad_1730.000000_um",
70+
["rotate", 90],
71+
1,
72+
0,
73+
0,
74+
])
75+
76+
expect(pin.padstackId).toBe("Round[T]Pad_1730.000000_um")
77+
expect(pin.pinId).toBe("1")
78+
expect(pin.x).toBe(0)
79+
expect(pin.y).toBe(0)
80+
expect(pin.rotation).toBe(90)
81+
})
82+
83+
test("DsnPin parses rotation at end of expression", () => {
84+
// Format: (pin <padstack_id> <pin_id> <x> <y> <rotation>)
85+
const pin = DsnPin.fromSexprPrimitives([
86+
"Rect[T]Pad_1000x1000_um",
87+
"A1",
88+
100,
89+
200,
90+
45,
91+
])
92+
93+
expect(pin.padstackId).toBe("Rect[T]Pad_1000x1000_um")
94+
expect(pin.pinId).toBe("A1")
95+
expect(pin.x).toBe(100)
96+
expect(pin.y).toBe(200)
97+
expect(pin.rotation).toBe(45)
98+
})

0 commit comments

Comments
 (0)