kicadts 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. package/.cursor/rules/use-bun-instead-of-node-vite-npm-pnpm.mdc +111 -0
  2. package/.vscode/settings.json +16 -0
  3. package/AGENTS.md +30 -0
  4. package/README.md +206 -0
  5. package/biome.json +93 -0
  6. package/bun.lock +48 -0
  7. package/bunfig.toml +5 -0
  8. package/lib/index.ts +1 -0
  9. package/lib/sexpr/base-classes/SxClass.ts +164 -0
  10. package/lib/sexpr/base-classes/SxPrimitiveBoolean.ts +35 -0
  11. package/lib/sexpr/base-classes/SxPrimitiveNumber.ts +26 -0
  12. package/lib/sexpr/base-classes/SxPrimitiveString.ts +26 -0
  13. package/lib/sexpr/classes/At.ts +38 -0
  14. package/lib/sexpr/classes/Bus.ts +83 -0
  15. package/lib/sexpr/classes/BusEntry.ts +142 -0
  16. package/lib/sexpr/classes/Color.ts +29 -0
  17. package/lib/sexpr/classes/Dnp.ts +8 -0
  18. package/lib/sexpr/classes/EmbeddedFonts.ts +70 -0
  19. package/lib/sexpr/classes/ExcludeFromSim.ts +8 -0
  20. package/lib/sexpr/classes/FieldsAutoplaced.ts +8 -0
  21. package/lib/sexpr/classes/Footprint.ts +719 -0
  22. package/lib/sexpr/classes/FootprintAttr.ts +102 -0
  23. package/lib/sexpr/classes/FootprintAutoplaceCost180.ts +9 -0
  24. package/lib/sexpr/classes/FootprintAutoplaceCost90.ts +9 -0
  25. package/lib/sexpr/classes/FootprintClearance.ts +9 -0
  26. package/lib/sexpr/classes/FootprintDescr.ts +44 -0
  27. package/lib/sexpr/classes/FootprintLocked.ts +32 -0
  28. package/lib/sexpr/classes/FootprintModel.ts +145 -0
  29. package/lib/sexpr/classes/FootprintNetTiePadGroups.ts +50 -0
  30. package/lib/sexpr/classes/FootprintPad.ts +705 -0
  31. package/lib/sexpr/classes/FootprintPath.ts +44 -0
  32. package/lib/sexpr/classes/FootprintPlaced.ts +32 -0
  33. package/lib/sexpr/classes/FootprintPrivateLayers.ts +56 -0
  34. package/lib/sexpr/classes/FootprintSheetfile.ts +44 -0
  35. package/lib/sexpr/classes/FootprintSheetname.ts +44 -0
  36. package/lib/sexpr/classes/FootprintSolderMaskMargin.ts +9 -0
  37. package/lib/sexpr/classes/FootprintSolderPasteMargin.ts +9 -0
  38. package/lib/sexpr/classes/FootprintSolderPasteRatio.ts +9 -0
  39. package/lib/sexpr/classes/FootprintTags.ts +44 -0
  40. package/lib/sexpr/classes/FootprintTedit.ts +21 -0
  41. package/lib/sexpr/classes/FootprintThermalGap.ts +9 -0
  42. package/lib/sexpr/classes/FootprintThermalWidth.ts +9 -0
  43. package/lib/sexpr/classes/FootprintZoneConnect.ts +9 -0
  44. package/lib/sexpr/classes/FpArc.ts +289 -0
  45. package/lib/sexpr/classes/FpCircle.ts +293 -0
  46. package/lib/sexpr/classes/FpLine.ts +288 -0
  47. package/lib/sexpr/classes/FpPoly.ts +266 -0
  48. package/lib/sexpr/classes/FpPolyFill.ts +48 -0
  49. package/lib/sexpr/classes/FpPolyLocked.ts +40 -0
  50. package/lib/sexpr/classes/FpRect.ts +293 -0
  51. package/lib/sexpr/classes/FpText.ts +341 -0
  52. package/lib/sexpr/classes/FpTextBox.ts +412 -0
  53. package/lib/sexpr/classes/GrLine.ts +245 -0
  54. package/lib/sexpr/classes/GrLineAngle.ts +32 -0
  55. package/lib/sexpr/classes/GrLineEnd.ts +61 -0
  56. package/lib/sexpr/classes/GrLineLocked.ts +40 -0
  57. package/lib/sexpr/classes/GrLineStart.ts +61 -0
  58. package/lib/sexpr/classes/GrText.ts +202 -0
  59. package/lib/sexpr/classes/Image.ts +256 -0
  60. package/lib/sexpr/classes/InBom.ts +8 -0
  61. package/lib/sexpr/classes/Junction.ts +134 -0
  62. package/lib/sexpr/classes/KicadPcb.ts +313 -0
  63. package/lib/sexpr/classes/KicadSch.ts +303 -0
  64. package/lib/sexpr/classes/KicadSchGenerator.ts +32 -0
  65. package/lib/sexpr/classes/KicadSchGeneratorVersion.ts +30 -0
  66. package/lib/sexpr/classes/KicadSchVersion.ts +22 -0
  67. package/lib/sexpr/classes/Label.ts +136 -0
  68. package/lib/sexpr/classes/Layer.ts +51 -0
  69. package/lib/sexpr/classes/Layers.ts +47 -0
  70. package/lib/sexpr/classes/LibSymbols.ts +61 -0
  71. package/lib/sexpr/classes/NoConnect.ts +73 -0
  72. package/lib/sexpr/classes/OnBoard.ts +8 -0
  73. package/lib/sexpr/classes/PadChamfer.ts +50 -0
  74. package/lib/sexpr/classes/PadChamferRatio.ts +9 -0
  75. package/lib/sexpr/classes/PadClearance.ts +9 -0
  76. package/lib/sexpr/classes/PadDieLength.ts +9 -0
  77. package/lib/sexpr/classes/PadDrill.ts +145 -0
  78. package/lib/sexpr/classes/PadDrillOffset.ts +54 -0
  79. package/lib/sexpr/classes/PadLayers.ts +59 -0
  80. package/lib/sexpr/classes/PadNet.ts +56 -0
  81. package/lib/sexpr/classes/PadOptions.ts +182 -0
  82. package/lib/sexpr/classes/PadPinFunction.ts +9 -0
  83. package/lib/sexpr/classes/PadPinType.ts +9 -0
  84. package/lib/sexpr/classes/PadPrimitiveGrArc.ts +254 -0
  85. package/lib/sexpr/classes/PadPrimitiveGrCircle.ts +279 -0
  86. package/lib/sexpr/classes/PadPrimitiveGrLine.ts +126 -0
  87. package/lib/sexpr/classes/PadPrimitives.ts +289 -0
  88. package/lib/sexpr/classes/PadRectDelta.ts +57 -0
  89. package/lib/sexpr/classes/PadRoundrectRratio.ts +9 -0
  90. package/lib/sexpr/classes/PadSize.ts +54 -0
  91. package/lib/sexpr/classes/PadSolderMaskMargin.ts +9 -0
  92. package/lib/sexpr/classes/PadSolderPasteMargin.ts +9 -0
  93. package/lib/sexpr/classes/PadSolderPasteMarginRatio.ts +9 -0
  94. package/lib/sexpr/classes/PadTeardrops.ts +208 -0
  95. package/lib/sexpr/classes/PadThermalBridgeAngle.ts +9 -0
  96. package/lib/sexpr/classes/PadThermalGap.ts +9 -0
  97. package/lib/sexpr/classes/PadThermalWidth.ts +9 -0
  98. package/lib/sexpr/classes/PadZoneConnect.ts +9 -0
  99. package/lib/sexpr/classes/Paper.ts +119 -0
  100. package/lib/sexpr/classes/PcbGeneral.ts +75 -0
  101. package/lib/sexpr/classes/PcbGeneralLegacyTeardrops.ts +44 -0
  102. package/lib/sexpr/classes/PcbGeneralThickness.ts +9 -0
  103. package/lib/sexpr/classes/PcbGenerator.ts +16 -0
  104. package/lib/sexpr/classes/PcbGeneratorVersion.ts +16 -0
  105. package/lib/sexpr/classes/PcbLayerDefinition.ts +102 -0
  106. package/lib/sexpr/classes/PcbLayers.ts +34 -0
  107. package/lib/sexpr/classes/PcbNet.ts +56 -0
  108. package/lib/sexpr/classes/PcbVersion.ts +9 -0
  109. package/lib/sexpr/classes/Property.ts +246 -0
  110. package/lib/sexpr/classes/PropertyHide.ts +9 -0
  111. package/lib/sexpr/classes/PropertyUnlocked.ts +9 -0
  112. package/lib/sexpr/classes/Pts.ts +65 -0
  113. package/lib/sexpr/classes/RenderCache.ts +221 -0
  114. package/lib/sexpr/classes/SchematicText.ts +141 -0
  115. package/lib/sexpr/classes/Segment.ts +222 -0
  116. package/lib/sexpr/classes/SegmentEnd.ts +59 -0
  117. package/lib/sexpr/classes/SegmentLocked.ts +33 -0
  118. package/lib/sexpr/classes/SegmentNet.ts +62 -0
  119. package/lib/sexpr/classes/SegmentStart.ts +59 -0
  120. package/lib/sexpr/classes/Setup/PcbPlotParams.ts +729 -0
  121. package/lib/sexpr/classes/Setup/PcbPlotParamsBase.ts +9 -0
  122. package/lib/sexpr/classes/Setup/PcbPlotParamsNumericProperties.ts +105 -0
  123. package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesA.ts +104 -0
  124. package/lib/sexpr/classes/Setup/PcbPlotParamsStringPropertiesB.ts +105 -0
  125. package/lib/sexpr/classes/Setup/Setup.ts +573 -0
  126. package/lib/sexpr/classes/Setup/SetupPropertyTypes.ts +119 -0
  127. package/lib/sexpr/classes/Setup/Stackup.ts +140 -0
  128. package/lib/sexpr/classes/Setup/StackupLayer.ts +233 -0
  129. package/lib/sexpr/classes/Setup/StackupLayerProperties.ts +78 -0
  130. package/lib/sexpr/classes/Setup/StackupProperties.ts +41 -0
  131. package/lib/sexpr/classes/Setup/base.ts +167 -0
  132. package/lib/sexpr/classes/Setup/index.ts +14 -0
  133. package/lib/sexpr/classes/Setup/setupMultiValueProperties.ts +54 -0
  134. package/lib/sexpr/classes/Setup/setupNumericProperties.ts +151 -0
  135. package/lib/sexpr/classes/Setup/setupPropertyHandlers.ts +90 -0
  136. package/lib/sexpr/classes/Setup/setupStringProperties.ts +75 -0
  137. package/lib/sexpr/classes/Sheet.ts +205 -0
  138. package/lib/sexpr/classes/SheetFill.ts +44 -0
  139. package/lib/sexpr/classes/SheetInstances.ts +168 -0
  140. package/lib/sexpr/classes/SheetInstancesRoot.ts +165 -0
  141. package/lib/sexpr/classes/SheetPin.ts +122 -0
  142. package/lib/sexpr/classes/SheetProperty.ts +115 -0
  143. package/lib/sexpr/classes/SheetSize.ts +44 -0
  144. package/lib/sexpr/classes/Stroke.ts +58 -0
  145. package/lib/sexpr/classes/StrokeType.ts +34 -0
  146. package/lib/sexpr/classes/Symbol.ts +1541 -0
  147. package/lib/sexpr/classes/TextEffects.ts +444 -0
  148. package/lib/sexpr/classes/TitleBlock.ts +352 -0
  149. package/lib/sexpr/classes/Unit.ts +28 -0
  150. package/lib/sexpr/classes/Uuid.ts +8 -0
  151. package/lib/sexpr/classes/Via.ts +328 -0
  152. package/lib/sexpr/classes/ViaNet.ts +59 -0
  153. package/lib/sexpr/classes/Width.ts +8 -0
  154. package/lib/sexpr/classes/Wire.ts +91 -0
  155. package/lib/sexpr/classes/Xy.ts +35 -0
  156. package/lib/sexpr/classes/Zone.ts +41 -0
  157. package/lib/sexpr/index.ts +130 -0
  158. package/lib/sexpr/parseKicadSexpr.ts +5 -0
  159. package/lib/sexpr/parseToPrimitiveSExpr.ts +240 -0
  160. package/lib/sexpr/utils/indentLines.ts +3 -0
  161. package/lib/sexpr/utils/parseYesNo.ts +12 -0
  162. package/lib/sexpr/utils/quoteSExprString.ts +8 -0
  163. package/lib/sexpr/utils/strokeFromArgs.ts +19 -0
  164. package/lib/sexpr/utils/toNumberValue.ts +13 -0
  165. package/lib/sexpr/utils/toStringValue.ts +10 -0
  166. package/package.json +26 -0
  167. package/scripts/download-references.ts +66 -0
  168. package/tests/fixtures/expectEqualPrimitiveSExpr.ts +200 -0
  169. package/tests/sexpr/KicadPcbDemos.test.ts +48 -0
  170. package/tests/sexpr/KicadSchDemos.test.ts +49 -0
  171. package/tests/sexpr/classes/Footprint.test.ts +277 -0
  172. package/tests/sexpr/classes/FootprintPad.test.ts +71 -0
  173. package/tests/sexpr/classes/FpArc.test.ts +45 -0
  174. package/tests/sexpr/classes/FpCircle.test.ts +39 -0
  175. package/tests/sexpr/classes/FpPoly.test.ts +43 -0
  176. package/tests/sexpr/classes/FpRect.test.ts +40 -0
  177. package/tests/sexpr/classes/FpTextBox.test.ts +84 -0
  178. package/tests/sexpr/classes/Image.test.ts +50 -0
  179. package/tests/sexpr/classes/KicadSch.test.ts +97 -0
  180. package/tests/sexpr/classes/Paper.test.ts +30 -0
  181. package/tests/sexpr/classes/Property.test.ts +48 -0
  182. package/tests/sexpr/classes/Setup.test.ts +189 -0
  183. package/tests/sexpr/classes/Sheet.test.ts +107 -0
  184. package/tests/sexpr/classes/Stroke.test.ts +15 -0
  185. package/tests/sexpr/classes/Symbol.test.ts +96 -0
  186. package/tests/sexpr/classes/TextEffects.test.ts +56 -0
  187. package/tests/sexpr/classes/TitleBlock.test.ts +40 -0
  188. package/tsconfig.json +35 -0
