circuitscript 0.1.31 → 0.1.33

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 (58) hide show
  1. package/dist/cjs/BaseVisitor.js +37 -3
  2. package/dist/cjs/RefdesAnnotationVisitor.js +27 -10
  3. package/dist/cjs/antlr/CircuitScriptParser.js +990 -831
  4. package/dist/cjs/draw_symbols.js +38 -34
  5. package/dist/cjs/environment.js +24 -4
  6. package/dist/cjs/execute.js +107 -68
  7. package/dist/cjs/globals.js +4 -2
  8. package/dist/cjs/graph.js +14 -12
  9. package/dist/cjs/helpers.js +85 -16
  10. package/dist/cjs/layout.js +50 -25
  11. package/dist/cjs/main.js +16 -18
  12. package/dist/cjs/objects/ClassComponent.js +199 -30
  13. package/dist/cjs/objects/types.js +5 -1
  14. package/dist/cjs/regenerate-tests.js +3 -3
  15. package/dist/cjs/render.js +5 -3
  16. package/dist/cjs/rules-check/no-connect-on-connected-pin.js +9 -8
  17. package/dist/cjs/rules-check/rules.js +7 -2
  18. package/dist/cjs/rules-check/unconnected-pins.js +10 -8
  19. package/dist/cjs/utils.js +2 -1
  20. package/dist/cjs/validate/SymbolValidatorVisitor.js +0 -10
  21. package/dist/cjs/visitor.js +284 -191
  22. package/dist/esm/BaseVisitor.js +37 -3
  23. package/dist/esm/RefdesAnnotationVisitor.js +27 -10
  24. package/dist/esm/antlr/CircuitScriptParser.js +989 -830
  25. package/dist/esm/antlr/CircuitScriptVisitor.js +1 -0
  26. package/dist/esm/draw_symbols.js +38 -34
  27. package/dist/esm/environment.js +21 -1
  28. package/dist/esm/execute.js +108 -69
  29. package/dist/esm/globals.js +2 -0
  30. package/dist/esm/graph.js +14 -12
  31. package/dist/esm/helpers.js +86 -17
  32. package/dist/esm/layout.js +51 -26
  33. package/dist/esm/main.js +16 -18
  34. package/dist/esm/objects/ClassComponent.js +201 -30
  35. package/dist/esm/objects/types.js +7 -1
  36. package/dist/esm/regenerate-tests.js +3 -3
  37. package/dist/esm/render.js +5 -3
  38. package/dist/esm/rules-check/no-connect-on-connected-pin.js +9 -8
  39. package/dist/esm/rules-check/rules.js +7 -2
  40. package/dist/esm/rules-check/unconnected-pins.js +10 -8
  41. package/dist/esm/utils.js +2 -1
  42. package/dist/esm/validate/SymbolValidatorVisitor.js +0 -10
  43. package/dist/esm/visitor.js +185 -92
  44. package/dist/types/BaseVisitor.d.ts +15 -5
  45. package/dist/types/RefdesAnnotationVisitor.d.ts +2 -0
  46. package/dist/types/antlr/CircuitScriptParser.d.ts +32 -14
  47. package/dist/types/antlr/CircuitScriptVisitor.d.ts +2 -0
  48. package/dist/types/environment.d.ts +7 -1
  49. package/dist/types/execute.d.ts +4 -1
  50. package/dist/types/globals.d.ts +2 -0
  51. package/dist/types/graph.d.ts +2 -2
  52. package/dist/types/helpers.d.ts +2 -1
  53. package/dist/types/layout.d.ts +5 -4
  54. package/dist/types/objects/ClassComponent.d.ts +34 -9
  55. package/dist/types/objects/types.d.ts +19 -3
  56. package/dist/types/validate/SymbolValidatorVisitor.d.ts +0 -4
  57. package/dist/types/visitor.d.ts +7 -1
  58. package/package.json +1 -1
