circuitscript 0.0.29 → 0.0.31
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.
- package/dist/cjs/BaseVisitor.js +6 -1
- package/dist/cjs/antlr/CircuitScriptLexer.js +204 -200
- package/dist/cjs/antlr/CircuitScriptParser.js +1066 -1173
- package/dist/cjs/draw_symbols.js +330 -87
- package/dist/cjs/execute.js +39 -14
- package/dist/cjs/geometry.js +79 -18
- package/dist/cjs/globals.js +36 -6
- package/dist/cjs/helpers.js +40 -2
- package/dist/cjs/layout.js +72 -39
- package/dist/cjs/main.js +10 -4
- package/dist/cjs/objects/ClassComponent.js +2 -0
- package/dist/cjs/objects/ExecutionScope.js +1 -1
- package/dist/cjs/objects/Net.js +3 -2
- package/dist/cjs/objects/PinTypes.js +7 -1
- package/dist/cjs/objects/types.js +11 -1
- package/dist/cjs/regenerate-tests.js +64 -3
- package/dist/cjs/render.js +20 -14
- package/dist/cjs/sizing.js +4 -6
- package/dist/cjs/utils.js +29 -5
- package/dist/cjs/visitor.js +176 -10
- package/dist/esm/BaseVisitor.mjs +6 -1
- package/dist/esm/antlr/CircuitScriptLexer.mjs +204 -200
- package/dist/esm/antlr/CircuitScriptParser.mjs +1061 -1171
- package/dist/esm/antlr/CircuitScriptVisitor.mjs +3 -0
- package/dist/esm/draw_symbols.mjs +324 -85
- package/dist/esm/execute.mjs +40 -15
- package/dist/esm/geometry.mjs +79 -17
- package/dist/esm/globals.mjs +35 -5
- package/dist/esm/helpers.mjs +38 -1
- package/dist/esm/layout.mjs +75 -42
- package/dist/esm/main.mjs +11 -5
- package/dist/esm/objects/ClassComponent.mjs +6 -0
- package/dist/esm/objects/ExecutionScope.mjs +1 -1
- package/dist/esm/objects/Net.mjs +3 -2
- package/dist/esm/objects/PinTypes.mjs +6 -0
- package/dist/esm/objects/types.mjs +14 -0
- package/dist/esm/regenerate-tests.mjs +64 -3
- package/dist/esm/render.mjs +21 -15
- package/dist/esm/sizing.mjs +3 -4
- package/dist/esm/utils.mjs +26 -4
- package/dist/esm/visitor.mjs +179 -13
- package/dist/types/antlr/CircuitScriptLexer.d.ts +42 -41
- package/dist/types/antlr/CircuitScriptParser.d.ts +144 -133
- package/dist/types/antlr/CircuitScriptVisitor.d.ts +6 -0
- package/dist/types/draw_symbols.d.ts +15 -2
- package/dist/types/execute.d.ts +5 -4
- package/dist/types/geometry.d.ts +4 -3
- package/dist/types/globals.d.ts +31 -3
- package/dist/types/helpers.d.ts +12 -0
- package/dist/types/layout.d.ts +2 -1
- package/dist/types/objects/ClassComponent.d.ts +8 -0
- package/dist/types/objects/PinTypes.d.ts +1 -0
- package/dist/types/objects/Wire.d.ts +4 -2
- package/dist/types/objects/types.d.ts +8 -0
- package/dist/types/sizing.d.ts +0 -4
- package/dist/types/utils.d.ts +3 -0
- package/dist/types/visitor.d.ts +8 -1
- package/fonts/Arial.ttf +0 -0
- package/libs/lib.cst +58 -41
- package/package.json +1 -1
package/dist/esm/main.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { program } from 'commander';
|
|
3
3
|
import figlet from 'figlet';
|
|
4
4
|
import path from 'path';
|
|
5
|
-
import { readFileSync, watch } from 'fs';
|
|
5
|
+
import { readFileSync, watch, existsSync } from 'fs';
|
|
6
6
|
import { prepareSVGEnvironment } from './sizing.mjs';
|
|
7
7
|
import { getDefaultLibsPath, getFontsPath, getPackageVersion, renderScript } from './helpers.mjs';
|
|
8
8
|
export default async function main() {
|
|
@@ -47,16 +47,22 @@ export default async function main() {
|
|
|
47
47
|
let scriptData;
|
|
48
48
|
if (args.length > 0 && args[0]) {
|
|
49
49
|
inputFilePath = args[0];
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
currentDirectory
|
|
50
|
+
if (existsSync(inputFilePath)) {
|
|
51
|
+
scriptData = readFileSync(inputFilePath, { encoding: 'utf-8' });
|
|
52
|
+
if (currentDirectory === null) {
|
|
53
|
+
currentDirectory = path.dirname(inputFilePath);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.error("Error: File could not be found");
|
|
58
|
+
return;
|
|
53
59
|
}
|
|
54
60
|
}
|
|
55
61
|
else if (options.input) {
|
|
56
62
|
scriptData = options.input;
|
|
57
63
|
}
|
|
58
64
|
else {
|
|
59
|
-
console.
|
|
65
|
+
console.error("Error: No input provided");
|
|
60
66
|
return;
|
|
61
67
|
}
|
|
62
68
|
const scriptOptions = {
|
|
@@ -22,8 +22,14 @@ export class ClassComponent {
|
|
|
22
22
|
followWireOrientationProp = true;
|
|
23
23
|
wireOrientationAngle = 0;
|
|
24
24
|
useWireOrientationAngle = true;
|
|
25
|
+
didSetWireOrientationAngle = false;
|
|
25
26
|
styles = {};
|
|
26
27
|
assignedRefDes = null;
|
|
28
|
+
moduleContainsExpressions;
|
|
29
|
+
moduleCounter = 0;
|
|
30
|
+
moduleExecutionContext;
|
|
31
|
+
moduleExecutionContextName;
|
|
32
|
+
modulePinIdToPortMap;
|
|
27
33
|
constructor(instanceName, numPins, className) {
|
|
28
34
|
this.instanceName = instanceName;
|
|
29
35
|
this.numPins = numPins;
|
package/dist/esm/objects/Net.mjs
CHANGED
|
@@ -18,10 +18,11 @@ export class Net {
|
|
|
18
18
|
this.baseName = name;
|
|
19
19
|
}
|
|
20
20
|
toString() {
|
|
21
|
-
return this.name;
|
|
21
|
+
return this.namespace + this.name;
|
|
22
22
|
}
|
|
23
23
|
static isSame(netA, netB) {
|
|
24
|
-
return netA.
|
|
24
|
+
return netA.namespace === netB.namespace &&
|
|
25
|
+
netA.name === netB.name &&
|
|
25
26
|
netA.baseName === netB.baseName &&
|
|
26
27
|
netA.priority === netB.priority &&
|
|
27
28
|
netA.type === netB.type;
|
|
@@ -4,6 +4,20 @@ export class UndeclaredReference {
|
|
|
4
4
|
this.reference = reference;
|
|
5
5
|
}
|
|
6
6
|
}
|
|
7
|
+
export class DeclaredReference {
|
|
8
|
+
found;
|
|
9
|
+
name;
|
|
10
|
+
trailers;
|
|
11
|
+
type;
|
|
12
|
+
value;
|
|
13
|
+
constructor(refType) {
|
|
14
|
+
this.found = refType.found;
|
|
15
|
+
this.name = refType.name;
|
|
16
|
+
this.trailers = refType.trailers;
|
|
17
|
+
this.type = refType.type;
|
|
18
|
+
this.value = refType.value;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
7
21
|
export var ParseSymbolType;
|
|
8
22
|
(function (ParseSymbolType) {
|
|
9
23
|
ParseSymbolType["Variable"] = "variable";
|
|
@@ -4,7 +4,7 @@ import { prepareSVGEnvironment } from './sizing.mjs';
|
|
|
4
4
|
const mainDir = './__tests__/renderData/';
|
|
5
5
|
const fontsPath = getFontsPath();
|
|
6
6
|
const defaultLibsPath = getDefaultLibsPath();
|
|
7
|
-
async function regenerateTests() {
|
|
7
|
+
async function regenerateTests(extra = "") {
|
|
8
8
|
await prepareSVGEnvironment(fontsPath);
|
|
9
9
|
const cstFiles = [];
|
|
10
10
|
const files = fs.readdirSync(mainDir);
|
|
@@ -16,12 +16,73 @@ async function regenerateTests() {
|
|
|
16
16
|
cstFiles.forEach(file => {
|
|
17
17
|
const inputPath = mainDir + file;
|
|
18
18
|
const scriptData = fs.readFileSync(inputPath, { encoding: 'utf-8' });
|
|
19
|
-
const outputPath =
|
|
19
|
+
const outputPath = mainDir + 'svgs/' + file + extra + '.svg';
|
|
20
20
|
renderScript(scriptData, outputPath, {
|
|
21
21
|
currentDirectory: mainDir,
|
|
22
22
|
defaultLibsPath,
|
|
23
23
|
});
|
|
24
24
|
console.log('generated ', outputPath);
|
|
25
25
|
});
|
|
26
|
+
return cstFiles;
|
|
26
27
|
}
|
|
27
|
-
|
|
28
|
+
(async () => {
|
|
29
|
+
const generateDiff = false;
|
|
30
|
+
const nextExtra = generateDiff ? '.next' : '';
|
|
31
|
+
const cstFiles = await regenerateTests(nextExtra);
|
|
32
|
+
const allFiles = [];
|
|
33
|
+
if (generateDiff) {
|
|
34
|
+
cstFiles.forEach(file => {
|
|
35
|
+
const svg1 = 'svgs/' + file + '.svg';
|
|
36
|
+
const svg2 = 'svgs/' + file + '.next.svg';
|
|
37
|
+
const cleanedName = file.replace('script', '').replace('.cst', '');
|
|
38
|
+
allFiles.push([file, svg1, svg2, cleanedName]);
|
|
39
|
+
});
|
|
40
|
+
const sortedFiles = allFiles.sort((a, b) => {
|
|
41
|
+
const nameA = a[3];
|
|
42
|
+
const nameB = b[3];
|
|
43
|
+
const indexA = Number(nameA);
|
|
44
|
+
const indexB = Number(nameB);
|
|
45
|
+
if (indexA > indexB) {
|
|
46
|
+
return 1;
|
|
47
|
+
}
|
|
48
|
+
else if (indexA < indexB) {
|
|
49
|
+
return -1;
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
return 0;
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
const output = [];
|
|
56
|
+
sortedFiles.forEach(group => {
|
|
57
|
+
const [file, svg1, svg2] = group;
|
|
58
|
+
output.push(`<div class='group'>
|
|
59
|
+
<h3>${file}</h3>
|
|
60
|
+
<div class='items'>
|
|
61
|
+
<div style='margin-right: 10px'>
|
|
62
|
+
<h4>${svg1}</h4>
|
|
63
|
+
<img src='${svg1}'/>
|
|
64
|
+
</div>
|
|
65
|
+
<div>
|
|
66
|
+
<h4>${svg2}</h4>
|
|
67
|
+
<img src='${svg2}'/>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>`);
|
|
71
|
+
});
|
|
72
|
+
const result = `
|
|
73
|
+
<html>
|
|
74
|
+
<header>
|
|
75
|
+
<title>SVG compare</title>
|
|
76
|
+
<style>
|
|
77
|
+
img { border: solid thin #ccc; }
|
|
78
|
+
.items { display: flex; }
|
|
79
|
+
body { font-family: Arial; }
|
|
80
|
+
</style>
|
|
81
|
+
</header>
|
|
82
|
+
<body>
|
|
83
|
+
${output.join('')}
|
|
84
|
+
</body>
|
|
85
|
+
</html>`;
|
|
86
|
+
fs.writeFileSync(mainDir + "compiled.html", result);
|
|
87
|
+
}
|
|
88
|
+
})();
|
package/dist/esm/render.mjs
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { SVG, registerWindow } from '@svgdotjs/svg.js';
|
|
2
2
|
import { RenderFrameType, getBounds } from "./layout.mjs";
|
|
3
3
|
import { applyFontsToSVG, getCreateSVGWindow } from './sizing.mjs';
|
|
4
|
-
import { ColorScheme, ComponentTypes, ParamKeys, junctionSize } from './globals.mjs';
|
|
4
|
+
import { ColorScheme, ComponentTypes, MMToPx, ParamKeys, defaultGridSizeUnits, defaultWireLineWidth, defaultZoomScale, junctionSize } from './globals.mjs';
|
|
5
5
|
import { NumericValue } from './objects/ParamDefinition.mjs';
|
|
6
6
|
import { getBoundsSize } from './utils.mjs';
|
|
7
|
+
import { milsToMM } from './helpers.mjs';
|
|
7
8
|
export function generateSVG2(graph) {
|
|
8
9
|
const window = getCreateSVGWindow()();
|
|
9
10
|
const document = window.document;
|
|
@@ -12,10 +13,10 @@ export function generateSVG2(graph) {
|
|
|
12
13
|
applyFontsToSVG(canvas);
|
|
13
14
|
generateSVGChild(canvas, graph.components, graph.wires, graph.junctions, graph.mergedWires, graph.frameObjects, graph.textObjects);
|
|
14
15
|
const { x, y, width, height } = canvas.bbox();
|
|
15
|
-
const margin =
|
|
16
|
+
const margin = milsToMM(10);
|
|
16
17
|
const widthAndMargin = width + margin * 2;
|
|
17
18
|
const heightAndMargin = height + margin * 2;
|
|
18
|
-
const scale =
|
|
19
|
+
const scale = MMToPx * defaultZoomScale;
|
|
19
20
|
canvas.size(widthAndMargin * scale, heightAndMargin * scale);
|
|
20
21
|
canvas.viewbox(x - margin, y - margin, widthAndMargin, heightAndMargin);
|
|
21
22
|
return canvas.svg();
|
|
@@ -79,8 +80,11 @@ function generateSVGChild(canvas, components, wires, junctions, mergedWires, fra
|
|
|
79
80
|
const pt1 = segment[0];
|
|
80
81
|
const pt2 = segment[1];
|
|
81
82
|
mergedWireGroup.line([pt1, pt2])
|
|
82
|
-
.stroke({
|
|
83
|
-
|
|
83
|
+
.stroke({
|
|
84
|
+
width: defaultWireLineWidth,
|
|
85
|
+
color: ColorScheme.WireColor,
|
|
86
|
+
linecap: 'square'
|
|
87
|
+
})
|
|
84
88
|
.fill('none');
|
|
85
89
|
});
|
|
86
90
|
intersectPoints.forEach(point => {
|
|
@@ -109,7 +113,7 @@ function generateSVGChild(canvas, components, wires, junctions, mergedWires, fra
|
|
|
109
113
|
}
|
|
110
114
|
const tmpRect = frameGroup.rect(width, height)
|
|
111
115
|
.fill('none')
|
|
112
|
-
.stroke({ width: borderWidth, color: strokeColor });
|
|
116
|
+
.stroke({ width: milsToMM(borderWidth), color: strokeColor });
|
|
113
117
|
tmpRect.translate(item.x, item.y);
|
|
114
118
|
}
|
|
115
119
|
});
|
|
@@ -120,13 +124,14 @@ function generateSVGChild(canvas, components, wires, junctions, mergedWires, fra
|
|
|
120
124
|
symbol.draw(innerGroup);
|
|
121
125
|
});
|
|
122
126
|
const drawOrigin = false;
|
|
127
|
+
const originSize = milsToMM(10);
|
|
123
128
|
drawOrigin && canvas.group().translate(0, 0)
|
|
124
|
-
.circle(
|
|
125
|
-
.translate(-
|
|
129
|
+
.circle(originSize)
|
|
130
|
+
.translate(-originSize / 2, -originSize / 2)
|
|
126
131
|
.stroke('none').fill('red');
|
|
127
132
|
}
|
|
128
133
|
function drawGrid(group, canvasSize) {
|
|
129
|
-
const gridSize =
|
|
134
|
+
const gridSize = defaultGridSizeUnits;
|
|
130
135
|
const { x, y, x2, y2 } = canvasSize;
|
|
131
136
|
const gridStartX = (Math.floor(x / gridSize) - 1) * gridSize;
|
|
132
137
|
const gridStartY = (Math.floor(y / gridSize) - 1) * gridSize;
|
|
@@ -134,19 +139,20 @@ function drawGrid(group, canvasSize) {
|
|
|
134
139
|
const gridEndY = (Math.ceil(y2 / gridSize) + 1) * gridSize;
|
|
135
140
|
const numCols = Math.ceil((gridEndX - gridStartX) / gridSize);
|
|
136
141
|
const lines = [];
|
|
142
|
+
const smallOffset = milsToMM(3);
|
|
143
|
+
const startY = gridStartY - smallOffset / 2;
|
|
144
|
+
const endY = gridEndY + smallOffset;
|
|
137
145
|
for (let i = 0; i <= numCols; i++) {
|
|
138
146
|
const startX = gridStartX + i * gridSize;
|
|
139
|
-
const startY = gridStartY - 0.5;
|
|
140
|
-
const endY = gridEndY;
|
|
141
147
|
lines.push(`M ${startX} ${startY} L ${startX} ${endY}`);
|
|
142
148
|
}
|
|
149
|
+
const strokeSize = milsToMM(3);
|
|
143
150
|
group.path(lines.join(" "))
|
|
144
|
-
.fill('none')
|
|
145
151
|
.attr({
|
|
146
|
-
'stroke-dasharray':
|
|
152
|
+
'stroke-dasharray': `${strokeSize},${gridSize - strokeSize}`,
|
|
147
153
|
})
|
|
148
154
|
.stroke({
|
|
149
|
-
width:
|
|
150
|
-
color: '#
|
|
155
|
+
width: strokeSize,
|
|
156
|
+
color: '#000'
|
|
151
157
|
});
|
|
152
158
|
}
|
package/dist/esm/sizing.mjs
CHANGED
|
@@ -3,7 +3,9 @@ import { HorizontalAlign, VerticalAlign } from './geometry.mjs';
|
|
|
3
3
|
import { defaultFont } from './globals.mjs';
|
|
4
4
|
import { JSModuleType, detectJSModuleType } from './helpers.mjs';
|
|
5
5
|
let MainCanvas = null;
|
|
6
|
-
const supportedFonts = {
|
|
6
|
+
const supportedFonts = {
|
|
7
|
+
'Arial': 'Arial.ttf',
|
|
8
|
+
};
|
|
7
9
|
let globalCreateSVGWindow;
|
|
8
10
|
export async function prepareSVGEnvironment(fontsPath) {
|
|
9
11
|
const moduleType = detectJSModuleType();
|
|
@@ -25,9 +27,6 @@ export function getCreateSVGWindow() {
|
|
|
25
27
|
}
|
|
26
28
|
export function applyFontsToSVG(canvas) {
|
|
27
29
|
}
|
|
28
|
-
export async function measureTextSize(text, fontFamily, fontSize) {
|
|
29
|
-
return measureTextSize2(text, fontFamily, fontSize);
|
|
30
|
-
}
|
|
31
30
|
const measureTextSizeCache = {};
|
|
32
31
|
const measureTextSizeCacheHits = {};
|
|
33
32
|
export function measureTextSize2(text, fontFamily, fontSize, fontWeight = 'regular', anchor = HorizontalAlign.Left, vanchor = VerticalAlign.Bottom) {
|
package/dist/esm/utils.mjs
CHANGED
|
@@ -23,11 +23,17 @@ export function printBounds(bounds) {
|
|
|
23
23
|
return 'null';
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
|
+
function hasRemainder(value, value2) {
|
|
27
|
+
const tmpValue = Math.abs(value) / value2;
|
|
28
|
+
const flooredValue = Math.floor(tmpValue);
|
|
29
|
+
const diff = tmpValue - flooredValue;
|
|
30
|
+
return diff;
|
|
31
|
+
}
|
|
26
32
|
export function resizeToNearestGrid(bounds, gridSize = 20) {
|
|
27
|
-
const addXMin = (bounds.xmin
|
|
28
|
-
const addYMin = (bounds.ymin
|
|
29
|
-
const addXMax = (bounds.xmax
|
|
30
|
-
const addYMax = (bounds.ymax
|
|
33
|
+
const addXMin = hasRemainder(bounds.xmin, gridSize) === 0 ? -1 : 0;
|
|
34
|
+
const addYMin = hasRemainder(bounds.ymin, gridSize) === 0 ? -1 : 0;
|
|
35
|
+
const addXMax = hasRemainder(bounds.xmax, gridSize) === 0 ? 1 : 0;
|
|
36
|
+
const addYMax = hasRemainder(bounds.ymax, gridSize) === 0 ? 1 : 0;
|
|
31
37
|
return {
|
|
32
38
|
xmin: Math.floor((bounds.xmin + addXMin) / gridSize) * gridSize,
|
|
33
39
|
ymin: Math.floor((bounds.ymin + addYMin) / gridSize) * gridSize,
|
|
@@ -44,3 +50,19 @@ export function getBoundsSize(bounds) {
|
|
|
44
50
|
height: bounds.ymax - bounds.ymin,
|
|
45
51
|
};
|
|
46
52
|
}
|
|
53
|
+
export function getPortType(component) {
|
|
54
|
+
const drawingCommands = component.displayProp;
|
|
55
|
+
let foundPinType = null;
|
|
56
|
+
const commands = drawingCommands.getCommands();
|
|
57
|
+
commands.some(item => {
|
|
58
|
+
if (item[0] === 'label' && item[2].has('portType')) {
|
|
59
|
+
foundPinType = item[2].get('portType');
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
return false;
|
|
63
|
+
});
|
|
64
|
+
return foundPinType;
|
|
65
|
+
}
|
|
66
|
+
export function roundValue(value) {
|
|
67
|
+
return +value.toFixed(7);
|
|
68
|
+
}
|
package/dist/esm/visitor.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { ClassComponent } from './objects/ClassComponent.mjs';
|
|
2
|
-
import { NumericValue, ParamDefinition, } from './objects/ParamDefinition.mjs';
|
|
2
|
+
import { NumericValue, ParamDefinition, PinBlankValue, } from './objects/ParamDefinition.mjs';
|
|
3
3
|
import { PinDefinition, PinIdType } from './objects/PinDefinition.mjs';
|
|
4
4
|
import { PinTypes } from './objects/PinTypes.mjs';
|
|
5
|
-
import { UndeclaredReference } from './objects/types.mjs';
|
|
6
|
-
import { BlockTypes, ComponentTypes, NoNetText, ReferenceTypes } from './globals.mjs';
|
|
5
|
+
import { DeclaredReference, UndeclaredReference } from './objects/types.mjs';
|
|
6
|
+
import { BlockTypes, ComponentTypes, NoNetText, ReferenceTypes, WireAutoDirection } from './globals.mjs';
|
|
7
7
|
import { PlaceHolderCommands, SymbolDrawingCommands } from './draw_symbols.mjs';
|
|
8
8
|
import { BaseVisitor } from './BaseVisitor.mjs';
|
|
9
|
+
import { getPortType } from './utils.mjs';
|
|
10
|
+
import { UnitDimension } from './helpers.mjs';
|
|
9
11
|
export class ParserVisitor extends BaseVisitor {
|
|
10
12
|
visitKeyword_assignment_expr = (ctx) => {
|
|
11
13
|
const id = ctx.ID().getText();
|
|
@@ -145,7 +147,8 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
145
147
|
arrange, display, type, width, copy,
|
|
146
148
|
angle, followWireOrientation
|
|
147
149
|
};
|
|
148
|
-
|
|
150
|
+
const createdComponent = this.getExecutor().createComponent(instanceName, pins, params, props);
|
|
151
|
+
this.setResult(ctx, createdComponent);
|
|
149
152
|
};
|
|
150
153
|
visitCreate_graphic_expr = (ctx) => {
|
|
151
154
|
const commands = ctx.graphic_expr().reduce((accum, item) => {
|
|
@@ -191,8 +194,82 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
191
194
|
this.visit(ctxParameters);
|
|
192
195
|
parameters = this.getResult(ctxParameters);
|
|
193
196
|
}
|
|
197
|
+
if (commandName === 'label') {
|
|
198
|
+
parameters.forEach(item => {
|
|
199
|
+
if (item[0] == 'keyword' && item[1] === 'portType') {
|
|
200
|
+
if (item[2] === 'in') {
|
|
201
|
+
item[2] = 'input';
|
|
202
|
+
}
|
|
203
|
+
else if (item[2] === 'out') {
|
|
204
|
+
item[2] = 'output';
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
194
209
|
this.setResult(ctx, [commandName, parameters]);
|
|
195
210
|
};
|
|
211
|
+
visitCreate_module_expr = (ctx) => {
|
|
212
|
+
const properties = this.getPropertyExprList(ctx.property_expr());
|
|
213
|
+
const { left: leftPorts, right: rightPorts } = this.parseCreateModulePorts(properties.get('ports'));
|
|
214
|
+
const allPorts = [...leftPorts, ...rightPorts].filter(item => {
|
|
215
|
+
return !(item instanceof PinBlankValue);
|
|
216
|
+
});
|
|
217
|
+
const nameToPinId = new Map();
|
|
218
|
+
const tmpPorts = allPorts.map((portName, index) => {
|
|
219
|
+
nameToPinId.set(portName, index + 1);
|
|
220
|
+
return new PinDefinition(index + 1, PinIdType.Int, portName, PinTypes.Any);
|
|
221
|
+
});
|
|
222
|
+
const arrangeLeftItems = leftPorts.map(item => {
|
|
223
|
+
if (item instanceof PinBlankValue) {
|
|
224
|
+
return item;
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
return nameToPinId.get(item);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
const arrangeRightItems = rightPorts.map(item => {
|
|
231
|
+
if (item instanceof PinBlankValue) {
|
|
232
|
+
return item;
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
return nameToPinId.get(item);
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
const arrange = new Map();
|
|
239
|
+
if (arrangeLeftItems.length > 0) {
|
|
240
|
+
arrange.set('left', arrangeLeftItems);
|
|
241
|
+
}
|
|
242
|
+
if (arrangeRightItems.length > 0) {
|
|
243
|
+
arrange.set('right', arrangeRightItems);
|
|
244
|
+
}
|
|
245
|
+
const width = properties.has('width') ?
|
|
246
|
+
properties.get('width') : null;
|
|
247
|
+
const blankParams = [];
|
|
248
|
+
const props = {
|
|
249
|
+
arrange, width
|
|
250
|
+
};
|
|
251
|
+
const moduleInstanceName = this.getExecutor().getUniqueInstanceName('');
|
|
252
|
+
const createdComponent = this.getExecutor().createComponent(moduleInstanceName, tmpPorts, blankParams, props);
|
|
253
|
+
createdComponent.typeProp = 'module';
|
|
254
|
+
const ctxPropertyBlock = ctx.property_block_expr();
|
|
255
|
+
if (ctxPropertyBlock) {
|
|
256
|
+
const [firstBlock] = ctxPropertyBlock;
|
|
257
|
+
this.visit(firstBlock);
|
|
258
|
+
const [keyName, expressionsBlock] = this.getResult(firstBlock);
|
|
259
|
+
if (keyName === 'contains') {
|
|
260
|
+
createdComponent.moduleContainsExpressions = expressionsBlock;
|
|
261
|
+
this.expandModuleContains(createdComponent, this.getExecutor().netNamespace);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
this.setResult(ctx, createdComponent);
|
|
265
|
+
};
|
|
266
|
+
visitProperty_block_expr = (ctx) => {
|
|
267
|
+
const tmpCtx = ctx.property_key_expr();
|
|
268
|
+
this.visit(tmpCtx);
|
|
269
|
+
const keyName = this.getResult(tmpCtx);
|
|
270
|
+
const expressionsBlock = ctx.expressions_block();
|
|
271
|
+
this.setResult(ctx, [keyName, expressionsBlock]);
|
|
272
|
+
};
|
|
196
273
|
visitProperty_expr = (ctx) => {
|
|
197
274
|
const ctxPropertyKeyExpr = ctx.property_key_expr();
|
|
198
275
|
const ctxPropertyValueExpr = ctx.property_value_expr();
|
|
@@ -270,6 +347,14 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
270
347
|
&& component.copyProp) {
|
|
271
348
|
component = this.getExecutor().copyComponent(component);
|
|
272
349
|
}
|
|
350
|
+
if (component instanceof DeclaredReference
|
|
351
|
+
&& component.found
|
|
352
|
+
&& component.trailers
|
|
353
|
+
&& component.trailers.length > 0
|
|
354
|
+
&& component.trailers[0] === 'contains') {
|
|
355
|
+
component = component.value;
|
|
356
|
+
this.placeModuleContains(component);
|
|
357
|
+
}
|
|
273
358
|
if (component && component instanceof ClassComponent) {
|
|
274
359
|
const modifiers = ctx.component_modifier_expr();
|
|
275
360
|
modifiers.forEach(modifier => {
|
|
@@ -328,10 +413,65 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
328
413
|
pinValue = this.getResult(ctxPinSelectExpr);
|
|
329
414
|
}
|
|
330
415
|
else {
|
|
331
|
-
|
|
416
|
+
if (component instanceof ClassComponent) {
|
|
417
|
+
pinValue = component.getDefaultPin();
|
|
418
|
+
}
|
|
419
|
+
else {
|
|
420
|
+
const undeclaredRef = component;
|
|
421
|
+
throw 'Invalid component: ' + undeclaredRef.reference.name;
|
|
422
|
+
}
|
|
332
423
|
}
|
|
333
424
|
this.setResult(ctx, [component, pinValue]);
|
|
334
425
|
};
|
|
426
|
+
expandModuleContains(component, netNamespace) {
|
|
427
|
+
this.getExecutor().log('expanding module `contains`');
|
|
428
|
+
const executionStack = this.executionStack;
|
|
429
|
+
const resolveNet = this.createNetResolver(executionStack);
|
|
430
|
+
const executionContextName = this.getExecutor().namespace + "_"
|
|
431
|
+
+ component.instanceName
|
|
432
|
+
+ '_' + component.moduleCounter;
|
|
433
|
+
const tmpNamespace = this.getNetNamespace(netNamespace, "+/" + component.instanceName + "_" + component.moduleCounter);
|
|
434
|
+
const newExecutor = this.enterNewChildContext(executionStack, this.getExecutor(), executionContextName, { netNamespace: tmpNamespace }, [], []);
|
|
435
|
+
component.moduleCounter += 1;
|
|
436
|
+
newExecutor.resolveNet = resolveNet;
|
|
437
|
+
this.visit(component.moduleContainsExpressions);
|
|
438
|
+
const executionContext = executionStack.pop();
|
|
439
|
+
component.moduleExecutionContext = executionContext;
|
|
440
|
+
component.moduleExecutionContextName = executionContextName;
|
|
441
|
+
this.linkModuleSymbolWithContains(component, executionContext);
|
|
442
|
+
}
|
|
443
|
+
linkModuleSymbolWithContains(moduleComponent, executionContext) {
|
|
444
|
+
this.log('link module symbol');
|
|
445
|
+
const modulePinMapping = new Map();
|
|
446
|
+
moduleComponent.pins.forEach(pin => {
|
|
447
|
+
const pinName = pin.name;
|
|
448
|
+
modulePinMapping.set(pinName, pin.id);
|
|
449
|
+
});
|
|
450
|
+
const pinIdToPortMap = new Map();
|
|
451
|
+
moduleComponent.modulePinIdToPortMap = pinIdToPortMap;
|
|
452
|
+
for (const [key, component] of executionContext.scope.instances) {
|
|
453
|
+
if (component._copyID !== null && component.typeProp === 'port') {
|
|
454
|
+
const portName = component.parameters.get('net_name');
|
|
455
|
+
const modulePinId = modulePinMapping.get(portName);
|
|
456
|
+
pinIdToPortMap.set(modulePinId, component);
|
|
457
|
+
const portType = getPortType(component);
|
|
458
|
+
const tmpPin = moduleComponent.pins.get(modulePinId);
|
|
459
|
+
tmpPin.pinType = portType;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
placeModuleContains(moduleComponent) {
|
|
464
|
+
if (moduleComponent.typeProp === 'module'
|
|
465
|
+
&& moduleComponent.moduleContainsExpressions) {
|
|
466
|
+
this.log('place module `contains`');
|
|
467
|
+
this.getExecutor().mergeScope(moduleComponent.moduleExecutionContext.scope, moduleComponent.moduleExecutionContextName);
|
|
468
|
+
this.log('connect module ports');
|
|
469
|
+
for (const [pinId, portComponent] of moduleComponent.modulePinIdToPortMap) {
|
|
470
|
+
this.getExecutor().atComponent(moduleComponent, pinId);
|
|
471
|
+
this.getExecutor().toComponent(portComponent, 1);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
}
|
|
335
475
|
visitUnaryOperatorExpr = (ctx) => {
|
|
336
476
|
this.visit(ctx.data_expr());
|
|
337
477
|
let value = this.getResult(ctx.data_expr());
|
|
@@ -360,6 +500,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
360
500
|
let value;
|
|
361
501
|
const ctxCreateComponentExpr = ctx.create_component_expr();
|
|
362
502
|
const ctxCreateGraphicExpr = ctx.create_graphic_expr();
|
|
503
|
+
const ctxCreateModuleExpr = ctx.create_module_expr();
|
|
363
504
|
if (ctxCreateComponentExpr) {
|
|
364
505
|
this.visit(ctxCreateComponentExpr);
|
|
365
506
|
value = this.getResult(ctxCreateComponentExpr);
|
|
@@ -368,6 +509,10 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
368
509
|
this.visit(ctxCreateGraphicExpr);
|
|
369
510
|
value = this.getResult(ctxCreateGraphicExpr);
|
|
370
511
|
}
|
|
512
|
+
else if (ctxCreateModuleExpr) {
|
|
513
|
+
this.visit(ctxCreateModuleExpr);
|
|
514
|
+
value = this.getResult(ctxCreateModuleExpr);
|
|
515
|
+
}
|
|
371
516
|
else {
|
|
372
517
|
throw "Invalid data expression";
|
|
373
518
|
}
|
|
@@ -536,13 +681,11 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
536
681
|
}
|
|
537
682
|
};
|
|
538
683
|
visitAt_block_pin_expression_complex = (ctx) => {
|
|
539
|
-
ctx.
|
|
540
|
-
this.visit(item);
|
|
541
|
-
});
|
|
684
|
+
this.visit(ctx.expressions_block());
|
|
542
685
|
};
|
|
543
686
|
visitWire_expr_direction_only = (ctx) => {
|
|
544
687
|
const value = ctx.ID().getText();
|
|
545
|
-
if (value ===
|
|
688
|
+
if (value === WireAutoDirection.Auto || value === WireAutoDirection.Auto_) {
|
|
546
689
|
this.setResult(ctx, [value]);
|
|
547
690
|
}
|
|
548
691
|
else {
|
|
@@ -563,7 +706,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
563
706
|
useValue = this.getResult(ctxDataExpr);
|
|
564
707
|
}
|
|
565
708
|
if (useValue !== null) {
|
|
566
|
-
this.setResult(ctx, [direction, useValue]);
|
|
709
|
+
this.setResult(ctx, [direction, new UnitDimension(useValue)]);
|
|
567
710
|
return;
|
|
568
711
|
}
|
|
569
712
|
}
|
|
@@ -597,9 +740,12 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
597
740
|
const propertyName = ctx.ID().getText();
|
|
598
741
|
this.getExecutor().setProperty('..' + propertyName, result);
|
|
599
742
|
};
|
|
743
|
+
visitExpressions_block = (ctx) => {
|
|
744
|
+
this.runExpressions(this.getExecutor(), ctx.expression());
|
|
745
|
+
};
|
|
600
746
|
visitFrame_expr = (ctx) => {
|
|
601
747
|
const frameId = this.getExecutor().enterFrame();
|
|
602
|
-
this.
|
|
748
|
+
this.visit(ctx.expressions_block());
|
|
603
749
|
this.getExecutor().exitFrame(frameId);
|
|
604
750
|
};
|
|
605
751
|
visitNet_namespace_expr = (ctx) => {
|
|
@@ -630,7 +776,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
630
776
|
this.visit(ctxDataExpr);
|
|
631
777
|
const result = this.getResult(ctxDataExpr);
|
|
632
778
|
if (result) {
|
|
633
|
-
this.
|
|
779
|
+
this.visit(ctx.expressions_block());
|
|
634
780
|
}
|
|
635
781
|
else {
|
|
636
782
|
const ctxInnerIfExprs = ctx.if_inner_expr();
|
|
@@ -657,7 +803,7 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
657
803
|
this.visit(ctxDataExpr);
|
|
658
804
|
const result = this.getResult(ctxDataExpr);
|
|
659
805
|
if (result) {
|
|
660
|
-
this.
|
|
806
|
+
this.visit(ctx.expressions_block());
|
|
661
807
|
}
|
|
662
808
|
this.setResult(ctx, result);
|
|
663
809
|
};
|
|
@@ -712,6 +858,26 @@ export class ParserVisitor extends BaseVisitor {
|
|
|
712
858
|
}
|
|
713
859
|
return pins;
|
|
714
860
|
}
|
|
861
|
+
parseCreateModulePorts(portsDefinition) {
|
|
862
|
+
let leftItems = [];
|
|
863
|
+
let rightItems = [];
|
|
864
|
+
if (portsDefinition.has('left')) {
|
|
865
|
+
leftItems = portsDefinition.get('left');
|
|
866
|
+
if (!Array.isArray(leftItems)) {
|
|
867
|
+
leftItems = [leftItems];
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
if (portsDefinition.has('right')) {
|
|
871
|
+
rightItems = portsDefinition.get('right');
|
|
872
|
+
if (!Array.isArray(rightItems)) {
|
|
873
|
+
rightItems = [rightItems];
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
return {
|
|
877
|
+
left: leftItems,
|
|
878
|
+
right: rightItems
|
|
879
|
+
};
|
|
880
|
+
}
|
|
715
881
|
parseCreateComponentParams(params) {
|
|
716
882
|
const result = [];
|
|
717
883
|
if (params) {
|