@@ -0,0 +1,1541 @@
1
+ import { SxClass } from "../base-classes/SxClass"
2
+ import { SxPrimitiveBoolean } from "../base-classes/SxPrimitiveBoolean"
3
+ import { SxPrimitiveNumber } from "../base-classes/SxPrimitiveNumber"
4
+ import { quoteSExprString } from "../utils/quoteSExprString"
5
+ import { indentLines } from "../utils/indentLines"
6
+ import { toNumberValue } from "../utils/toNumberValue"
7
+ import { toStringValue } from "../utils/toStringValue"
8
+ import type { PrimitiveSExpr } from "../parseToPrimitiveSExpr"
9
+ import { At } from "./At"
10
+ import { Dnp } from "./Dnp"
11
+ import { EmbeddedFonts } from "./EmbeddedFonts"
12
+ import { ExcludeFromSim } from "./ExcludeFromSim"
13
+ import { InBom } from "./InBom"
14
+ import { OnBoard } from "./OnBoard"
15
+ import { FieldsAutoplaced } from "./FieldsAutoplaced"
16
+ import { TextEffects } from "./TextEffects"
17
+ import { Uuid } from "./Uuid"
18
+ import { Pts } from "./Pts"
19
+ import { Stroke } from "./Stroke"
20
+
21
+ export class SymbolUnit extends SxPrimitiveNumber {
22
+ static override token = "unit"
23
+ static override parentToken = "symbol"
24
+ token = "unit"
25
+
26
+ static from(value: number | SymbolUnit): SymbolUnit {
27
+ if (value instanceof SymbolUnit) {
28
+ return value
29
+ }
30
+ return new SymbolUnit(value)
31
+ }
32
+ }
33
+ SxClass.register(SymbolUnit)
34
+
35
+ export class SymbolLibId extends SxClass {
36
+ static override token = "lib_id"
37
+ static override parentToken = "symbol"
38
+ token = "lib_id"
39
+
40
+ value: string
41
+
42
+ constructor(value: string) {
43
+ super()
44
+ this.value = value
45
+ }
46
+
47
+ static override fromSexprPrimitives(
48
+ primitiveSexprs: PrimitiveSExpr[],
49
+ ): SymbolLibId {
50
+ const [valuePrimitive] = primitiveSexprs
51
+ const value = toStringValue(valuePrimitive)
52
+ if (value === undefined) {
53
+ throw new Error("lib_id expects a string value")
54
+ }
55
+ return new SymbolLibId(value)
56
+ }
57
+
58
+ override getChildren(): SxClass[] {
59
+ return []
60
+ }
61
+
62
+ override getString(): string {
63
+ return `(lib_id ${quoteSExprString(this.value)})`
64
+ }
65
+ }
66
+ SxClass.register(SymbolLibId)
67
+
68
+ export class SymbolDuplicatePinNumbersAreJumpers extends SxPrimitiveBoolean {
69
+ static override token = "duplicate_pin_numbers_are_jumpers"
70
+ static override parentToken = "symbol"
71
+ token = "duplicate_pin_numbers_are_jumpers"
72
+ }
73
+ SxClass.register(SymbolDuplicatePinNumbersAreJumpers)
74
+
75
+ export class SymbolPinNumbers extends SxClass {
76
+ static override token = "pin_numbers"
77
+ static override parentToken = "symbol"
78
+ token = "pin_numbers"
79
+
80
+ private _sxHide?: SymbolPinNumbersHide
81
+
82
+ static override fromSexprPrimitives(
83
+ primitiveSexprs: PrimitiveSExpr[],
84
+ ): SymbolPinNumbers {
85
+ const pinNumbers = new SymbolPinNumbers()
86
+ const primitiveStrings: string[] = []
87
+ const primitiveNodes: PrimitiveSExpr[] = []
88
+ for (const primitive of primitiveSexprs) {
89
+ if (typeof primitive === "string") {
90
+ primitiveStrings.push(primitive)
91
+ continue
92
+ }
93
+ primitiveNodes.push(primitive)
94
+ }
95
+
96
+ const { propertyMap } =
97
+ SxClass.parsePrimitivesToClassProperties(primitiveNodes, this.token)
98
+
99
+ pinNumbers._sxHide = propertyMap.hide as SymbolPinNumbersHide
100
+
101
+ for (const flag of primitiveStrings) {
102
+ if (flag === "hide") {
103
+ pinNumbers._sxHide = new SymbolPinNumbersHide(true, { inline: true })
104
+ continue
105
+ }
106
+ throw new Error(
107
+ `symbol pin_numbers encountered unsupported flag "${flag}"`,
108
+ )
109
+ }
110
+
111
+ return pinNumbers
112
+ }
113
+
114
+ get hide(): boolean {
115
+ return this._sxHide?.value ?? false
116
+ }
117
+
118
+ set hide(value: boolean) {
119
+ this._sxHide = new SymbolPinNumbersHide(value)
120
+ }
121
+
122
+ override getChildren(): SxClass[] {
123
+ return this._sxHide ? [this._sxHide] : []
124
+ }
125
+ }
126
+ SxClass.register(SymbolPinNumbers)
127
+
128
+ export class SymbolPinNumbersHide extends SxPrimitiveBoolean {
129
+ static override token = "hide"
130
+ static override parentToken = "pin_numbers"
131
+ token = "hide"
132
+
133
+ private inline = false
134
+
135
+ constructor(value?: boolean, options: { inline?: boolean } = {}) {
136
+ super(value ?? true)
137
+ this.inline = options.inline ?? false
138
+ }
139
+
140
+ override getString(): string {
141
+ if (this.inline) {
142
+ return this.value ? "hide" : "(hide no)"
143
+ }
144
+ return super.getString()
145
+ }
146
+ }
147
+ SxClass.register(SymbolPinNumbersHide)
148
+
149
+ export class SymbolPinNames extends SxClass {
150
+ static override token = "pin_names"
151
+ static override parentToken = "symbol"
152
+ token = "pin_names"
153
+
154
+ private _sxOffset?: SymbolPinNamesOffset
155
+ private _sxHide?: SymbolPinNamesHide
156
+
157
+ static override fromSexprPrimitives(
158
+ primitiveSexprs: PrimitiveSExpr[],
159
+ ): SymbolPinNames {
160
+ const pinNames = new SymbolPinNames()
161
+ const { propertyMap } =
162
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
163
+
164
+ pinNames._sxOffset = propertyMap.offset as SymbolPinNamesOffset
165
+ pinNames._sxHide = propertyMap.hide as SymbolPinNamesHide
166
+
167
+ return pinNames
168
+ }
169
+
170
+ get offset(): number | undefined {
171
+ return this._sxOffset?.value
172
+ }
173
+
174
+ set offset(value: number | undefined) {
175
+ if (value === undefined) {
176
+ this._sxOffset = undefined
177
+ return
178
+ }
179
+ this._sxOffset = new SymbolPinNamesOffset(value)
180
+ }
181
+
182
+ get hide(): boolean {
183
+ return this._sxHide?.value ?? false
184
+ }
185
+
186
+ set hide(value: boolean) {
187
+ this._sxHide = new SymbolPinNamesHide(value)
188
+ }
189
+
190
+ override getChildren(): SxClass[] {
191
+ const children: SxClass[] = []
192
+ if (this._sxOffset) children.push(this._sxOffset)
193
+ if (this._sxHide) children.push(this._sxHide)
194
+ return children
195
+ }
196
+ }
197
+ SxClass.register(SymbolPinNames)
198
+
199
+ export class SymbolPinNamesOffset extends SxClass {
200
+ static override token = "offset"
201
+ static override parentToken = "pin_names"
202
+ token = "offset"
203
+
204
+ value: number
205
+
206
+ constructor(value: number) {
207
+ super()
208
+ this.value = value
209
+ }
210
+
211
+ static override fromSexprPrimitives(
212
+ primitiveSexprs: PrimitiveSExpr[],
213
+ ): SymbolPinNamesOffset {
214
+ const [valuePrimitive] = primitiveSexprs
215
+ const value = toNumberValue(valuePrimitive)
216
+ if (value === undefined) {
217
+ throw new Error("pin_names offset expects a numeric value")
218
+ }
219
+ return new SymbolPinNamesOffset(value)
220
+ }
221
+
222
+ override getChildren(): SxClass[] {
223
+ return []
224
+ }
225
+
226
+ override getString(): string {
227
+ return `(offset ${this.value})`
228
+ }
229
+ }
230
+ SxClass.register(SymbolPinNamesOffset)
231
+
232
+ export class SymbolPinNamesHide extends SxPrimitiveBoolean {
233
+ static override token = "hide"
234
+ static override parentToken = "pin_names"
235
+ token = "hide"
236
+ }
237
+ SxClass.register(SymbolPinNamesHide)
238
+
239
+ abstract class SymbolPointBase extends SxClass {
240
+ protected _x: number
241
+ protected _y: number
242
+
243
+ constructor(x: number, y: number) {
244
+ super()
245
+ this._x = x
246
+ this._y = y
247
+ }
248
+
249
+ static override fromSexprPrimitives(
250
+ primitiveSexprs: PrimitiveSExpr[],
251
+ ): SymbolPointBase {
252
+ const [rawX, rawY] = primitiveSexprs
253
+ const x = toNumberValue(rawX)
254
+ const y = toNumberValue(rawY)
255
+ if (x === undefined || y === undefined) {
256
+ throw new Error(`${this.name} expects two numeric arguments`)
257
+ }
258
+ const Ctor = this as unknown as new (x: number, y: number) => SymbolPointBase
259
+ return new Ctor(x, y)
260
+ }
261
+
262
+ get x(): number {
263
+ return this._x
264
+ }
265
+
266
+ set x(value: number) {
267
+ this._x = value
268
+ }
269
+
270
+ get y(): number {
271
+ return this._y
272
+ }
273
+
274
+ set y(value: number) {
275
+ this._y = value
276
+ }
277
+
278
+ toObject(): { x: number; y: number } {
279
+ return { x: this._x, y: this._y }
280
+ }
281
+
282
+ override getChildren(): SxClass[] {
283
+ return []
284
+ }
285
+
286
+ override getString(): string {
287
+ return `(${this.token} ${this._x} ${this._y})`
288
+ }
289
+ }
290
+
291
+ export class SymbolRectangleStart extends SymbolPointBase {
292
+ static override token = "start"
293
+ static override parentToken = "rectangle"
294
+ token = "start"
295
+ }
296
+ SxClass.register(SymbolRectangleStart)
297
+
298
+ export class SymbolRectangleEnd extends SymbolPointBase {
299
+ static override token = "end"
300
+ static override parentToken = "rectangle"
301
+ token = "end"
302
+ }
303
+ SxClass.register(SymbolRectangleEnd)
304
+
305
+ export class SymbolArcStart extends SymbolPointBase {
306
+ static override token = "start"
307
+ static override parentToken = "arc"
308
+ token = "start"
309
+ }
310
+ SxClass.register(SymbolArcStart)
311
+
312
+ export class SymbolArcMid extends SymbolPointBase {
313
+ static override token = "mid"
314
+ static override parentToken = "arc"
315
+ token = "mid"
316
+ }
317
+ SxClass.register(SymbolArcMid)
318
+
319
+ export class SymbolArcEnd extends SymbolPointBase {
320
+ static override token = "end"
321
+ static override parentToken = "arc"
322
+ token = "end"
323
+ }
324
+ SxClass.register(SymbolArcEnd)
325
+
326
+ export class SymbolCircleCenter extends SymbolPointBase {
327
+ static override token = "center"
328
+ static override parentToken = "circle"
329
+ token = "center"
330
+ }
331
+ SxClass.register(SymbolCircleCenter)
332
+
333
+ export class SymbolCircleRadius extends SxPrimitiveNumber {
334
+ static override token = "radius"
335
+ static override parentToken = "circle"
336
+ token = "radius"
337
+ }
338
+ SxClass.register(SymbolCircleRadius)
339
+
340
+ abstract class SymbolFillBase extends SxClass {
341
+ protected _sxType?: SymbolFillType
342
+
343
+ static override fromSexprPrimitives(
344
+ primitiveSexprs: PrimitiveSExpr[],
345
+ ): SymbolFillBase {
346
+ const fill = new (this as unknown as new () => SymbolFillBase)()
347
+ const { propertyMap } =
348
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, "fill")
349
+ fill._sxType = propertyMap.type as SymbolFillType
350
+ return fill
351
+ }
352
+
353
+ get type(): string | undefined {
354
+ return this._sxType?.value
355
+ }
356
+
357
+ set type(value: string | undefined) {
358
+ if (value === undefined) {
359
+ this._sxType = undefined
360
+ return
361
+ }
362
+ this._sxType = new SymbolFillType(value)
363
+ }
364
+
365
+ override getChildren(): SxClass[] {
366
+ return this._sxType ? [this._sxType] : []
367
+ }
368
+ }
369
+
370
+ export class SymbolPolylineFill extends SymbolFillBase {
371
+ static override token = "fill"
372
+ static override parentToken = "polyline"
373
+ token = "fill"
374
+ }
375
+ SxClass.register(SymbolPolylineFill)
376
+
377
+ export class SymbolRectangleFill extends SymbolFillBase {
378
+ static override token = "fill"
379
+ static override parentToken = "rectangle"
380
+ token = "fill"
381
+ }
382
+ SxClass.register(SymbolRectangleFill)
383
+
384
+ export class SymbolCircleFill extends SymbolFillBase {
385
+ static override token = "fill"
386
+ static override parentToken = "circle"
387
+ token = "fill"
388
+ }
389
+ SxClass.register(SymbolCircleFill)
390
+
391
+ export class SymbolArcFill extends SymbolFillBase {
392
+ static override token = "fill"
393
+ static override parentToken = "arc"
394
+ token = "fill"
395
+ }
396
+ SxClass.register(SymbolArcFill)
397
+
398
+ export class SymbolFillType extends SxClass {
399
+ static override token = "type"
400
+ static override parentToken = "fill"
401
+ token = "type"
402
+
403
+ value: string
404
+
405
+ constructor(value: string) {
406
+ super()
407
+ this.value = value
408
+ }
409
+
410
+ static override fromSexprPrimitives(
411
+ primitiveSexprs: PrimitiveSExpr[],
412
+ ): SymbolFillType {
413
+ const [valuePrimitive] = primitiveSexprs
414
+ const value = toStringValue(valuePrimitive)
415
+ if (value === undefined) {
416
+ throw new Error("fill type expects a string value")
417
+ }
418
+ return new SymbolFillType(value)
419
+ }
420
+
421
+ override getChildren(): SxClass[] {
422
+ return []
423
+ }
424
+
425
+ override getString(): string {
426
+ return `(type ${this.value})`
427
+ }
428
+ }
429
+ SxClass.register(SymbolFillType)
430
+
431
+ export class SymbolPolyline extends SxClass {
432
+ static override token = "polyline"
433
+ static override parentToken = "symbol"
434
+ token = "polyline"
435
+
436
+ private _sxPts?: Pts
437
+ private _sxStroke?: Stroke
438
+ private _sxFill?: SymbolPolylineFill
439
+
440
+ static override fromSexprPrimitives(
441
+ primitiveSexprs: PrimitiveSExpr[],
442
+ ): SymbolPolyline {
443
+ const polyline = new SymbolPolyline()
444
+ const { propertyMap } =
445
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
446
+
447
+ polyline._sxPts = propertyMap.pts as Pts
448
+ polyline._sxStroke = propertyMap.stroke as Stroke
449
+ polyline._sxFill = propertyMap.fill as SymbolPolylineFill
450
+
451
+ return polyline
452
+ }
453
+
454
+ get points(): Pts | undefined {
455
+ return this._sxPts
456
+ }
457
+
458
+ set points(value: Pts | undefined) {
459
+ this._sxPts = value
460
+ }
461
+
462
+ get stroke(): Stroke | undefined {
463
+ return this._sxStroke
464
+ }
465
+
466
+ set stroke(value: Stroke | undefined) {
467
+ this._sxStroke = value
468
+ }
469
+
470
+ get fill(): SymbolPolylineFill | undefined {
471
+ return this._sxFill
472
+ }
473
+
474
+ set fill(value: SymbolPolylineFill | undefined) {
475
+ this._sxFill = value
476
+ }
477
+
478
+ override getChildren(): SxClass[] {
479
+ const children: SxClass[] = []
480
+ if (this._sxPts) children.push(this._sxPts)
481
+ if (this._sxStroke) children.push(this._sxStroke)
482
+ if (this._sxFill) children.push(this._sxFill)
483
+ return children
484
+ }
485
+ }
486
+ SxClass.register(SymbolPolyline)
487
+
488
+ export class SymbolRectangle extends SxClass {
489
+ static override token = "rectangle"
490
+ static override parentToken = "symbol"
491
+ token = "rectangle"
492
+
493
+ private _sxStart?: SymbolRectangleStart
494
+ private _sxEnd?: SymbolRectangleEnd
495
+ private _sxStroke?: Stroke
496
+ private _sxFill?: SymbolRectangleFill
497
+
498
+ static override fromSexprPrimitives(
499
+ primitiveSexprs: PrimitiveSExpr[],
500
+ ): SymbolRectangle {
501
+ const rectangle = new SymbolRectangle()
502
+ const { propertyMap } =
503
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
504
+
505
+ rectangle._sxStart = propertyMap.start as SymbolRectangleStart
506
+ rectangle._sxEnd = propertyMap.end as SymbolRectangleEnd
507
+ rectangle._sxStroke = propertyMap.stroke as Stroke
508
+ rectangle._sxFill = propertyMap.fill as SymbolRectangleFill
509
+
510
+ return rectangle
511
+ }
512
+
513
+ override getChildren(): SxClass[] {
514
+ const children: SxClass[] = []
515
+ if (this._sxStart) children.push(this._sxStart)
516
+ if (this._sxEnd) children.push(this._sxEnd)
517
+ if (this._sxStroke) children.push(this._sxStroke)
518
+ if (this._sxFill) children.push(this._sxFill)
519
+ return children
520
+ }
521
+ }
522
+ SxClass.register(SymbolRectangle)
523
+
524
+ export class SymbolCircle extends SxClass {
525
+ static override token = "circle"
526
+ static override parentToken = "symbol"
527
+ token = "circle"
528
+
529
+ private _sxCenter?: SymbolCircleCenter
530
+ private _sxRadius?: SymbolCircleRadius
531
+ private _sxStroke?: Stroke
532
+ private _sxFill?: SymbolCircleFill
533
+
534
+ static override fromSexprPrimitives(
535
+ primitiveSexprs: PrimitiveSExpr[],
536
+ ): SymbolCircle {
537
+ const circle = new SymbolCircle()
538
+ const { propertyMap } =
539
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
540
+
541
+ circle._sxCenter = propertyMap.center as SymbolCircleCenter
542
+ circle._sxRadius = propertyMap.radius as SymbolCircleRadius
543
+ circle._sxStroke = propertyMap.stroke as Stroke
544
+ circle._sxFill = propertyMap.fill as SymbolCircleFill
545
+
546
+ return circle
547
+ }
548
+
549
+ override getChildren(): SxClass[] {
550
+ const children: SxClass[] = []
551
+ if (this._sxCenter) children.push(this._sxCenter)
552
+ if (this._sxRadius) children.push(this._sxRadius)
553
+ if (this._sxStroke) children.push(this._sxStroke)
554
+ if (this._sxFill) children.push(this._sxFill)
555
+ return children
556
+ }
557
+ }
558
+ SxClass.register(SymbolCircle)
559
+
560
+ export class SymbolArc extends SxClass {
561
+ static override token = "arc"
562
+ static override parentToken = "symbol"
563
+ token = "arc"
564
+
565
+ private _sxStart?: SymbolArcStart
566
+ private _sxMid?: SymbolArcMid
567
+ private _sxEnd?: SymbolArcEnd
568
+ private _sxStroke?: Stroke
569
+ private _sxFill?: SymbolArcFill
570
+
571
+ static override fromSexprPrimitives(
572
+ primitiveSexprs: PrimitiveSExpr[],
573
+ ): SymbolArc {
574
+ const arc = new SymbolArc()
575
+ const { propertyMap } =
576
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
577
+
578
+ arc._sxStart = propertyMap.start as SymbolArcStart
579
+ arc._sxMid = propertyMap.mid as SymbolArcMid
580
+ arc._sxEnd = propertyMap.end as SymbolArcEnd
581
+ arc._sxStroke = propertyMap.stroke as Stroke
582
+ arc._sxFill = propertyMap.fill as SymbolArcFill
583
+
584
+ return arc
585
+ }
586
+
587
+ override getChildren(): SxClass[] {
588
+ const children: SxClass[] = []
589
+ if (this._sxStart) children.push(this._sxStart)
590
+ if (this._sxMid) children.push(this._sxMid)
591
+ if (this._sxEnd) children.push(this._sxEnd)
592
+ if (this._sxStroke) children.push(this._sxStroke)
593
+ if (this._sxFill) children.push(this._sxFill)
594
+ return children
595
+ }
596
+ }
597
+ SxClass.register(SymbolArc)
598
+
599
+ export class SymbolText extends SxClass {
600
+ static override token = "text"
601
+ static override parentToken = "symbol"
602
+ token = "text"
603
+
604
+ private _value = ""
605
+ private _sxAt?: At
606
+ private _sxEffects?: TextEffects
607
+
608
+ static override fromSexprPrimitives(
609
+ primitiveSexprs: PrimitiveSExpr[],
610
+ ): SymbolText {
611
+ const [valuePrimitive, ...rest] = primitiveSexprs
612
+ const value = toStringValue(valuePrimitive)
613
+ if (value === undefined) {
614
+ throw new Error("text expects a string value")
615
+ }
616
+
617
+ const text = new SymbolText()
618
+ text._value = value
619
+
620
+ const { propertyMap } =
621
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
622
+
623
+ text._sxAt = propertyMap.at as At
624
+ text._sxEffects = propertyMap.effects as TextEffects
625
+
626
+ return text
627
+ }
628
+
629
+ get value(): string {
630
+ return this._value
631
+ }
632
+
633
+ set value(newValue: string) {
634
+ this._value = newValue
635
+ }
636
+
637
+ get at(): At | undefined {
638
+ return this._sxAt
639
+ }
640
+
641
+ set at(value: At | undefined) {
642
+ this._sxAt = value
643
+ }
644
+
645
+ get effects(): TextEffects | undefined {
646
+ return this._sxEffects
647
+ }
648
+
649
+ set effects(value: TextEffects | undefined) {
650
+ this._sxEffects = value
651
+ }
652
+
653
+ override getChildren(): SxClass[] {
654
+ const children: SxClass[] = []
655
+ if (this._sxAt) children.push(this._sxAt)
656
+ if (this._sxEffects) children.push(this._sxEffects)
657
+ return children
658
+ }
659
+
660
+ override getString(): string {
661
+ const lines = [`(text ${quoteSExprString(this._value)}`]
662
+ for (const child of this.getChildren()) {
663
+ lines.push(child.getStringIndented())
664
+ }
665
+ lines.push(")")
666
+ return lines.join("\n")
667
+ }
668
+ }
669
+ SxClass.register(SymbolText)
670
+
671
+ export class SymbolPower extends SxClass {
672
+ static override token = "power"
673
+ static override parentToken = "symbol"
674
+ token = "power"
675
+
676
+ static override fromSexprPrimitives(): SymbolPower {
677
+ return new SymbolPower()
678
+ }
679
+
680
+ override getChildren(): SxClass[] {
681
+ return []
682
+ }
683
+
684
+ override getString(): string {
685
+ return "(power)"
686
+ }
687
+ }
688
+ SxClass.register(SymbolPower)
689
+
690
+ export class SchematicSymbol extends SxClass {
691
+ static override token = "symbol"
692
+ token = "symbol"
693
+
694
+ private _sxLibId?: SymbolLibId
695
+ _sxAt?: At
696
+ _sxUnit?: SymbolUnit
697
+ _sxPinNumbers?: SymbolPinNumbers
698
+ _sxPinNames?: SymbolPinNames
699
+ _sxExcludeFromSim?: ExcludeFromSim
700
+ _sxInBom?: InBom
701
+ _sxOnBoard?: OnBoard
702
+ _sxDnp?: Dnp
703
+ _sxUuid?: Uuid
704
+ _sxDuplicatePinNumbersAreJumpers?: SymbolDuplicatePinNumbersAreJumpers
705
+ _sxFieldsAutoplaced?: FieldsAutoplaced
706
+ properties: SymbolProperty[] = []
707
+ pins: SymbolPin[] = []
708
+ subSymbols: SchematicSymbol[] = []
709
+ polylines: SymbolPolyline[] = []
710
+ rectangles: SymbolRectangle[] = []
711
+ circles: SymbolCircle[] = []
712
+ arcs: SymbolArc[] = []
713
+ texts: SymbolText[] = []
714
+ _sxPower?: SymbolPower
715
+ _sxEmbeddedFonts?: EmbeddedFonts
716
+ _sxInstances?: SymbolInstances
717
+ private _inlineLibId?: string
718
+
719
+ get libraryId(): string | undefined {
720
+ return this._sxLibId?.value ?? this._inlineLibId
721
+ }
722
+
723
+ set libraryId(value: string | undefined) {
724
+ if (value === undefined || value === "") {
725
+ this._inlineLibId = undefined
726
+ if (this._sxLibId) {
727
+ this._sxLibId = undefined
728
+ }
729
+ return
730
+ }
731
+ this._inlineLibId = value
732
+ this._sxLibId = undefined
733
+ }
734
+
735
+ get at(): At | undefined {
736
+ return this._sxAt
737
+ }
738
+
739
+ set at(value: At | undefined) {
740
+ this._sxAt = value
741
+ }
742
+
743
+ get unit(): number | undefined {
744
+ return this._sxUnit?.value
745
+ }
746
+
747
+ set unit(value: number | undefined) {
748
+ this._sxUnit = value === undefined ? undefined : SymbolUnit.from(value)
749
+ }
750
+
751
+ get pinNumbers(): SymbolPinNumbers | undefined {
752
+ return this._sxPinNumbers
753
+ }
754
+
755
+ set pinNumbers(value: SymbolPinNumbers | undefined) {
756
+ this._sxPinNumbers = value
757
+ }
758
+
759
+ get pinNames(): SymbolPinNames | undefined {
760
+ return this._sxPinNames
761
+ }
762
+
763
+ set pinNames(value: SymbolPinNames | undefined) {
764
+ this._sxPinNames = value
765
+ }
766
+
767
+ get inBom(): boolean | undefined {
768
+ return this._sxInBom?.value
769
+ }
770
+
771
+ set inBom(value: boolean | undefined) {
772
+ this._sxInBom = value === undefined ? undefined : new InBom(value)
773
+ }
774
+
775
+ get excludeFromSim(): boolean {
776
+ return this._sxExcludeFromSim?.value ?? false
777
+ }
778
+
779
+ set excludeFromSim(value: boolean) {
780
+ this._sxExcludeFromSim = new ExcludeFromSim(value)
781
+ }
782
+
783
+ get onBoard(): boolean | undefined {
784
+ return this._sxOnBoard?.value
785
+ }
786
+
787
+ set onBoard(value: boolean | undefined) {
788
+ this._sxOnBoard = value === undefined ? undefined : new OnBoard(value)
789
+ }
790
+
791
+ get dnp(): boolean {
792
+ return this._sxDnp?.value ?? false
793
+ }
794
+
795
+ set dnp(value: boolean) {
796
+ this._sxDnp = new Dnp(value)
797
+ }
798
+
799
+ get fieldsAutoplaced(): boolean {
800
+ return this._sxFieldsAutoplaced?.value ?? false
801
+ }
802
+
803
+ set fieldsAutoplaced(value: boolean) {
804
+ this._sxFieldsAutoplaced = new FieldsAutoplaced(value)
805
+ }
806
+
807
+ get uuid(): string | undefined {
808
+ return this._sxUuid?.value
809
+ }
810
+
811
+ set uuid(value: string | undefined) {
812
+ this._sxUuid = value === undefined ? undefined : new Uuid(value)
813
+ }
814
+
815
+ get duplicatePinNumbersAreJumpers(): boolean {
816
+ return this._sxDuplicatePinNumbersAreJumpers?.value ?? false
817
+ }
818
+
819
+ set duplicatePinNumbersAreJumpers(value: boolean | undefined) {
820
+ if (value === undefined) {
821
+ this._sxDuplicatePinNumbersAreJumpers = undefined
822
+ return
823
+ }
824
+ this._sxDuplicatePinNumbersAreJumpers = new SymbolDuplicatePinNumbersAreJumpers(value)
825
+ }
826
+
827
+ get instances(): SymbolInstances | undefined {
828
+ return this._sxInstances
829
+ }
830
+
831
+ set instances(value: SymbolInstances | undefined) {
832
+ this._sxInstances = value
833
+ }
834
+
835
+ static override fromSexprPrimitives(
836
+ primitiveSexprs: PrimitiveSExpr[],
837
+ ): SchematicSymbol {
838
+ const symbol = new SchematicSymbol()
839
+
840
+ let remaining = primitiveSexprs
841
+ let inlineId: string | undefined
842
+ if (remaining.length > 0) {
843
+ const first = remaining[0]
844
+ inlineId = toStringValue(first)
845
+ if (inlineId !== undefined) {
846
+ symbol._inlineLibId = inlineId
847
+ remaining = remaining.slice(1)
848
+ }
849
+ }
850
+
851
+ const { propertyMap, arrayPropertyMap } =
852
+ SxClass.parsePrimitivesToClassProperties(remaining, this.token)
853
+
854
+ const libIdClass = propertyMap.lib_id as SymbolLibId | undefined
855
+ if (libIdClass) {
856
+ symbol._sxLibId = libIdClass
857
+ } else if (inlineId !== undefined) {
858
+ symbol._inlineLibId = inlineId
859
+ }
860
+ symbol._sxAt = propertyMap.at as At
861
+ symbol._sxUnit = propertyMap.unit as SymbolUnit
862
+ symbol._sxPinNumbers = propertyMap.pin_numbers as SymbolPinNumbers
863
+ symbol._sxPinNames = propertyMap.pin_names as SymbolPinNames
864
+ symbol._sxExcludeFromSim = propertyMap.exclude_from_sim as ExcludeFromSim
865
+ symbol._sxInBom = propertyMap.in_bom as InBom
866
+ symbol._sxOnBoard = propertyMap.on_board as OnBoard
867
+ symbol._sxDnp = propertyMap.dnp as Dnp
868
+ symbol._sxUuid = propertyMap.uuid as Uuid
869
+ symbol._sxDuplicatePinNumbersAreJumpers =
870
+ propertyMap.duplicate_pin_numbers_are_jumpers as SymbolDuplicatePinNumbersAreJumpers
871
+ symbol._sxFieldsAutoplaced =
872
+ propertyMap.fields_autoplaced as FieldsAutoplaced
873
+ symbol._sxPower = propertyMap.power as SymbolPower
874
+ symbol._sxEmbeddedFonts = propertyMap.embedded_fonts as EmbeddedFonts
875
+ symbol.properties = (arrayPropertyMap.property as SymbolProperty[]) ?? []
876
+ symbol.pins = (arrayPropertyMap.pin as SymbolPin[]) ?? []
877
+ symbol.subSymbols = (arrayPropertyMap.symbol as SchematicSymbol[]) ?? []
878
+ symbol.polylines = (arrayPropertyMap.polyline as SymbolPolyline[]) ?? []
879
+ symbol.rectangles = (arrayPropertyMap.rectangle as SymbolRectangle[]) ?? []
880
+ symbol.circles = (arrayPropertyMap.circle as SymbolCircle[]) ?? []
881
+ symbol.arcs = (arrayPropertyMap.arc as SymbolArc[]) ?? []
882
+ symbol.texts = (arrayPropertyMap.text as SymbolText[]) ?? []
883
+ symbol._sxInstances = propertyMap.instances as SymbolInstances
884
+
885
+ return symbol
886
+ }
887
+
888
+ override getChildren(): SxClass[] {
889
+ const children: SxClass[] = []
890
+ if (this._sxLibId) children.push(this._sxLibId)
891
+ if (this._sxAt) children.push(this._sxAt)
892
+ if (this._sxUnit) children.push(this._sxUnit)
893
+ if (this._sxPinNumbers) children.push(this._sxPinNumbers)
894
+ if (this._sxPinNames) children.push(this._sxPinNames)
895
+ if (this._sxExcludeFromSim) children.push(this._sxExcludeFromSim)
896
+ if (this._sxInBom) children.push(this._sxInBom)
897
+ if (this._sxOnBoard) children.push(this._sxOnBoard)
898
+ if (this._sxDnp) children.push(this._sxDnp)
899
+ if (this._sxUuid) children.push(this._sxUuid)
900
+ if (this._sxDuplicatePinNumbersAreJumpers) {
901
+ children.push(this._sxDuplicatePinNumbersAreJumpers)
902
+ }
903
+ if (this._sxFieldsAutoplaced) children.push(this._sxFieldsAutoplaced)
904
+ children.push(...this.properties)
905
+ children.push(...this.pins)
906
+ children.push(...this.subSymbols)
907
+ children.push(...this.polylines)
908
+ children.push(...this.rectangles)
909
+ children.push(...this.circles)
910
+ children.push(...this.arcs)
911
+ children.push(...this.texts)
912
+ if (this._sxPower) children.push(this._sxPower)
913
+ if (this._sxEmbeddedFonts) children.push(this._sxEmbeddedFonts)
914
+ if (this._sxInstances) children.push(this._sxInstances)
915
+ return children
916
+ }
917
+
918
+ override getString() {
919
+ const inlineLibId = this._sxLibId ? undefined : this.libraryId
920
+ const lines =
921
+ inlineLibId !== undefined && inlineLibId !== ""
922
+ ? [`(symbol ${quoteSExprString(inlineLibId)}`]
923
+ : ["(symbol"]
924
+
925
+ for (const child of this.getChildren()) {
926
+ lines.push(child.getStringIndented())
927
+ }
928
+
929
+ lines.push(")")
930
+ return lines.join("\n")
931
+ }
932
+ }
933
+ SxClass.register(SchematicSymbol)
934
+
935
+ export class SymbolPropertyId extends SxPrimitiveNumber {
936
+ static override token = "id"
937
+ static override parentToken = "property"
938
+ token = "id"
939
+
940
+ static from(value: number | SymbolPropertyId): SymbolPropertyId {
941
+ if (value instanceof SymbolPropertyId) {
942
+ return value
943
+ }
944
+ return new SymbolPropertyId(value)
945
+ }
946
+ }
947
+ SxClass.register(SymbolPropertyId)
948
+
949
+ export class SymbolProperty extends SxClass {
950
+ static override token = "property"
951
+ static override parentToken = "symbol"
952
+ token = "property"
953
+
954
+ key: string
955
+ value: string
956
+ _sxId?: SymbolPropertyId
957
+ _sxAt?: At
958
+ _sxEffects?: TextEffects
959
+
960
+ constructor(params: {
961
+ key: string
962
+ value: string
963
+ id?: number | SymbolPropertyId
964
+ at?: At
965
+ effects?: TextEffects
966
+ }) {
967
+ super()
968
+ this.key = params.key
969
+ this.value = params.value
970
+ this._sxId = params.id !== undefined ? SymbolPropertyId.from(params.id) : undefined
971
+ this._sxAt = params.at
972
+ this._sxEffects = params.effects
973
+ }
974
+
975
+ static override fromSexprPrimitives(
976
+ primitiveSexprs: PrimitiveSExpr[],
977
+ ): SymbolProperty {
978
+ const [inputKey, inputValue, ...rest] = primitiveSexprs
979
+
980
+ const key = toStringValue(inputKey) ?? ""
981
+ const value = toStringValue(inputValue) ?? ""
982
+
983
+ const { propertyMap } =
984
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
985
+
986
+ return new SymbolProperty({
987
+ key,
988
+ value,
989
+ id: propertyMap.id as SymbolPropertyId,
990
+ at: propertyMap.at as At,
991
+ effects: propertyMap.effects as TextEffects,
992
+ })
993
+ }
994
+
995
+ get id(): number | undefined {
996
+ return this._sxId?.value
997
+ }
998
+
999
+ set id(value: number | undefined) {
1000
+ this._sxId = value === undefined ? undefined : SymbolPropertyId.from(value)
1001
+ }
1002
+
1003
+ get at(): At | undefined {
1004
+ return this._sxAt
1005
+ }
1006
+
1007
+ set at(value: At | undefined) {
1008
+ this._sxAt = value
1009
+ }
1010
+
1011
+ get effects(): TextEffects | undefined {
1012
+ return this._sxEffects
1013
+ }
1014
+
1015
+ set effects(value: TextEffects | undefined) {
1016
+ this._sxEffects = value
1017
+ }
1018
+
1019
+ override getChildren(): SxClass[] {
1020
+ const children: SxClass[] = []
1021
+ if (this._sxId) children.push(this._sxId)
1022
+ if (this._sxAt) children.push(this._sxAt)
1023
+ if (this._sxEffects) children.push(this._sxEffects)
1024
+ return children
1025
+ }
1026
+
1027
+ override getString() {
1028
+ const lines = [
1029
+ `(property ${quoteSExprString(this.key)} ${quoteSExprString(this.value)}`,
1030
+ ]
1031
+
1032
+ if (this._sxId) {
1033
+ lines.push(...indentLines(this._sxId.getString()))
1034
+ }
1035
+ if (this._sxAt) {
1036
+ lines.push(...indentLines(this._sxAt.getString()))
1037
+ }
1038
+ if (this._sxEffects) {
1039
+ lines.push(...indentLines(this._sxEffects.getString()))
1040
+ }
1041
+
1042
+ lines.push(")")
1043
+ return lines.join("\n")
1044
+ }
1045
+ }
1046
+ SxClass.register(SymbolProperty)
1047
+
1048
+ type PinElectricalType =
1049
+ | "input"
1050
+ | "output"
1051
+ | "bidirectional"
1052
+ | "tri_state"
1053
+ | "passive"
1054
+ | "free"
1055
+ | "unspecified"
1056
+ | "power_in"
1057
+ | "power_out"
1058
+ | "open_collector"
1059
+ | "open_emitter"
1060
+ | "no_connect"
1061
+
1062
+ type PinGraphicStyle =
1063
+ | "line"
1064
+ | "inverted"
1065
+ | "clock"
1066
+ | "inverted_clock"
1067
+ | "input_low"
1068
+ | "clock_low"
1069
+ | "output_low"
1070
+ | "edge_clock_high"
1071
+ | "non_logic"
1072
+
1073
+ const electricalTypeSet = new Set<PinElectricalType>(["input", "output", "bidirectional", "tri_state", "passive", "free", "unspecified", "power_in", "power_out", "open_collector", "open_emitter", "no_connect"])
1074
+ const graphicStyleSet = new Set<PinGraphicStyle>(["line", "inverted", "clock", "inverted_clock", "input_low", "clock_low", "output_low", "edge_clock_high", "non_logic"])
1075
+
1076
+ export class SymbolPinLength extends SxPrimitiveNumber {
1077
+ static override token = "length"
1078
+ static override parentToken = "pin"
1079
+ token = "length"
1080
+ }
1081
+ SxClass.register(SymbolPinLength)
1082
+
1083
+ export class SymbolPinName extends SxClass {
1084
+ static override token = "name"
1085
+ static override parentToken = "pin"
1086
+ token = "name"
1087
+
1088
+ value: string
1089
+ _sxEffects?: TextEffects
1090
+
1091
+ constructor(params: { value: string; effects?: TextEffects }) {
1092
+ super()
1093
+ this.value = params.value
1094
+ this._sxEffects = params.effects
1095
+ }
1096
+
1097
+ static override fromSexprPrimitives(
1098
+ primitiveSexprs: PrimitiveSExpr[],
1099
+ ): SymbolPinName {
1100
+ const [valuePrimitive, ...rest] = primitiveSexprs
1101
+ const value = toStringValue(valuePrimitive) ?? ""
1102
+ const { propertyMap } =
1103
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
1104
+
1105
+ return new SymbolPinName({
1106
+ value,
1107
+ effects: propertyMap.effects as TextEffects,
1108
+ })
1109
+ }
1110
+
1111
+ get effects(): TextEffects | undefined {
1112
+ return this._sxEffects
1113
+ }
1114
+
1115
+ set effects(value: TextEffects | undefined) {
1116
+ this._sxEffects = value
1117
+ }
1118
+
1119
+ override getChildren(): SxClass[] {
1120
+ return this._sxEffects ? [this._sxEffects] : []
1121
+ }
1122
+
1123
+ override getString(): string {
1124
+ const lines = [`(name ${quoteSExprString(this.value)}`]
1125
+ if (this._sxEffects) {
1126
+ lines.push(...indentLines(this._sxEffects.getString()))
1127
+ }
1128
+ lines.push(")")
1129
+ return lines.join("\n")
1130
+ }
1131
+ }
1132
+ SxClass.register(SymbolPinName)
1133
+
1134
+ export class SymbolPinNumber extends SxClass {
1135
+ static override token = "number"
1136
+ static override parentToken = "pin"
1137
+ token = "number"
1138
+
1139
+ value: string
1140
+ _sxEffects?: TextEffects
1141
+
1142
+ constructor(params: { value: string; effects?: TextEffects }) {
1143
+ super()
1144
+ this.value = params.value
1145
+ this._sxEffects = params.effects
1146
+ }
1147
+
1148
+ static override fromSexprPrimitives(
1149
+ primitiveSexprs: PrimitiveSExpr[],
1150
+ ): SymbolPinNumber {
1151
+ const [valuePrimitive, ...rest] = primitiveSexprs
1152
+ const value = toStringValue(valuePrimitive) ?? ""
1153
+ const { propertyMap } =
1154
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
1155
+
1156
+ return new SymbolPinNumber({
1157
+ value,
1158
+ effects: propertyMap.effects as TextEffects,
1159
+ })
1160
+ }
1161
+
1162
+ get effects(): TextEffects | undefined {
1163
+ return this._sxEffects
1164
+ }
1165
+
1166
+ set effects(value: TextEffects | undefined) {
1167
+ this._sxEffects = value
1168
+ }
1169
+
1170
+ override getChildren(): SxClass[] {
1171
+ return this._sxEffects ? [this._sxEffects] : []
1172
+ }
1173
+
1174
+ override getString(): string {
1175
+ const lines = [`(number ${quoteSExprString(this.value)}`]
1176
+ if (this._sxEffects) {
1177
+ lines.push(...indentLines(this._sxEffects.getString()))
1178
+ }
1179
+ lines.push(")")
1180
+ return lines.join("\n")
1181
+ }
1182
+ }
1183
+ SxClass.register(SymbolPinNumber)
1184
+
1185
+ export class SymbolPin extends SxClass {
1186
+ static override token = "pin"
1187
+ static override parentToken = "symbol"
1188
+ token = "pin"
1189
+
1190
+ pinElectricalType?: PinElectricalType
1191
+ pinGraphicStyle?: PinGraphicStyle
1192
+ _sxAt?: At
1193
+ _sxLength?: SymbolPinLength
1194
+ _sxName?: SymbolPinName
1195
+ _sxNumber?: SymbolPinNumber
1196
+ _sxUuid?: Uuid
1197
+ private inlineNumber?: string
1198
+ private _sxHide?: SymbolPinHide
1199
+
1200
+ static override fromSexprPrimitives(args: PrimitiveSExpr[]): SymbolPin {
1201
+ const symbolPin = new SymbolPin()
1202
+
1203
+ let index = 0
1204
+ const first = args[0]
1205
+ const firstString = toStringValue(first)
1206
+
1207
+ if (firstString && electricalTypeSet.has(firstString as PinElectricalType)) {
1208
+ symbolPin.pinElectricalType = firstString as PinElectricalType
1209
+ index = 1
1210
+ const second = args[1]
1211
+ const secondString = toStringValue(second)
1212
+ if (secondString && graphicStyleSet.has(secondString as PinGraphicStyle)) {
1213
+ symbolPin.pinGraphicStyle = secondString as PinGraphicStyle
1214
+ index = 2
1215
+ }
1216
+ } else if (firstString !== undefined && !Array.isArray(first)) {
1217
+ symbolPin.inlineNumber = firstString
1218
+ index = 1
1219
+ }
1220
+
1221
+ const remaining = args.slice(index)
1222
+
1223
+ const primitiveStrings: string[] = []
1224
+ const primitiveNodes: PrimitiveSExpr[] = []
1225
+ for (const primitive of remaining) {
1226
+ if (typeof primitive === "string") {
1227
+ primitiveStrings.push(primitive)
1228
+ continue
1229
+ }
1230
+ primitiveNodes.push(primitive)
1231
+ }
1232
+
1233
+ const { propertyMap } =
1234
+ SxClass.parsePrimitivesToClassProperties(primitiveNodes, this.token)
1235
+
1236
+ symbolPin._sxAt = propertyMap.at as At
1237
+ symbolPin._sxLength = propertyMap.length as SymbolPinLength
1238
+ symbolPin._sxName = propertyMap.name as SymbolPinName
1239
+ symbolPin._sxNumber = propertyMap.number as SymbolPinNumber
1240
+ symbolPin._sxUuid = propertyMap.uuid as Uuid
1241
+ symbolPin._sxHide = propertyMap.hide as SymbolPinHide | undefined
1242
+
1243
+ for (const flag of primitiveStrings) {
1244
+ if (flag === "hide") {
1245
+ symbolPin._sxHide = new SymbolPinHide(true, { inline: true })
1246
+ continue
1247
+ }
1248
+ throw new Error(`symbol pin encountered unsupported flag "${flag}"`)
1249
+ }
1250
+
1251
+ return symbolPin
1252
+ }
1253
+
1254
+ get at(): At | undefined {
1255
+ return this._sxAt
1256
+ }
1257
+
1258
+ set at(value: At | undefined) {
1259
+ this._sxAt = value
1260
+ }
1261
+
1262
+ get length(): number | undefined {
1263
+ return this._sxLength?.value
1264
+ }
1265
+
1266
+ set length(value: number | undefined) {
1267
+ this._sxLength = value === undefined ? undefined : new SymbolPinLength(value)
1268
+ }
1269
+
1270
+ get name(): string | undefined {
1271
+ return this._sxName?.value
1272
+ }
1273
+
1274
+ set name(value: string | undefined) {
1275
+ if (value === undefined) {
1276
+ this._sxName = undefined
1277
+ return
1278
+ }
1279
+ this._sxName = new SymbolPinName({ value })
1280
+ }
1281
+
1282
+ get numberString(): string | undefined {
1283
+ return this._sxNumber?.value ?? this.inlineNumber
1284
+ }
1285
+
1286
+ set numberString(value: string | undefined) {
1287
+ if (value === undefined) {
1288
+ this._sxNumber = undefined
1289
+ this.inlineNumber = undefined
1290
+ return
1291
+ }
1292
+ this.inlineNumber = value
1293
+ this._sxNumber = undefined
1294
+ }
1295
+
1296
+ get uuid(): string | undefined {
1297
+ return this._sxUuid?.value
1298
+ }
1299
+
1300
+ set uuid(value: string | undefined) {
1301
+ this._sxUuid = value === undefined ? undefined : new Uuid(value)
1302
+ }
1303
+
1304
+ get hidden(): boolean {
1305
+ return this._sxHide?.value ?? false
1306
+ }
1307
+
1308
+ set hidden(value: boolean) {
1309
+ this._sxHide = value ? new SymbolPinHide(value) : undefined
1310
+ }
1311
+
1312
+ override getChildren(): SxClass[] {
1313
+ const children: SxClass[] = []
1314
+ if (this._sxAt) children.push(this._sxAt)
1315
+ if (this._sxLength) children.push(this._sxLength)
1316
+ if (this._sxName) children.push(this._sxName)
1317
+ if (this._sxNumber) children.push(this._sxNumber)
1318
+ if (this._sxUuid) children.push(this._sxUuid)
1319
+ if (this._sxHide) children.push(this._sxHide)
1320
+ return children
1321
+ }
1322
+
1323
+ override getString() {
1324
+ if (this.pinElectricalType) {
1325
+ const headerParts = ["(pin", this.pinElectricalType]
1326
+ if (this.pinGraphicStyle) {
1327
+ headerParts.push(this.pinGraphicStyle)
1328
+ }
1329
+ const lines = [headerParts.join(" ")]
1330
+ for (const child of this.getChildren()) {
1331
+ lines.push(...indentLines(child.getString()))
1332
+ }
1333
+ lines.push(")")
1334
+ return lines.join("\n")
1335
+ }
1336
+
1337
+ const number = this.numberString ?? ""
1338
+ const lines = [`(pin ${quoteSExprString(number)}`]
1339
+ if (this._sxUuid) {
1340
+ lines.push(...indentLines(this._sxUuid.getString()))
1341
+ }
1342
+ lines.push(")")
1343
+ return lines.join("\n")
1344
+ }
1345
+ }
1346
+ SxClass.register(SymbolPin)
1347
+
1348
+ export class SymbolInstances extends SxClass {
1349
+ static override token = "instances"
1350
+ static override parentToken = "symbol"
1351
+ token = "instances"
1352
+
1353
+ projects: SymbolInstancesProject[] = []
1354
+
1355
+ static override fromSexprPrimitives(
1356
+ primitiveSexprs: PrimitiveSExpr[],
1357
+ ): SymbolInstances {
1358
+ const symbolInstances = new SymbolInstances()
1359
+ const { arrayPropertyMap } =
1360
+ SxClass.parsePrimitivesToClassProperties(primitiveSexprs, this.token)
1361
+
1362
+ symbolInstances.projects =
1363
+ (arrayPropertyMap.project as SymbolInstancesProject[]) ?? []
1364
+
1365
+ return symbolInstances
1366
+ }
1367
+
1368
+ override getChildren(): SxClass[] {
1369
+ return [...this.projects]
1370
+ }
1371
+
1372
+ override getString() {
1373
+ const lines = ["(instances"]
1374
+ for (const project of this.projects) {
1375
+ lines.push(project.getStringIndented())
1376
+ }
1377
+ lines.push(")")
1378
+ return lines.join("\n")
1379
+ }
1380
+ }
1381
+ SxClass.register(SymbolInstances)
1382
+
1383
+ class SymbolPinHide extends SxPrimitiveBoolean {
1384
+ static override token = "hide"
1385
+ static override parentToken = "pin"
1386
+ token = "hide"
1387
+
1388
+ private inline = false
1389
+
1390
+ constructor(value?: boolean, options: { inline?: boolean } = {}) {
1391
+ super(value ?? true)
1392
+ this.inline = options.inline ?? false
1393
+ }
1394
+
1395
+ override getString(): string {
1396
+ if (this.inline) {
1397
+ return this.value ? "hide" : "(hide no)"
1398
+ }
1399
+ return this.value ? "(hide yes)" : "(hide no)"
1400
+ }
1401
+ }
1402
+ SxClass.register(SymbolPinHide)
1403
+
1404
+ export class SymbolInstancesProject extends SxClass {
1405
+ static override token = "project"
1406
+ static override parentToken = "instances"
1407
+ token = "project"
1408
+
1409
+ name: string
1410
+ paths: SymbolInstancePath[] = []
1411
+
1412
+ constructor(name: string) {
1413
+ super()
1414
+ this.name = name
1415
+ }
1416
+
1417
+ static override fromSexprPrimitives(
1418
+ primitiveSexprs: PrimitiveSExpr[],
1419
+ ): SymbolInstancesProject {
1420
+ const [namePrimitive, ...rest] = primitiveSexprs
1421
+ const name = toStringValue(namePrimitive) ?? ""
1422
+ const project = new SymbolInstancesProject(name)
1423
+
1424
+ const { arrayPropertyMap } =
1425
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
1426
+
1427
+ project.paths = (arrayPropertyMap.path as SymbolInstancePath[]) ?? []
1428
+
1429
+ return project
1430
+ }
1431
+
1432
+ override getChildren(): SxClass[] {
1433
+ return [...this.paths]
1434
+ }
1435
+
1436
+ override getString() {
1437
+ const lines = [`(project ${quoteSExprString(this.name)}`]
1438
+ for (const path of this.paths) {
1439
+ lines.push(path.getStringIndented())
1440
+ }
1441
+ lines.push(")")
1442
+ return lines.join("\n")
1443
+ }
1444
+ }
1445
+ SxClass.register(SymbolInstancesProject)
1446
+
1447
+ export class SymbolInstancePath extends SxClass {
1448
+ static override token = "path"
1449
+ static override parentToken = "project"
1450
+ token = "path"
1451
+
1452
+ value: string
1453
+ _sxReference?: SymbolInstanceReference
1454
+ _sxUnit?: SymbolInstanceUnit
1455
+
1456
+ constructor(value: string) {
1457
+ super()
1458
+ this.value = value
1459
+ }
1460
+
1461
+ static override fromSexprPrimitives(
1462
+ primitiveSexprs: PrimitiveSExpr[],
1463
+ ): SymbolInstancePath {
1464
+ const [pathPrimitive, ...rest] = primitiveSexprs
1465
+ const value = toStringValue(pathPrimitive) ?? ""
1466
+ const path = new SymbolInstancePath(value)
1467
+
1468
+ const { propertyMap } =
1469
+ SxClass.parsePrimitivesToClassProperties(rest, this.token)
1470
+
1471
+ path._sxReference = propertyMap.reference as SymbolInstanceReference
1472
+ path._sxUnit = propertyMap.unit as SymbolInstanceUnit
1473
+
1474
+ return path
1475
+ }
1476
+
1477
+ get reference(): string | undefined {
1478
+ return this._sxReference?.value
1479
+ }
1480
+
1481
+ set reference(value: string | undefined) {
1482
+ this._sxReference = value === undefined ? undefined : new SymbolInstanceReference(value)
1483
+ }
1484
+
1485
+ get unit(): number | undefined {
1486
+ return this._sxUnit?.value
1487
+ }
1488
+
1489
+ set unit(value: number | undefined) {
1490
+ this._sxUnit = value === undefined ? undefined : new SymbolInstanceUnit(value)
1491
+ }
1492
+
1493
+ override getChildren(): SxClass[] {
1494
+ const children: SxClass[] = []
1495
+ if (this._sxReference) children.push(this._sxReference)
1496
+ if (this._sxUnit) children.push(this._sxUnit)
1497
+ return children
1498
+ }
1499
+
1500
+ override getString() {
1501
+ const lines = [`(path ${quoteSExprString(this.value)}`]
1502
+ for (const child of this.getChildren()) {
1503
+ lines.push(child.getStringIndented())
1504
+ }
1505
+ lines.push(")")
1506
+ return lines.join("\n")
1507
+ }
1508
+ }
1509
+ SxClass.register(SymbolInstancePath)
1510
+
1511
+ export class SymbolInstanceReference extends SxClass {
1512
+ static override token = "reference"
1513
+ static override parentToken = "path"
1514
+ token = "reference"
1515
+
1516
+ value: string
1517
+
1518
+ constructor(value: string) {
1519
+ super()
1520
+ this.value = value
1521
+ }
1522
+
1523
+ static override fromSexprPrimitives(
1524
+ primitiveSexprs: PrimitiveSExpr[],
1525
+ ): SymbolInstanceReference {
1526
+ const [valuePrimitive] = primitiveSexprs
1527
+ return new SymbolInstanceReference(toStringValue(valuePrimitive) ?? "")
1528
+ }
1529
+
1530
+ override getString(): string {
1531
+ return `(reference ${quoteSExprString(this.value)})`
1532
+ }
1533
+ }
1534
+ SxClass.register(SymbolInstanceReference)
1535
+
1536
+ export class SymbolInstanceUnit extends SxPrimitiveNumber {
1537
+ static override token = "unit"
1538
+ static override parentToken = "path"
1539
+ token = "unit"
1540
+ }
1541
+ SxClass.register(SymbolInstanceUnit)