@@ -167,137 +167,20 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
167
167
  if (ctxNotPathBlock) {
168
168
  this.visit(ctxNotPathBlock);
169
169
  }
170
+ if (ctx.start && ctx.stop) {
171
+ const startToken = ctx.start;
172
+ const stopToken = ctx.stop;
173
+ const annotationKey = this.getRefdesFileAnnotation(this.getCurrentFile(), startToken.line, startToken.column, stopToken.line, stopToken.column);
174
+ if (this.refdesFileAnnotations.has(annotationKey)) {
175
+ let refdesValue = this.refdesFileAnnotations.get(annotationKey);
176
+ refdesValue = refdesValue.split(',')[0];
177
+ this.setCurrentComponentRefdes(refdesValue, true);
178
+ }
179
+ }
170
180
  };
171
181
  this.visitCreate_component_expr = (ctx) => {
172
182
  const scope = this.getScope();
173
- const definedPinIds = [];
174
- const arrangedPinIds = [];
175
- const checkPinExistsAndNotDuplicated = (pinId, ctx) => {
176
- if (definedPinIds.indexOf(pinId) === -1) {
177
- this.warnings.push({
178
- message: `Invalid pin ${pinId}`, ctx
179
- });
180
- }
181
- if (arrangedPinIds.indexOf(pinId) !== -1) {
182
- this.warnings.push({
183
- message: `Pin ${pinId} specified more than once`,
184
- ctx,
185
- });
186
- }
187
- arrangedPinIds.push(pinId);
188
- };
189
- let didDefineArrangeProp = false;
190
- let didDefineDisplayProp = false;
191
- scope.setOnPropertyHandler((path, value, ctx) => {
192
- if (path.length === 1) {
193
- const [, keyName] = path[0];
194
- switch (keyName) {
195
- case 'type':
196
- this.validateString(value, ctx);
197
- break;
198
- case 'angle':
199
- case 'width':
200
- case 'height':
201
- this.validateNumeric(value, ctx);
202
- break;
203
- case 'display':
204
- if (didDefineArrangeProp) {
205
- throw new utils_js_2.RuntimeExecutionError("arrange property has already been defined", ctx);
206
- }
207
- didDefineDisplayProp = true;
208
- break;
209
- case 'arrange':
210
- if (didDefineDisplayProp) {
211
- throw new utils_js_2.RuntimeExecutionError("display property already defined", ctx);
212
- }
213
- didDefineArrangeProp = true;
214
- break;
215
- case 'pins':
216
- if (!(value instanceof Map)) {
217
- this.validateNumeric(value, ctx);
218
- const numPins = value.toNumber();
219
- for (let i = 0; i < numPins; i++) {
220
- definedPinIds.push(i + 1);
221
- }
222
- }
223
- break;
224
- case 'copy':
225
- if (value instanceof ParamDefinition_js_1.NumericValue) {
226
- this.validateNumeric(value, ctx);
227
- }
228
- else if (typeof value === 'boolean') {
229
- this.validateBoolean(value, ctx);
230
- }
231
- else {
232
- throw new utils_js_2.RuntimeExecutionError("Invalid value for 'copy' property", ctx);
233
- }
234
- break;
235
- }
236
- }
237
- else {
238
- const [, keyName] = path[0];
239
- if (keyName === 'arrange') {
240
- const [sideKeyCtx, sideKeyName] = path[1];
241
- if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
242
- throw new utils_js_2.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx);
243
- }
244
- else {
245
- if (path.length === 2 && value instanceof ParamDefinition_js_1.NumericValue) {
246
- checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
247
- }
248
- else if (path.length > 2 && path[2][0] === 'index') {
249
- if (Array.isArray(value)) {
250
- const goodBlank = value.length === 1 &&
251
- value[0] instanceof ParamDefinition_js_1.NumericValue;
252
- if (!goodBlank) {
253
- throw new utils_js_2.RuntimeExecutionError(`Invalid blank specifier`, ctx);
254
- }
255
- }
256
- else {
257
- if (!(value instanceof ParamDefinition_js_1.NumericValue) && !(typeof value === 'string')) {
258
- throw new utils_js_2.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
259
- }
260
- else {
261
- let useValue;
262
- if (value instanceof ParamDefinition_js_1.NumericValue) {
263
- useValue = value.toNumber();
264
- }
265
- else if (typeof value === 'string') {
266
- useValue = value;
267
- }
268
- value && checkPinExistsAndNotDuplicated(useValue, ctx);
269
- }
270
- }
271
- }
272
- }
273
- }
274
- else if (keyName === 'params') {
275
- const [, subKeyName] = path[1];
276
- switch (subKeyName) {
277
- case 'mpn':
278
- case 'refdes':
279
- case 'footprint':
280
- this.validateString(value, ctx);
281
- break;
282
- case 'place':
283
- this.validateBoolean(value, ctx);
284
- break;
285
- }
286
- }
287
- else if (keyName === 'pins') {
288
- if (path.length === 2) {
289
- const idName = path[1][1];
290
- definedPinIds.push(idName);
291
- if (value.length === 2) {
292
- const [pinType,] = value;
293
- if (pinType instanceof types_js_1.UndeclaredReference) {
294
- throw new utils_js_2.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx);
295
- }
296
- }
297
- }
298
- }
299
- }
300
- });
183
+ scope.setOnPropertyHandler(this.createComponentPropertyValidator());
301
184
  scope.enterContext(ctx);
