first circuit modification

This commit is contained in:
hneemann 2021-01-04 09:13:05 +01:00
parent d765d3b154
commit 4ba6bfd855
4 changed files with 82 additions and 25 deletions

View File

@ -15,6 +15,7 @@ import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.library.ElementLibrary; import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.library.ElementNotFoundException; import de.neemann.digital.draw.library.ElementNotFoundException;
import de.neemann.digital.draw.library.LibraryInterface; import de.neemann.digital.draw.library.LibraryInterface;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.hdl.hgs.*;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -72,6 +73,11 @@ public class SubstituteLibrary implements LibraryInterface {
return parent.getElementType(elementName, attr); return parent.getElementType(elementName, attr);
} }
@Override
public ShapeFactory getShapeFactory() {
return parent.getShapeFactory();
}
private interface SubstituteInterface { private interface SubstituteInterface {
ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException; ElementTypeDescription getElementType(ElementAttributes attr, ElementLibrary library) throws PinException, IOException;
} }

View File

@ -340,9 +340,7 @@ public class ElementLibrary implements Iterable<ElementLibrary.ElementContainer>
this.shapeFactory = shapeFactory; this.shapeFactory = shapeFactory;
} }
/** @Override
* @return the shape factory
*/
public ShapeFactory getShapeFactory() { public ShapeFactory getShapeFactory() {
return shapeFactory; return shapeFactory;
} }

View File

