fixes the concrete circuit creation; see #543

This commit is contained in:
hneemann 2020-11-05 08:02:13 +01:00
parent 287a6a9975
commit 6c65bccd2e
6 changed files with 104 additions and 29 deletions

View File

@ -81,20 +81,20 @@
<entry>
<string>generic</string>
<string>if (args.direction=&quot;right&quot;) {
export circuit:=&quot;shift-fixed-right-inc.dig&quot;;
} else {
if (args.direction=&quot;arith&quot;) {
export circuit:=&quot;shift-fixed-arith-right-inc.dig&quot;;
} else {
if (args.direction=&quot;left&quot;) {
export circuit:=&quot;shift-fixed-left-inc.dig&quot;;
} else {
panic(&quot;only \&quot;left\&quot;, \&quot;right\&quot; or \&quot;arith\&quot; is allowed as direction, not \&quot;&quot;+args.direction+&quot;\&quot;!&quot;);
}
}
}
export circuit:=&quot;shift-fixed-right-inc.dig&quot;;
} else {
if (args.direction=&quot;arith&quot;) {
export circuit:=&quot;shift-fixed-arith-right-inc.dig&quot;;
} else {
if (args.direction=&quot;left&quot;) {
export circuit:=&quot;shift-fixed-left-inc.dig&quot;;
} else {
panic(&quot;only \&quot;left\&quot;, \&quot;right\&quot; or \&quot;arith\&quot; is allowed as direction, not \&quot;&quot;+args.direction+&quot;\&quot;!&quot;);
}
}
}
export shiftBits:=bitsNeededFor(args.dataBits-1);</string>
shiftBits:=bitsNeededFor(args.dataBits-1);</string>
</entry>
</elementAttributes>
<pos x="420" y="120"/>

View File

@ -13,7 +13,7 @@
<elementAttributes>
<entry>
<string>generic</string>
<string>export shift := 1&lt;&lt;(args.shiftBits-1);
<string>shift := 1&lt;&lt;(args.shiftBits-1);
setCircuit(args.circuit);</string>
</entry>
</elementAttributes>
@ -87,8 +87,8 @@ setCircuit(args.circuit);</string>
<entry>
<string>generic</string>
<string>if (args.shiftBits=2) {
export shift := 1;
setCircuit(args.circuit);
export shift := 1;
setCircuit(args.circuit);
} else {
export shiftBits := args.shiftBits-1;
}</string>

View File