302
185
  ctx.property_expr().forEach(item => {
303
186
  this.visitResult(item);
@@ -317,49 +200,16 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
317
200
  }
318
201
  instanceName += `${globals_js_1.Delimiter1}${appendValue}`;
319
202
  }
320
- const arrangeProp = properties.has('arrange') ?
321
- properties.get('arrange') : null;
322
- const displayProp = properties.has('display') ?
323
- properties.get('display') : null;
324
- const typeProp = properties.has('type') ?
325
- properties.get('type') : null;
326
- const copy = properties.has('copy') ?
327
- properties.get('copy') : false;
328
- const width = properties.has('width') ?
329
- properties.get('width') : null;
330
- const height = properties.has('height') ?
331
- properties.get('height') : null;
332
- const angle = properties.has(globals_js_1.ParamKeys.angle) ?
333
- properties.get(globals_js_1.ParamKeys.angle) : null;
334
- const followWireOrientation = properties.has('followWireOrientation') ?
335
- properties.get('followWireOrientation') : true;
336
- let pins = [];
337
- if (displayProp !== null && arrangeProp === null
338
- && typeProp !== types_js_1.TypeProps.Graphic) {
339
- const drawCommands = displayProp.getCommands();
340
- drawCommands.forEach(command => {
341
- const [commandValue,] = command;
342
- if (commandValue === draw_symbols_js_1.PlaceHolderCommands.vpin
343
- || commandValue === draw_symbols_js_1.PlaceHolderCommands.hpin
344
- || commandValue === draw_symbols_js_1.PlaceHolderCommands.pin) {
345
- const id = PinDefinition_js_1.PinId.from(command[1][0]);
346
- const pinType = id.getType();
347
- const pinName = id.toString();
348
- pins.push(new PinDefinition_js_1.PinDefinition(id, pinType, pinName, PinTypes_js_1.PinTypes.Any));
349
- }
350
- });
351
- }
352
- else {
353
- pins = this.parseCreateComponentPins(properties.get('pins'));
354
- }
203
+ const typeProp = properties.get('type') ?? null;
204
+ const copy = properties.get('copy') ?? false;
205
+ const unitDefinitions = this.extractComponentUnitProperties(properties, typeProp);
355
206
  const props = {
356
- arrange: arrangeProp,
357
- display: displayProp,
358
- type: typeProp, width, height, copy,
359
- angle, followWireOrientation
207
+ type: typeProp,
208
+ copy,
209
+ units: unitDefinitions
360
210
  };