@ -7,11 +7,18 @@ package de.neemann.digital.draw.library;
import de.neemann.digital.core.element.ElementAttributes; import de.neemann.digital.core.element.ElementAttributes;
import de.neemann.digital.core.element.ElementTypeDescription; import de.neemann.digital.core.element.ElementTypeDescription;
import de.neemann.digital.draw.shapes.ShapeFactory;
/** /**
* Library interface used by the model creator * Library interface used by the model creator
*/ */
public interface LibraryInterface { public interface LibraryInterface {
/**
* @return the shape factory
*/
ShapeFactory getShapeFactory();
/** /**
* Creates a element description. * Creates a element description.
* *

View File

@ -10,16 +10,17 @@ import de.neemann.digital.core.NodeException;
import de.neemann.digital.core.element.Keys; import de.neemann.digital.core.element.Keys;
import de.neemann.digital.draw.elements.Circuit; import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.VisualElement; import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.elements.Wire;
import de.neemann.digital.draw.graphics.Vector;
import de.neemann.digital.hdl.hgs.*; import de.neemann.digital.hdl.hgs.*;
import de.neemann.digital.hdl.hgs.function.Function; import de.neemann.digital.hdl.hgs.function.Function;
import de.neemann.digital.hdl.hgs.function.InnerFunction; import de.neemann.digital.hdl.hgs.function.InnerFunction;
import de.neemann.digital.lang.Lang; import de.neemann.digital.lang.Lang;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.*;
import java.util.HashSet;
import java.util.List; import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
import java.util.Objects;
/** /**
* Resolves a generic circuit and makes it non generic * Resolves a generic circuit and makes it non generic
@ -48,16 +49,18 @@ public class ResolveGenerics {
*/ */
public CircuitHolder resolveCircuit(VisualElement visualElement, Circuit circuit, LibraryInterface library) throws NodeException, ElementNotFoundException { public CircuitHolder resolveCircuit(VisualElement visualElement, Circuit circuit, LibraryInterface library) throws NodeException, ElementNotFoundException {
this.library = library; this.library = library;
final Args args = createArgs(visualElement, circuit); final Circuit c = circuit.createDeepCopy();
ArrayList<VisualElement> newComponents = new ArrayList<>();
final Args args = createArgs(visualElement, c, newComponents);
Circuit c = circuit.createDeepCopy();
for (VisualElement ve : c.getElements()) { for (VisualElement ve : c.getElements()) {
String gen = ve.getElementAttributes().get(Keys.GENERIC).trim(); String gen = ve.getElementAttributes().get(Keys.GENERIC).trim();
try { try {
if (!gen.isEmpty()) { if (!gen.isEmpty()) {
boolean isCustom = library.getElementType(ve.getElementName(), ve.getElementAttributes()).isCustom(); boolean isCustom = library.getElementType(ve.getElementName(), ve.getElementAttributes()).isCustom();
Statement genS = getStatement(gen); Statement genS = getStatement(gen);
Context mod = publishCircuitPath(new Context(), circuit); Context mod = createContext(c, newComponents);
if (isCustom) { if (isCustom) {
mod.declareVar("args", args) mod.declareVar("args", args)
.declareFunc("setCircuit", new SetCircuitFunc(ve)); .declareFunc("setCircuit", new SetCircuitFunc(ve));
@ -75,20 +78,26 @@ public class ResolveGenerics {
throw ex; throw ex;
} }
} }
for (VisualElement ve : newComponents)
c.add(ve);
return new CircuitHolder(c, args); return new CircuitHolder(c, args);
} }
private Context publishCircuitPath(Context context, Circuit circuit) throws NodeException { private Context createContext(Circuit circuit, ArrayList<VisualElement> newComponents) throws NodeException {
try { try {
Context context = new Context();
if (circuit.getOrigin() != null) if (circuit.getOrigin() != null)
context.declareVar(Context.BASE_FILE_KEY, circuit.getOrigin().getPath()); context.declareVar(Context.BASE_FILE_KEY, circuit.getOrigin().getPath());
context.declareFunc("addWire", new AddWire(circuit));
context.declareFunc("addComponent", new AddComponent(newComponents));
return context; return context;
} catch (HGSEvalException e) { } catch (HGSEvalException e) {
throw new NodeException("error setting the base filename", e); throw new NodeException("error setting the base filename", e);
} }
} }
private Args createArgs(VisualElement visualElement, Circuit circuit) throws NodeException { private Args createArgs(VisualElement visualElement, Circuit circuit, ArrayList<VisualElement> newComponents) throws NodeException {
Context context; Context context;
if (visualElement != null) { if (visualElement != null) {
context = visualElement.getGenericArgs(); context = visualElement.getGenericArgs();
@ -96,7 +105,7 @@ public class ResolveGenerics {
String argsCode = visualElement.getElementAttributes().get(Keys.GENERIC); String argsCode = visualElement.getElementAttributes().get(Keys.GENERIC);
try { try {
Statement s = getStatement(argsCode); Statement s = getStatement(argsCode);
context = new Context(); context = createContext(circuit, newComponents);
s.execute(context); s.execute(context);
} catch (HGSEvalException | ParserException | IOException e) { } catch (HGSEvalException | ParserException | IOException e) {
final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", visualElement, argsCode), e); final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", visualElement, argsCode), e);
@ -105,7 +114,7 @@ public class ResolveGenerics {
} }
} }
} else { } else {
context = publishCircuitPath(new Context(), circuit); context = createContext(circuit, newComponents);
List<VisualElement> g = circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED)); List<VisualElement> g = circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION) && v.getElementAttributes().get(Keys.ENABLED));
if (g.size() == 0) if (g.size() == 0)
throw new NodeException(Lang.get("err_noGenericInitCode")); throw new NodeException(Lang.get("err_noGenericInitCode"));
@ -252,17 +261,19 @@ public class ResolveGenerics {
return; return;
} }
contentSet.add(key); if (!key.equals(Context.BASE_FILE_KEY)) {
sb.append(key).append(":="); contentSet.add(key);
if (val instanceof String) { sb.append(key).append(":=");
sb.append("\""); if (val instanceof String) {
escapeString(sb, (String) val); sb.append("\"");
sb.append("\""); escapeString(sb, (String) val);
} else if (val instanceof Integer) sb.append("\"");
sb.append("int(").append(val).append(")"); } else if (val instanceof Integer)
else sb.append("int(").append(val).append(")");
sb.append(val); else
sb.append(";\n"); sb.append(val);
sb.append(";\n");
}
} }
static void escapeString(StringBuilder sb, String str) { static void escapeString(StringBuilder sb, String str) {
@ -316,4 +327,39 @@ public class ResolveGenerics {
return 0; return 0;
} }
} }
private final static class AddWire extends Function {
private final Circuit circuit;
private AddWire(Circuit circuit) {
super(4);
this.circuit = circuit;
}
@Override
protected Object f(Object... args) throws HGSEvalException {
Vector p1 = new Vector(Value.toInt(args[0]) * SIZE, Value.toInt(args[1]) * SIZE);
Vector p2 = new Vector(Value.toInt(args[2]) * SIZE, Value.toInt(args[3]) * SIZE);
circuit.add(new Wire(p1, p2));
return null;
}
}
private final class AddComponent extends Function {
private final ArrayList<VisualElement> newComponents;
private AddComponent(ArrayList<VisualElement> newComponents) {
super(3);
this.newComponents = newComponents;
}
@Override
protected Object f(Object... args) throws HGSEvalException {
String name = args[0].toString();
Vector pos = new Vector(Value.toInt(args[1]) * SIZE, Value.toInt(args[2]) * SIZE);
VisualElement ve = new VisualElement(name).setPos(pos).setShapeFactory(library.getShapeFactory());
newComponents.add(ve);
return new SubstituteLibrary.AllowSetAttributes(ve.getElementAttributes());
}
}
} }