@ -12,10 +12,12 @@ import de.neemann.digital.draw.elements.Circuit;
import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.hdl.hgs.*;
import de.neemann.digital.hdl.hgs.function.Function;
import de.neemann.digital.hdl.hgs.function.InnerFunction;
import de.neemann.digital.lang.Lang;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
@ -25,6 +27,7 @@ import java.util.Objects;
public class ResolveGenerics {
private final HashMap<String, Statement> map;
private LibraryInterface library;
/**
* Creates a new instance
@ -44,6 +47,7 @@ public class ResolveGenerics {
* @throws ElementNotFoundException ElementNotFoundException
*/
public CircuitHolder resolveCircuit(VisualElement visualElement, Circuit circuit, LibraryInterface library) throws NodeException, ElementNotFoundException {
this.library = library;
final Args args = createArgs(visualElement, circuit);
Circuit c = circuit.createDeepCopy();
@ -53,18 +57,17 @@ public class ResolveGenerics {
if (!gen.isEmpty()) {
boolean isCustom = library.getElementType(ve.getElementName(), ve.getElementAttributes()).isCustom();
Statement genS = getStatement(gen);
Context mod = new Context();
if (isCustom) {
Context mod = new Context()
.declareVar("args", args)
mod.declareVar("args", args)
.declareFunc("setCircuit", new SetCircuitFunc(ve));
genS.execute(mod);
ve.setGenericArgs(mod);
} else {
Context mod = new Context()
.declareVar("args", args)
mod.declareVar("args", args)
.declareVar("this", new SubstituteLibrary.AllowSetAttributes(ve.getElementAttributes()));
genS.execute(mod);
}
ve.setGenericArgs(mod);
}
} catch (HGSEvalException | ParserException | IOException e) {
final NodeException ex = new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", ve, gen), e);
@ -158,7 +161,7 @@ public class ResolveGenerics {
/**
* Holds the circuit and the args that created that circuit.
*/
public static final class CircuitHolder {
public final class CircuitHolder {
private final Circuit circuit;
private final Args args;
@ -180,6 +183,70 @@ public class ResolveGenerics {
public Args getArgs() {
return args;
}
/**
* Converts a circuit that is only suitable for creating a model
* to a circuit that can also be edited and saved.
*
* @return this for chained calls
*/
public CircuitHolder cleanupConcreteCircuit() {
for (VisualElement gic : circuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION)))
circuit.delete(gic);
for (VisualElement v : circuit.getElements()) {
try {
boolean isCustom = library.getElementType(v.getElementName(), v.getElementAttributes()).isCustom();
if (isCustom)
v.getElementAttributes().set(Keys.GENERIC, createGenericCode(v.getGenericArgs()));
else
v.getElementAttributes().set(Keys.GENERIC, "");
} catch (ElementNotFoundException e) {
// can not happen
e.printStackTrace();
}
v.setGenericArgs(null);
}
circuit.getAttributes().set(Keys.IS_GENERIC, false);
return this;
}
}
private static String createGenericCode(Context args) {
StringBuilder sb = new StringBuilder();
HashSet<String> contentSet = new HashSet<>();
addVal(sb, "", args, contentSet);
return sb.toString();
}
private static void addVal(StringBuilder sb, String key, Object val, HashSet<String> contentSet) {
if (contentSet.contains(key))
return;
if (val instanceof InnerFunction)
return;
if (val instanceof Context) {
Context c = (Context) val;
for (String k : c.getKeySet()) {
Object v = c.hgsMapGet(k);
if (!(v instanceof Args))
addVal(sb, k, v, contentSet);
}
for (String k : c.getKeySet()) {
Object v = c.hgsMapGet(k);
if (v instanceof Args)
addVal(sb, k, ((Args) v).args, contentSet);
}
return;
}
contentSet.add(key);
if (val instanceof String)
sb.append(key).append(":=\"").append(val).append("\";\n");
else
sb.append(key).append(":=").append(val).append(";\n");
}
private static final class SetCircuitFunc extends Function {

View File

@ -1158,14 +1158,15 @@ public class CircuitComponent extends JComponent implements ChangedListener, Lib
try {
attributeDialog.fireOk();
ElementAttributes modified = attributeDialog.getModifiedAttributes();
if (modified != null && !isLocked()) {
if (modified != null && !isLocked() && !modified.equals(element.getElementAttributes())) {
Modification<Circuit> mod = new ModifyAttributes(element, modified);
modify(checkNetRename(element, modified, mod));
}
Circuit concreteCircuit = new ResolveGenerics().resolveCircuit(element, getCircuit(), library).getCircuit();
for (VisualElement gic : concreteCircuit.getElements(v -> v.equalsDescription(GenericInitCode.DESCRIPTION)))
concreteCircuit.delete(gic);
concreteCircuit.getAttributes().set(Keys.IS_GENERIC, false);
Circuit concreteCircuit = new ResolveGenerics()
.resolveCircuit(element, getCircuit(), library)
.cleanupConcreteCircuit()
.getCircuit();
new Main.MainBuilder()
.setParent(parent)

View File

@ -281,6 +281,13 @@ public class Context implements HGSMap {
return map.get(key);
}
/**
* @return the set of all contained values
*/
public HashSet<String> getKeySet() {
return new HashSet<>(map.keySet());
}
private static final class FunctionPrint extends InnerFunction {
private FunctionPrint() {
super(-1);

View File

@ -637,14 +637,14 @@ public class Parser {
}
}
private static class StructLiteral implements Expression {
private static final class StructLiteral implements Expression {
private final HashMap<String, Expression> map;
private StructLiteral() {
map = new HashMap<>();
}
public void add(String key, Expression exp) {
private void add(String key, Expression exp) {
map.put(key, exp);
}