361
211
  try {
362
- const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
212
+ const createdComponent = this.getExecutor().createComponent(instanceName, [], params, props);
363
213
  this.setResult(ctx, createdComponent);
364
214
  createdComponent._creationIndex = this.componentCreationIndex++;
365
215
  }
@@ -501,19 +351,18 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
501
351
  return new PinDefinition_js_1.PinDefinition(index + 1, PinDefinition_js_1.PinIdType.Int, portName, PinTypes_js_1.PinTypes.Any);
502
352
  });
503
353
  const arrange = this.getArrangePropFromModulePorts(modulePorts, nameToPinId);
504
- const width = properties.has('width') ?
505
- properties.get('width') : null;
506
- const height = properties.has('height') ?
507
- properties.get('height') : null;
354
+ const unitProperties = this.extractComponentUnitProperties(properties, types_js_1.TypeProps.Module);
355
+ const firstUnitDef = unitProperties[0][1];
356
+ firstUnitDef.pins = tmpPorts;
357
+ firstUnitDef.arrange = arrange;
508
358
  const blankParams = [];
509
359
  const props = {
510
- arrange, width, height,
511
360
  copy: false,
512
- followWireOrientation: true,
361
+ units: unitProperties,
513
362
  };
514
363
  const moduleInstanceName = this.getExecutor().getUniqueInstanceName();
515
364
  const moduleComponent = this.getExecutor().createComponent(moduleInstanceName, tmpPorts, blankParams, props, true);
516
- moduleComponent.typeProp = globals_js_1.ComponentTypes.module;
365
+ moduleComponent.typeProp = types_js_1.TypeProps.Module;
517
366
  const ctxPropertyBlock = ctx.property_block_expr();
518
367
  if (ctxPropertyBlock) {
519
368
  const [firstBlock] = ctxPropertyBlock;
@@ -536,6 +385,10 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
536
385
  this.visitProperty_expr = (ctx) => {
537
386
  const ctxKey = ctx.property_key_expr();
538
387
  const ctxValue = ctx.property_value_expr();
388
+ const extraValue = ctx._extra;
389
+ if (extraValue) {
390
+ console.log('extra', extraValue.text);
391
+ }
539
392
  const scope = this.getScope();
540
393
  this.getScope().enterContext(ctxKey);
541
394
  this.getScope().enterContext(ctxValue);
@@ -630,6 +483,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
630
483
  dataResult = this.getExecutor().copyComponent(dataResult);
631
484
  }
632
485
  if (dataResult && dataResult instanceof ClassComponent_js_1.ClassComponent) {
486
+ const defaultUnit = dataResult.getUnit();
633
487
  const modifiers = ctx.component_modifier_expr();
634
488
  modifiers.forEach(modifier => {
635
489
  const modifierText = modifier.ID(0).getText();
@@ -646,23 +500,23 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
646
500
  if (modifierText === globals_js_1.ParamKeys.flip) {
647
501
  const flipValue = result;
648
502
  if (flipValue.indexOf('x') !== -1) {
649
- dataResult.setParam(globals_js_1.ParamKeys.flipX, 1);
503
+ defaultUnit.setParam(globals_js_1.ParamKeys.flipX, (0, ParamDefinition_js_1.numeric)(1));
650
504
  shouldIgnoreWireOrientation = true;
651
505
  }
652
506
  if (flipValue.indexOf('y') !== -1) {
653
- dataResult.setParam(globals_js_1.ParamKeys.flipY, 1);
507
+ defaultUnit.setParam(globals_js_1.ParamKeys.flipY, (0, ParamDefinition_js_1.numeric)(1));
654
508
  shouldIgnoreWireOrientation = true;
655
509
  }
656
510
  }
657
511
  else if (modifierText === globals_js_1.ParamKeys.angle) {
658
- dataResult.setParam(globals_js_1.ParamKeys.angle, result);
512
+ defaultUnit.setParam(globals_js_1.ParamKeys.angle, result);
659
513
  shouldIgnoreWireOrientation = true;
660
514
  }
661
515
  else if (modifierText === 'anchor') {
662
516
  dataResult.setParam('anchor', result);
663
517
  }
664
518
  if (shouldIgnoreWireOrientation) {
665
- dataResult.useWireOrientationAngle = false;
519
+ defaultUnit.useWireOrientationAngle = false;
666
520
  }
667
521
  });
668
522
  }
@@ -1155,15 +1009,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1155
1009
  };
