diff --git a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java index f607fe496..b725581c9 100644 --- a/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java +++ b/src/main/java/de/neemann/digital/analyse/SubstituteLibrary.java @@ -14,6 +14,7 @@ import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.draw.library.LibraryInterface; import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.lang.Lang; @@ -121,7 +122,7 @@ public class SubstituteLibrary implements LibraryInterface { private static final class Substitute implements SubstituteInterface { private final String filename; - private ElementLibrary.ElementTypeDescriptionCustom typeDescriptionCustom; + private ElementTypeDescriptionCustom typeDescriptionCustom; private Substitute(String filename) { this.filename = filename; diff --git a/src/main/java/de/neemann/digital/draw/elements/Stats.java b/src/main/java/de/neemann/digital/draw/elements/Stats.java index 1502c902e..8be69458b 100644 --- a/src/main/java/de/neemann/digital/draw/elements/Stats.java +++ b/src/main/java/de/neemann/digital/draw/elements/Stats.java @@ -21,6 +21,7 @@ import de.neemann.digital.core.switching.PFET; import de.neemann.digital.core.wiring.*; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.gui.components.data.DummyElement; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestCaseElement; @@ -149,8 +150,8 @@ public class Stats { int transistors = 0; Circuit childCircuit = null; - if (description instanceof ElementLibrary.ElementTypeDescriptionCustom) { - ElementLibrary.ElementTypeDescriptionCustom c = (ElementLibrary.ElementTypeDescriptionCustom) description; + if (description instanceof ElementTypeDescriptionCustom) { + ElementTypeDescriptionCustom c = (ElementTypeDescriptionCustom) description; childCircuit = c.getCircuit(); transistors = childCircuit.getAttributes().get(Keys.TRANSISTORS); if (transistors > 0) diff --git a/src/main/java/de/neemann/digital/draw/elements/VisualElement.java b/src/main/java/de/neemann/digital/draw/elements/VisualElement.java index 1fe46005c..df7be1d82 100644 --- a/src/main/java/de/neemann/digital/draw/elements/VisualElement.java +++ b/src/main/java/de/neemann/digital/draw/elements/VisualElement.java @@ -13,6 +13,7 @@ import de.neemann.digital.draw.shapes.*; import de.neemann.digital.draw.shapes.Shape; import de.neemann.digital.draw.shapes.custom.CustomShape; import de.neemann.digital.gui.components.CircuitComponent; +import de.neemann.digital.hdl.hgs.Context; import de.neemann.gui.Screen; import javax.swing.*; @@ -39,6 +40,7 @@ public class VisualElement implements Drawable, Movable, AttributeListener { // shapes are recreated if attributes are changed, therefore a factory is necessary and not only a simple shape! private transient ShapeFactory shapeFactory; private transient Transform transform; + private transient Context genericArgs; // these fields are stored to disk private final String elementName; @@ -479,4 +481,19 @@ public class VisualElement implements Drawable, Movable, AttributeListener { public boolean isDecoratingShape() { return getShape() instanceof DecoratingShape; } + + /** + * Sets the generic arguments for this element + * @param genericArgs the arguments + */ + public void setGenericArgs(Context genericArgs) { + this.genericArgs = genericArgs; + } + + /** + * @return the generic arguments for this element + */ + public Context getGenericArgs() { + return genericArgs; + } } diff --git a/src/main/java/de/neemann/digital/draw/library/CustomElement.java b/src/main/java/de/neemann/digital/draw/library/CustomElement.java index 51e7822b9..4a3abb197 100644 --- a/src/main/java/de/neemann/digital/draw/library/CustomElement.java +++ b/src/main/java/de/neemann/digital/draw/library/CustomElement.java @@ -20,7 +20,7 @@ import de.neemann.digital.draw.model.ModelCreator; * existing circuit. So you can build hierarchical circuits. */ public class CustomElement implements Element { - private final ElementLibrary.ElementTypeDescriptionCustom descriptionCustom; + private final ElementTypeDescriptionCustom descriptionCustom; private final ElementLibrary library; /** @@ -29,7 +29,7 @@ public class CustomElement implements Element { * @param descriptionCustom the inner circuit * @param library the library to use. */ - public CustomElement(ElementLibrary.ElementTypeDescriptionCustom descriptionCustom, ElementLibrary library) { + public CustomElement(ElementTypeDescriptionCustom descriptionCustom, ElementLibrary library) { this.descriptionCustom = descriptionCustom; this.library = library; } @@ -40,14 +40,15 @@ public class CustomElement implements Element { * * @param subName name of the circuit, used to name unique elements * @param depth recursion depth, used to detect a circuit which contains itself + * @param errorVisualElement visual element used for error indicating * @param containingVisualElement the containing visual element * @return the {@link ModelCreator} * @throws PinException PinException * @throws NodeException NodeException * @throws ElementNotFoundException ElementNotFoundException */ - public ModelCreator getModelCreator(String subName, int depth, VisualElement containingVisualElement) throws PinException, NodeException, ElementNotFoundException { - return descriptionCustom.getModelCreator(subName, depth, containingVisualElement, library); + public ModelCreator getModelCreator(String subName, int depth, VisualElement errorVisualElement, VisualElement containingVisualElement) throws PinException, NodeException, ElementNotFoundException { + return descriptionCustom.getModelCreator(subName, depth, errorVisualElement, containingVisualElement, library); } @Override diff --git a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java index 0c63dc653..c0e8cc4b3 100644 --- a/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java +++ b/src/main/java/de/neemann/digital/draw/library/ElementLibrary.java @@ -5,13 +5,10 @@ */ package de.neemann.digital.draw.library; -import de.neemann.digital.analyse.SubstituteLibrary; -import de.neemann.digital.core.NodeException; import de.neemann.digital.core.arithmetic.*; import de.neemann.digital.core.arithmetic.Comparator; import de.neemann.digital.core.basic.*; import de.neemann.digital.core.element.ElementAttributes; -import de.neemann.digital.core.element.ElementFactory; import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.extern.External; @@ -27,9 +24,6 @@ import de.neemann.digital.core.wiring.*; import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.Tunnel; -import de.neemann.digital.draw.elements.VisualElement; -import de.neemann.digital.draw.model.ModelCreator; -import de.neemann.digital.draw.model.NetList; import de.neemann.digital.draw.shapes.ShapeFactory; import de.neemann.digital.gui.Settings; import de.neemann.digital.gui.components.data.DummyElement; @@ -37,7 +31,6 @@ import de.neemann.digital.gui.components.graphics.GraphicCard; import de.neemann.digital.gui.components.graphics.LedMatrix; import de.neemann.digital.gui.components.terminal.Keyboard; import de.neemann.digital.gui.components.terminal.Terminal; -import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.lang.Lang; import de.neemann.digital.testing.TestCaseElement; import org.slf4j.Logger; @@ -619,141 +612,6 @@ public class ElementLibrary implements Iterable return d; } - /** - * The description of a nested element. - * This is a complete circuit which is used as a element. - */ - public static final class ElementTypeDescriptionCustom extends ElementTypeDescription { - private static final int MAX_DEPTH = 30; - private final File file; - private final Circuit circuit; - private final HashMap map; - private String description; - private NetList netList; - - /** - * Creates a new element - * - * @param file the file which is loaded - * @param circuit the circuit - * @throws PinException PinException - */ - private ElementTypeDescriptionCustom(File file, Circuit circuit) throws PinException { - super(file.getName(), (ElementFactory) null, circuit.getInputNames()); - this.file = file; - this.circuit = circuit; - map = new HashMap<>(); - setShortName(file.getName()); - addAttribute(Keys.ROTATE); - addAttribute(Keys.LABEL); - addAttribute(Keys.SHAPE_TYPE); - if (circuit.getAttributes().get(Keys.IS_GENERIC)) - addAttribute(Keys.GENERIC); - } - - /** - * Returns the filename - * The returned file is opened if the user wants to modify the element - * - * @return the filename - */ - public File getFile() { - return file; - } - - /** - * @return the elements attributes - */ - public ElementAttributes getAttributes() { - return circuit.getAttributes(); - } - - /** - * @return the circuit - */ - public Circuit getCircuit() { - return circuit; - } - - /** - * Sets a custom description for this field - * - * @param description the description - */ - public void setDescription(String description) { - this.description = description; - } - - @Override - public String getDescription(ElementAttributes elementAttributes) { - if (description != null) - return description; - else - return super.getDescription(elementAttributes); - } - - /** - * Gets a {@link ModelCreator} of this circuit. - * Every time this method is called a new {@link ModelCreator} is created. - * - * @param subName name of the circuit, used to name unique elements - * @param depth recursion depth, used to detect a circuit which contains itself - * @param containingVisualElement the containing visual element - * @param library the library used - * @return the {@link ModelCreator} - * @throws PinException PinException - * @throws NodeException NodeException - * @throws ElementNotFoundException ElementNotFoundException - */ - public ModelCreator getModelCreator(String subName, int depth, VisualElement containingVisualElement, ElementLibrary library) throws PinException, NodeException, ElementNotFoundException { - if (netList == null) - netList = new NetList(circuit); - - if (depth > MAX_DEPTH) - throw new NodeException(Lang.get("err_recursiveNestingAt_N0", circuit.getOrigin())); - - if (circuit.getAttributes().get(Keys.IS_GENERIC)) { - String argsCode = containingVisualElement.getElementAttributes().get(Keys.GENERIC); - try { - Statement s = getStatement(argsCode); - Context args = new Context(); - s.execute(args); - - Circuit c = circuit.createDeepCopy(); - for (VisualElement ve : c.getElements()) { - String gen = ve.getElementAttributes().get(Keys.GENERIC).trim(); - if (!gen.isEmpty()) { - - Statement genS = getStatement(gen); - - Context mod = new Context() - .declareVar("args", args) - .declareVar("this", new SubstituteLibrary.AllowSetAttributes(ve.getElementAttributes())); - genS.execute(mod); - } - } - - return new ModelCreator(c, library, true, new NetList(netList, containingVisualElement), subName, depth, containingVisualElement); - - } catch (IOException | ParserException | HGSEvalException e) { - throw new NodeException(Lang.get("err_parsingGenericsCode"), e); - } - } else { - return new ModelCreator(circuit, library, true, new NetList(netList, containingVisualElement), subName, depth, containingVisualElement); - } - } - - private Statement getStatement(String code) throws IOException, ParserException { - Statement genS = map.get(code); - if (genS == null) { - genS = new Parser(code).parse(false); - map.put(code, genS); - } - return genS; - } - - } - /** * Used to store a elements name and its position in the elements menu. diff --git a/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java b/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java new file mode 100644 index 000000000..6a10f503b --- /dev/null +++ b/src/main/java/de/neemann/digital/draw/library/ElementTypeDescriptionCustom.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2019 Helmut Neemann. + * Use of this source code is governed by the GPL v3 license + * that can be found in the LICENSE file. + */ +package de.neemann.digital.draw.library; + +import de.neemann.digital.analyse.SubstituteLibrary; +import de.neemann.digital.core.NodeException; +import de.neemann.digital.core.element.ElementAttributes; +import de.neemann.digital.core.element.ElementFactory; +import de.neemann.digital.core.element.ElementTypeDescription; +import de.neemann.digital.core.element.Keys; +import de.neemann.digital.draw.elements.Circuit; +import de.neemann.digital.draw.elements.PinException; +import de.neemann.digital.draw.elements.VisualElement; +import de.neemann.digital.draw.model.ModelCreator; +import de.neemann.digital.draw.model.NetList; +import de.neemann.digital.hdl.hgs.*; +import de.neemann.digital.lang.Lang; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; + +/** + * The description of a nested element. + * This is a complete circuit which is used as a element. + */ +public final class ElementTypeDescriptionCustom extends ElementTypeDescription { + private static final int MAX_DEPTH = 30; + private final File file; + private final Circuit circuit; + private final HashMap map; + private String description; + private NetList netList; + + /** + * Creates a new element + * + * @param file the file which is loaded + * @param circuit the circuit + * @throws PinException PinException + */ + ElementTypeDescriptionCustom(File file, Circuit circuit) throws PinException { + super(file.getName(), (ElementFactory) null, circuit.getInputNames()); + this.file = file; + this.circuit = circuit; + map = new HashMap<>(); + setShortName(file.getName()); + addAttribute(Keys.ROTATE); + addAttribute(Keys.LABEL); + addAttribute(Keys.SHAPE_TYPE); + if (circuit.getAttributes().get(Keys.IS_GENERIC)) + addAttribute(Keys.GENERIC); + } + + /** + * Returns the filename + * The returned file is opened if the user wants to modify the element + * + * @return the filename + */ + public File getFile() { + return file; + } + + /** + * @return the elements attributes + */ + public ElementAttributes getAttributes() { + return circuit.getAttributes(); + } + + /** + * @return the circuit + */ + public Circuit getCircuit() { + return circuit; + } + + /** + * Sets a custom description for this field + * + * @param description the description + */ + public void setDescription(String description) { + this.description = description; + } + + @Override + public String getDescription(ElementAttributes elementAttributes) { + if (description != null) + return description; + else + return super.getDescription(elementAttributes); + } + + /** + * Gets a {@link ModelCreator} of this circuit. + * Every time this method is called a new {@link ModelCreator} is created. + * + * @param subName name of the circuit, used to name unique elements + * @param depth recursion depth, used to detect a circuit which contains itself + * @param containingVisualElement the containing visual element + * @param library the library used + * @return the {@link ModelCreator} + * @throws PinException PinException + * @throws NodeException NodeException + * @throws ElementNotFoundException ElementNotFoundException + */ + ModelCreator getModelCreator(String subName, int depth, VisualElement errorVisualElement, VisualElement containingVisualElement, ElementLibrary library) throws PinException, NodeException, ElementNotFoundException { + if (netList == null) + netList = new NetList(circuit); + + if (depth > MAX_DEPTH) + throw new NodeException(Lang.get("err_recursiveNestingAt_N0", circuit.getOrigin())); + + if (circuit.getAttributes().get(Keys.IS_GENERIC)) { + try { + Context args; + if (containingVisualElement != null) { + args = containingVisualElement.getGenericArgs(); + if (args==null) { + String argsCode = containingVisualElement.getElementAttributes().get(Keys.GENERIC); + Statement s = getStatement(argsCode); + args = new Context(); + if (containingVisualElement.getGenericArgs() != null) + args.declareVar("args", containingVisualElement.getGenericArgs()); + s.execute(args); + } + } else + args = new Context(); + + Circuit c = circuit.createDeepCopy(); + for (VisualElement ve : c.getElements()) { + String gen = ve.getElementAttributes().get(Keys.GENERIC).trim(); + if (!gen.isEmpty()) { + boolean isCustom = library.getElementType(ve.getElementName()) instanceof ElementTypeDescriptionCustom; + Statement genS = getStatement(gen); + if (isCustom) { + Context mod = new Context() + .declareVar("args", args); + genS.execute(mod); + ve.setGenericArgs(mod); + } else { + Context mod = new Context() + .declareVar("args", args) + .declareVar("this", new SubstituteLibrary.AllowSetAttributes(ve.getElementAttributes())); + genS.execute(mod); + } + } + } + + return new ModelCreator(c, library, true, new NetList(netList, errorVisualElement), subName, depth, errorVisualElement); + } catch (IOException | ParserException | HGSEvalException e) { + throw new NodeException(Lang.get("err_parsingGenericsCode"), e); + } + } else + return new ModelCreator(circuit, library, true, new NetList(netList, errorVisualElement), subName, depth, errorVisualElement); + } + + private Statement getStatement(String code) throws IOException, ParserException { + Statement genS = map.get(code); + if (genS == null) { + genS = new Parser(code).parse(false); + map.put(code, genS); + } + return genS; + } + +} diff --git a/src/main/java/de/neemann/digital/draw/model/ModelCreator.java b/src/main/java/de/neemann/digital/draw/model/ModelCreator.java index 4f52c6197..b495fea39 100644 --- a/src/main/java/de/neemann/digital/draw/model/ModelCreator.java +++ b/src/main/java/de/neemann/digital/draw/model/ModelCreator.java @@ -151,7 +151,7 @@ public class ModelCreator implements Iterable { ModelCreator child = ce.getModelCreator( combineNames(subName, me.getVisualElement().getElementAttributes().getLabel()), depth + 1, - containingVisualElement != null ? containingVisualElement : me.getVisualElement()); + containingVisualElement != null ? containingVisualElement : me.getVisualElement(), me.getVisualElement()); modelCreators.add(child); HashMap netMatch = new HashMap<>(); diff --git a/src/main/java/de/neemann/digital/draw/shapes/LayoutShape.java b/src/main/java/de/neemann/digital/draw/shapes/LayoutShape.java index 1466fdcc3..c5fe1ede2 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/LayoutShape.java +++ b/src/main/java/de/neemann/digital/draw/shapes/LayoutShape.java @@ -16,7 +16,7 @@ import de.neemann.digital.core.wiring.Clock; import de.neemann.digital.draw.elements.*; import de.neemann.digital.draw.graphics.*; import de.neemann.digital.draw.graphics.Polygon; -import de.neemann.digital.draw.library.ElementLibrary; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.lang.Lang; import java.awt.*; @@ -52,7 +52,7 @@ public class LayoutShape implements Shape { * @throws NodeException NodeException * @throws PinException PinException */ - public LayoutShape(ElementLibrary.ElementTypeDescriptionCustom custom, ElementAttributes elementAttributes) throws NodeException, PinException { + public LayoutShape(ElementTypeDescriptionCustom custom, ElementAttributes elementAttributes) throws NodeException, PinException { left = new PinList(false); right = new PinList(false); top = new PinList(true); diff --git a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java index d763b102c..49564f1ee 100644 --- a/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java +++ b/src/main/java/de/neemann/digital/draw/shapes/ShapeFactory.java @@ -20,6 +20,7 @@ import de.neemann.digital.core.wiring.*; import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.Tunnel; import de.neemann.digital.draw.library.ElementLibrary; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.draw.library.JarComponentManager; import de.neemann.digital.draw.shapes.custom.CustomShape; import de.neemann.digital.draw.shapes.custom.CustomShapeDescription; @@ -191,9 +192,9 @@ public final class ShapeFactory { throw new NodeException(Lang.get("err_noShapeFoundFor_N", elementName)); else { ElementTypeDescription pt = library.getElementType(elementName); - if (pt instanceof ElementLibrary.ElementTypeDescriptionCustom) { + if (pt instanceof ElementTypeDescriptionCustom) { // Custom component - ElementLibrary.ElementTypeDescriptionCustom customDescr = (ElementLibrary.ElementTypeDescriptionCustom) pt; + ElementTypeDescriptionCustom customDescr = (ElementTypeDescriptionCustom) pt; CustomCircuitShapeType shapeType = customDescr.getAttributes().get(Keys.SHAPE_TYPE); final CustomCircuitShapeType localShapeType = elementAttributes.get(Keys.SHAPE_TYPE); if (!localShapeType.equals(CustomCircuitShapeType.DEFAULT)) diff --git a/src/main/java/de/neemann/digital/gui/ExportZipAction.java b/src/main/java/de/neemann/digital/gui/ExportZipAction.java index 169072e24..fa7194684 100644 --- a/src/main/java/de/neemann/digital/gui/ExportZipAction.java +++ b/src/main/java/de/neemann/digital/gui/ExportZipAction.java @@ -10,6 +10,7 @@ import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.lang.Lang; import de.neemann.gui.ToolTipAction; @@ -65,8 +66,8 @@ public class ExportZipAction extends ToolTipAction { if (!elementSet.contains(name)) { elementSet.add(name); ElementTypeDescription desc = lib.getElementType(name); - if (desc instanceof ElementLibrary.ElementTypeDescriptionCustom) { - ElementLibrary.ElementTypeDescriptionCustom custom = (ElementLibrary.ElementTypeDescriptionCustom) desc; + if (desc instanceof ElementTypeDescriptionCustom) { + ElementTypeDescriptionCustom custom = (ElementTypeDescriptionCustom) desc; addFile(zip, custom.getFile(), custom.getCircuit()); } } diff --git a/src/main/java/de/neemann/digital/gui/Main.java b/src/main/java/de/neemann/digital/gui/Main.java index ec7d3f6f6..e0462a60d 100644 --- a/src/main/java/de/neemann/digital/gui/Main.java +++ b/src/main/java/de/neemann/digital/gui/Main.java @@ -23,6 +23,7 @@ import de.neemann.digital.draw.gif.GifExporter; import de.neemann.digital.draw.graphics.*; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.draw.model.AsyncSequentialClock; import de.neemann.digital.draw.model.ModelCreator; import de.neemann.digital.draw.model.RealTimeClock; @@ -368,7 +369,7 @@ public final class Main extends JFrame implements ClosingWindowListener.ConfirmS if (file == null) file = new File(name); try { - ElementLibrary.ElementTypeDescriptionCustom description = + ElementTypeDescriptionCustom description = ElementLibrary.createCustomDescription(file, circuit, library); description.setShortName(name); description.setDescription(Lang.evalMultilingualContent(circuit.getAttributes().get(Keys.DESCRIPTION))); diff --git a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java index 9c38f3079..84276d74d 100644 --- a/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java +++ b/src/main/java/de/neemann/digital/gui/components/CircuitComponent.java @@ -17,10 +17,7 @@ import de.neemann.digital.core.switching.Switch; import de.neemann.digital.draw.elements.*; import de.neemann.digital.draw.graphics.Vector; import de.neemann.digital.draw.graphics.*; -import de.neemann.digital.draw.library.ElementLibrary; -import de.neemann.digital.draw.library.ElementNotFoundException; -import de.neemann.digital.draw.library.LibraryListener; -import de.neemann.digital.draw.library.LibraryNode; +import de.neemann.digital.draw.library.*; import de.neemann.digital.draw.shapes.Drawable; import de.neemann.digital.draw.shapes.InputShape; import de.neemann.digital.draw.shapes.ShapeFactory; @@ -1030,14 +1027,14 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib SwingUtilities.convertPointToScreen(p, CircuitComponent.this); AttributeDialog attributeDialog = new AttributeDialog(parent, p, list, element.getElementAttributes()).setVisualElement(element); ElementTypeDescription elementType = library.getElementType(element.getElementName()); - if (elementType instanceof ElementLibrary.ElementTypeDescriptionCustom) { + if (elementType instanceof ElementTypeDescriptionCustom) { attributeDialog.addButton(Lang.get("attr_openCircuitLabel"), new ToolTipAction(Lang.get("attr_openCircuit")) { @Override public void actionPerformed(ActionEvent e) { attributeDialog.dispose(); new Main.MainBuilder() .setParent(parent) - .setFileToOpen(((ElementLibrary.ElementTypeDescriptionCustom) elementType).getFile()) + .setFileToOpen(((ElementTypeDescriptionCustom) elementType).getFile()) .setLibrary(library) .denyMostFileActions() .keepPrefMainFile() @@ -1225,7 +1222,7 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib private ArrayList getAttributeList(VisualElement ve) throws ElementNotFoundException { ArrayList list = library.getElementType(ve.getElementName()).getAttributeList(); - if (getCircuit().getAttributes().get(Keys.IS_GENERIC)) { + if (getCircuit().getAttributes().get(Keys.IS_GENERIC) && !list.contains(Keys.GENERIC)) { list = new ArrayList<>(list); list.add(Keys.GENERIC); } diff --git a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java index 83b591121..d99edd8c3 100644 --- a/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java +++ b/src/main/java/de/neemann/digital/hdl/model2/HDLModel.java @@ -21,6 +21,7 @@ import de.neemann.digital.draw.elements.PinException; import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementNotFoundException; +import de.neemann.digital.draw.library.ElementTypeDescriptionCustom; import de.neemann.digital.hdl.model2.clock.HDLClockIntegrator; import de.neemann.digital.hdl.model2.expression.*; @@ -59,8 +60,8 @@ public class HDLModel implements Iterable { public HDLNode createNode(VisualElement v, HDLCircuit parent) throws HDLException { try { ElementTypeDescription td = elementLibrary.getElementType(v.getElementName()); - if (td instanceof ElementLibrary.ElementTypeDescriptionCustom) { - ElementLibrary.ElementTypeDescriptionCustom tdc = (ElementLibrary.ElementTypeDescriptionCustom) td; + if (td instanceof ElementTypeDescriptionCustom) { + ElementTypeDescriptionCustom tdc = (ElementTypeDescriptionCustom) td; HDLCircuit c = circuitMap.get(tdc.getCircuit()); if (c == null) { diff --git a/src/test/java/de/neemann/digital/integration/TestExamples.java b/src/test/java/de/neemann/digital/integration/TestExamples.java index 74f0f757e..3f3f92583 100644 --- a/src/test/java/de/neemann/digital/integration/TestExamples.java +++ b/src/test/java/de/neemann/digital/integration/TestExamples.java @@ -43,8 +43,8 @@ public class TestExamples extends TestCase { */ public void testTestExamples() throws Exception { File examples = new File(Resources.getRoot(), "/dig/test"); - assertEquals(162, new FileScanner(this::check).scan(examples)); - assertEquals(160, testCasesInFiles); + assertEquals(164, new FileScanner(this::check).scan(examples)); + assertEquals(161, testCasesInFiles); } /** diff --git a/src/test/resources/dig/test/generics/mainNest.dig b/src/test/resources/dig/test/generics/mainNest.dig new file mode 100644 index 000000000..39f550b09 --- /dev/null +++ b/src/test/resources/dig/test/generics/mainNest.dig @@ -0,0 +1,214 @@ + + + 1 + + + + Clock + + + runRealTime + true + + + Label + C + + + Frequency + 5 + + + + + + VDD + + + + + Splitter + + + Input Splitting + 2,3,4 + + + Output Splitting + 9 + + + + + + Out + + + Label + O + + + Bits + 9 + + + intFormat + hex + + + + + + Testcase + + + Testdata + + C O +loop(n,512) +C (n+1) +end loop + + + + + + + nestError.dig + + + generic + bits:=2; + + + + + + nestError.dig + + + generic + bits:=3; + + + + + + nestError.dig + + + generic + bits:=4; + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/test/resources/dig/test/generics/nestError.dig b/src/test/resources/dig/test/generics/nestError.dig new file mode 100644 index 000000000..f4e33da83 --- /dev/null +++ b/src/test/resources/dig/test/generics/nestError.dig @@ -0,0 +1,105 @@ + + + 1 + + + isGeneric + true + + + + + In + + + Label + en + + + + + + count.dig + + + generic + bits:=args.bits; + + + + + + Clock + + + runRealTime + true + + + Label + C + + + Frequency + 5 + + + + + + Out + + + Label + d + + + + + + Out + + + Label + ov + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file