1156
1010
  this.visitAnnotation_comment_expr = (ctx) => {
1157
1011
  const refdesID = ctx.ID().getText();
1158
- const currentComponent = this.getScope().currentComponent;
1159
- if (currentComponent !== null) {
1160
- if (refdesID.indexOf('_') === -1) {
1161
- currentComponent.setParam('refdes', refdesID);
1162
- }
1163
- else {
1164
- currentComponent.placeHolderRefDes = refdesID;
1165
- }
1166
- }
1012
+ this.setCurrentComponentRefdes(refdesID);
1167
1013
  };
1168
1014
  this.visitPart_set_expr = (ctx) => {
1169
1015
  const paramKeys = ctx.data_expr().map(ctx => {
@@ -1293,6 +1139,192 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1293
1139
  this.log('-----------------');
1294
1140
  }
1295
1141
  }
1142
+ extractComponentUnitDefinition(properties, typeProp = null, lastNumericPinId = 0) {
1143
+ const width = properties.get('width') ?? null;
1144
+ const height = properties.get('height') ?? null;
1145
+ const angle = properties.get(globals_js_1.ParamKeys.angle) ?? null;
1146
+ const followWireOrientation = properties.get('followWireOrientation') ?? true;
1147
+ const arrange = properties.get('arrange') ?? null;
1148
+ const display = properties.get('display') ?? null;
1149
+ const suffix = properties.get('suffix') ?? null;
1150
+ let pins = [];
1151
+ if (display !== null && arrange === null && typeProp !== types_js_1.TypeProps.Graphic) {
1152
+ const drawCommands = display.getCommands();
1153
+ drawCommands.forEach(command => {
1154
+ const [commandValue,] = command;
1155
+ if (commandValue === draw_symbols_js_1.PlaceHolderCommands.vpin
1156
+ || commandValue === draw_symbols_js_1.PlaceHolderCommands.hpin
1157
+ || commandValue === draw_symbols_js_1.PlaceHolderCommands.pin) {
1158
+ const id = PinDefinition_js_1.PinId.from(command[1][0]);
1159
+ const pinType = id.getType();
1160
+ const pinName = id.toString();
1161
+ pins.push(new PinDefinition_js_1.PinDefinition(id, pinType, pinName, PinTypes_js_1.PinTypes.Any));
1162
+ }
1163
+ });
1164
+ }
1165
+ else {
1166
+ pins = this.extractPinDefintion(properties.get('pins'), lastNumericPinId);
1167
+ }
1168
+ return {
1169
+ width,
1170
+ height,
1171
+ angle,
1172
+ followWireOrientation,
1173
+ display, arrange,
1174
+ pins,
1175
+ suffix
1176
+ };
1177
+ }
1178
+ extractComponentUnitProperties(properties, typeProp) {
1179
+ let lastNumericPinId = 0;
1180
+ const unitsProperties = [];
1181
+ for (const [key, value] of properties) {
1182
+ if (key.split(':')[0] === 'unit') {
1183
+ const unitDef = this.extractComponentUnitDefinition(value, typeProp, lastNumericPinId);
1184
+ unitDef.pins.forEach(pin => {
1185
+ if (pin.id.isNumeric()) {
1186
+ lastNumericPinId = Math.max(lastNumericPinId, pin.id.getValue());
1187
+ }
1188
+ });
1189
+ unitsProperties.push([key, unitDef]);
1190
+ }
1191
+ }
1192
+ if (unitsProperties.length === 0) {
1193
+ unitsProperties.push(['unit',
1194
+ this.extractComponentUnitDefinition(properties, typeProp)]);
1195
+ }
1196
+ return unitsProperties;
1197
+ }
1198
+ createComponentPropertyValidator() {
1199
+ const definedPinIds = [];
1200
+ const arrangedPinIds = [];
1201
+ let didDefineArrangeProp = false;
1202
+ let didDefineDisplayProp = false;
1203
+ const checkPinExistsAndNotDuplicated = (pinId, ctx) => {
1204
+ if (definedPinIds.indexOf(pinId) === -1) {
1205
+ this.warnings.push({
1206
+ message: `Invalid pin ${pinId}`, ctx
1207
+ });
1208
+ }
1209
+ if (arrangedPinIds.indexOf(pinId) !== -1) {
1210
+ this.warnings.push({
1211
+ message: `Pin ${pinId} specified more than once`,
1212
+ ctx,
1213
+ });
1214
+ }
1215
+ arrangedPinIds.push(pinId);
1216
+ };
1217
+ return (path, value, ctx) => {
1218
+ if (path.length === 1) {
1219
+ const [, keyName] = path[0];
1220
+ switch (keyName) {
1221
+ case 'type':
1222
+ this.validateString(value, ctx);
1223
+ break;
1224
+ case 'angle':
1225
+ case 'width':
1226
+ case 'height':
1227
+ this.validateNumeric(value, ctx);
1228
+ break;
1229
+ case 'display':
1230
+ if (didDefineArrangeProp) {
1231
+ throw new utils_js_2.RuntimeExecutionError("arrange property has already been defined", ctx);
1232
+ }
1233
+ didDefineDisplayProp = true;
1234
+ break;
1235
+ case 'arrange':
1236
+ if (didDefineDisplayProp) {
1237
+ throw new utils_js_2.RuntimeExecutionError("display property already defined", ctx);
1238
+ }
1239
+ didDefineArrangeProp = true;
1240
+ break;
1241
+ case 'pins':
1242
+ if (!(value instanceof Map)) {
1243
+ this.validateNumeric(value, ctx);
1244
+ const numPins = value.toNumber();
1245
+ for (let i = 0; i < numPins; i++) {
1246
+ definedPinIds.push(i + 1);
1247
+ }
1248
+ }
1249
+ break;
1250
+ case 'copy':
1251
+ if (value instanceof ParamDefinition_js_1.NumericValue) {
1252
+ this.validateNumeric(value, ctx);
1253
+ }
1254
+ else if (typeof value === 'boolean') {
1255
+ this.validateBoolean(value, ctx);
1256
+ }
1257
+ else {
1258
+ throw new utils_js_2.RuntimeExecutionError("Invalid value for 'copy' property", ctx);
1259
+ }
1260
+ break;
1261
+ }
1262
+ }
1263
+ else {
1264
+ const [, keyName] = path[0];
1265
+ if (keyName === 'arrange') {
1266
+ const [sideKeyCtx, sideKeyName] = path[1];
1267
+ if (globals_js_1.ValidPinSides.indexOf(sideKeyName) === -1) {
1268
+ throw new utils_js_2.RuntimeExecutionError(`Invalid side ${sideKeyName} in arrange`, sideKeyCtx);
1269
+ }
1270
+ else {
1271
+ if (path.length === 2 && value instanceof ParamDefinition_js_1.NumericValue) {
1272
+ checkPinExistsAndNotDuplicated(value.toNumber(), ctx);
1273
+ }
1274
+ else if (path.length > 2 && path[2][0] === 'index') {
1275
+ if (Array.isArray(value)) {
1276
+ const goodBlank = value.length === 1 &&
1277
+ value[0] instanceof ParamDefinition_js_1.NumericValue;
1278
+ if (!goodBlank) {
1279
+ throw new utils_js_2.RuntimeExecutionError(`Invalid blank specifier`, ctx);
1280
+ }
1281
+ }
1282
+ else {
1283
+ if (!(value instanceof ParamDefinition_js_1.NumericValue) && !(typeof value === 'string')) {
1284
+ throw new utils_js_2.RuntimeExecutionError(`Invalid numeric value for arrange.${sideKeyName}`, ctx);
1285
+ }
1286
+ else {
1287
+ let useValue;
1288
+ if (value instanceof ParamDefinition_js_1.NumericValue) {
1289
+ useValue = value.toNumber();
1290
+ }
1291
+ else if (typeof value === 'string') {
1292
+ useValue = value;
1293
+ }
1294
+ value && checkPinExistsAndNotDuplicated(useValue, ctx);
1295
+ }
1296
+ }
1297
+ }
1298
+ }
1299
+ }
1300
+ else if (keyName === 'params') {
1301
+ const [, subKeyName] = path[1];
1302
+ switch (subKeyName) {
1303
+ case 'mpn':
1304
+ case 'refdes':
1305
+ case 'footprint':
1306
+ this.validateString(value, ctx);
1307
+ break;
1308
+ case 'place':
1309
+ this.validateBoolean(value, ctx);
1310
+ break;
1311
+ }
1312
+ }
1313
+ else if (keyName === 'pins') {
1314
+ if (path.length === 2) {
1315
+ const idName = path[1][1];
1316
+ definedPinIds.push(idName);
1317
+ if (value.length === 2) {
1318
+ const [pinType,] = value;
1319
+ if (pinType instanceof types_js_1.UndeclaredReference) {
1320
+ throw new utils_js_2.RuntimeExecutionError(`Invalid pin type: ${pinType.reference.name}`, ctx);
1321
+ }
1322
+ }
1323
+ }
1324
+ }
1325
+ }
1326
+ };
1327
+ }
1296
1328
  expandModuleContains(component, netNamespace) {
1297
1329
  this.getExecutor().log('expanding module `contains`');
1298
1330
  const executionStack = this.executionStack;
@@ -1341,6 +1373,40 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1341
1373
  }
1342
1374
  }
1343
1375
  }
1376
+ setCurrentComponentRefdes(refdesValue, forceSave = false) {
1377
+ const currentComponent = this.getScope().currentComponent;
1378
+ if (currentComponent !== null) {
1379
+ if (refdesValue.indexOf('_') === -1) {
1380
+ currentComponent.setParam('refdes', refdesValue);
1381
+ }
1382
+ else {
1383
+ currentComponent.placeHolderRefDes = refdesValue;
1384
+ }
1385
+ currentComponent.forceSaveRefdesAnnotation = forceSave;
1386
+ }
1387
+ }
1388
+ async checkModuleHasRefdesFile(filePath) {
1389
+ const dir = this.environment.dirname(filePath);
1390
+ const ext = this.environment.extname(filePath);
1391
+ const basename = this.environment.basename(filePath, ext);
1392
+ const annotatedFilePath = this.environment.join(dir, `${basename}${globals_js_1.RefdesFileSuffix}`);
1393
+ const exists = await this.environment.exists(annotatedFilePath);
1394
+ if (exists) {
1395
+ this.log(`Import has refdes file: ${annotatedFilePath}`);
1396
+ const fileData = await this.environment.readFile(annotatedFilePath);
1397
+ const jsonData = JSON.parse(fileData);
1398
+ const baseFilePath = this.environment.getAbsolutePath(this.filePathStack[0]);
1399
+ const basePathDirectory = this.environment.dirname(baseFilePath);
1400
+ const { file, items } = jsonData;
1401
+ for (const item of items) {
1402
+ const parts = item.split(':');
1403
+ const refdes = parts[4];
1404
+ const useFilePath = this.environment.join(basePathDirectory, file);
1405
+ const key = this.getRefdesFileAnnotation(useFilePath, Number(parts[0]), Number(parts[1]), Number(parts[2]), Number(parts[3]));
1406
+ this.refdesFileAnnotations.set(key, refdes);
1407
+ }
1408
+ }
1409
+ }
1344
1410
  resolveDataExpr(data_expr) {
1345
1411
  const value = this.visitResult(data_expr);
1346
1412
  if (value instanceof types_js_1.UndeclaredReference) {
@@ -1360,13 +1426,13 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1360
1426
  return value;
1361
1427
  }
1362
1428
  }
1363
- parseCreateComponentPins(pinData) {
1429
+ extractPinDefintion(pinData, lastNumericPinId = 0) {
1364
1430
  const pins = [];
1365
1431
  if (pinData instanceof ParamDefinition_js_1.NumericValue) {
1366
1432
  const tmpMap = new Map();
1367
1433
  const lastPin = pinData.toNumber();
1368
1434
  for (let i = 0; i < lastPin; i++) {
1369
- const pinId = i + 1;
1435
+ const pinId = lastNumericPinId + i + 1;
1370
1436
  tmpMap.set(pinId, (0, ParamDefinition_js_1.numeric)(pinId));
1371
1437
  }
1372
1438
  pinData = tmpMap;
@@ -1539,6 +1605,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1539
1605
  const refdes = instance.getParam('refdes');
1540
1606
  if (refdes) {
1541
1607
  instance.assignedRefDes = refdes;
1608
+ this.setComponentUnitRefdesSuffix(instance);
1542
1609
  annotater.trackRefDes(refdes);
1543
1610
  this.log(refdes, '-', instance.instanceName);
1544
1611
  continue;
@@ -1552,6 +1619,7 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1552
1619
  if (newRefDes !== null) {
1553
1620
  instance.assignedRefDes = newRefDes;
1554
1621
  this.log(newRefDes, '-', instance.instanceName);
1622
+ this.setComponentUnitRefdesSuffix(instance);
1555
1623
  }
1556
1624
  else {
1557
1625
  this.log('Failed to annotate:', instance.instanceName);
@@ -1562,6 +1630,24 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1562
1630
  this.renameNetsWithRefdes();
1563
1631
  this.log('===== rename nets done =====');
1564
1632
  }
1633
+ setComponentUnitRefdesSuffix(instance) {
1634
+ if (instance.assignedRefDes) {
1635
+ const { units } = instance;
1636
+ if (units.length > 1) {
1637
+ units.forEach((unit, index) => {
1638
+ let useRefdes = String.fromCharCode("A".charCodeAt(0) + index);
1639
+ if (unit.suffix !== null) {
1640
+ useRefdes = unit.suffix;
1641
+ }
1642
+ unit.refdesSuffix = useRefdes;
1643
+ });
1644
+ }
1645
+ else {
1646
+ const [firstUnit] = units;
1647
+ firstUnit.refdesSuffix = '';
1648
+ }
1649
+ }
1650
+ }
1565
1651
  renameNetsWithRefdes() {
1566
1652
  const nets = this.getScope().getNets();
1567
1653
  const seenNets = [];
@@ -1620,10 +1706,17 @@ class ParserVisitor extends BaseVisitor_js_1.BaseVisitor {
1620
1706
  }
1621
1707
  getPropertyExprList(items) {
1622
1708
  const properties = new Map();
1709
+ const keyCounter = new Map();
1623
1710
  items.forEach((item) => {
1624
1711
  const result = this.visitResult(item);
1625
1712
  for (const [key, value] of result) {
1626
- properties.set(key, value);
1713
+ let useKey = key;
1714
+ const counterValue = keyCounter.get(key) ?? 0;
1715
+ keyCounter.set(key, counterValue + 1);
1716
+ if (counterValue > 0) {
1717
+ useKey = key + ':' + counterValue;
1718
+ }
1719
+ properties.set(useKey, value);
1627
1720
  }
1628
1721
  });
1629
1722
  return properties;