From e051c5cd2589b218e715b648b588511e9b078ac2 Mon Sep 17 00:00:00 2001 From: hneemann Date: Mon, 22 Feb 2021 12:10:19 +0100 Subject: [PATCH 1/3] In code components is is allowed to write to the args-struct, see #657 --- .../digital/draw/library/ResolveGenerics.java | 69 ++++++++++++------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java index f3a32b31c..e44250957 100644 --- a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java +++ b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java @@ -128,30 +128,14 @@ public class ResolveGenerics { ArrayList newComponents = new ArrayList<>(); ArrayList newWires = new ArrayList<>(); - for (VisualElement ve : c.getElements()) { - ElementAttributes elementAttributes = ve.getElementAttributes(); - String gen = elementAttributes.get(Keys.GENERIC).trim(); - try { - if (!gen.isEmpty()) { - ElementTypeDescription elementTypeDescription = library.getElementType(ve.getElementName(), elementAttributes); + for (VisualElement ve : c.getElements()) + if (ve.equalsDescription(GenericCode.DESCRIPTION)) + handleVisualElement(c, ve, args, newComponents, newWires); + args.lock(); // allow write only in code components + for (VisualElement ve : c.getElements()) + if (!ve.equalsDescription(GenericCode.DESCRIPTION)) + handleVisualElement(c, ve, args, newComponents, newWires); - boolean isCustom = elementTypeDescription instanceof ElementTypeDescriptionCustom; - Statement genS = getStatement(gen); - Context mod = createContext(c, newComponents, newWires, args) - .declareVar("args", args); - if (isCustom) { - mod.declareFunc("setCircuit", new SetCircuitFunc(ve)); - genS.execute(mod); - } else { - mod.declareVar("this", new SubstituteLibrary.AllowSetAttributes(elementAttributes)); - genS.execute(mod); - } - elementAttributes.putToCache(GEN_ARGS_KEY, mod); - } - } catch (HGSEvalException | ParserException | IOException e) { - throw new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", ve, gen), e); - } - } c.add(newWires); for (VisualElement ve : newComponents) c.add(ve); @@ -159,6 +143,31 @@ public class ResolveGenerics { return new CircuitHolder(c, args); } + private void handleVisualElement(Circuit c, VisualElement ve, Args args, ArrayList newComponents, ArrayList newWires) throws ElementNotFoundException, NodeException { + ElementAttributes elementAttributes = ve.getElementAttributes(); + String gen = elementAttributes.get(Keys.GENERIC).trim(); + try { + if (!gen.isEmpty()) { + ElementTypeDescription elementTypeDescription = library.getElementType(ve.getElementName(), elementAttributes); + + boolean isCustom = elementTypeDescription instanceof ElementTypeDescriptionCustom; + Statement genS = getStatement(gen); + Context mod = createContext(c, newComponents, newWires, args) + .declareVar("args", args); + if (isCustom) { + mod.declareFunc("setCircuit", new SetCircuitFunc(ve)); + genS.execute(mod); + } else { + mod.declareVar("this", new SubstituteLibrary.AllowSetAttributes(elementAttributes)); + genS.execute(mod); + } + elementAttributes.putToCache(GEN_ARGS_KEY, mod); + } + } catch (HGSEvalException | ParserException | IOException e) { + throw new NodeException(Lang.get("err_evaluatingGenericsCode_N_N", ve, gen), e); + } + } + private Context createContext(Circuit circuit, ArrayList newComponents, ArrayList newWires, Args args) throws NodeException { try { Context context = new Context(); @@ -188,9 +197,11 @@ public class ResolveGenerics { */ public static final class Args implements HGSMap { private final Context args; + private boolean writeEnabled; private Args(Context args) { this.args = args; + writeEnabled = true; } @Override @@ -205,6 +216,18 @@ public class ResolveGenerics { return v; } + @Override + public void hgsMapPut(String key, Object val) throws HGSEvalException { + if (writeEnabled) + args.declareVar(key, val); + else + args.hgsMapPut(key, val); + } + + private void lock() { + writeEnabled = false; + } + @Override public boolean equals(Object o) { if (this == o) return true; From d83280e5bf8fb30a40f58bf44cfd7bb3be97c217 Mon Sep 17 00:00:00 2001 From: hneemann Date: Mon, 22 Feb 2021 15:29:07 +0100 Subject: [PATCH 2/3] adds a new global field in the generic components context, see #657 --- .../digital/draw/library/ResolveGenerics.java | 49 ++++++++++++------- src/main/resources/lang/lang_de.xml | 2 +- src/main/resources/lang/lang_en.xml | 1 + 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java index e44250957..7ba0e1650 100644 --- a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java +++ b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java @@ -37,6 +37,7 @@ public class ResolveGenerics { */ public static final String GEN_ARGS_KEY = "genArgs"; private static final String SETTINGS_KEY = "settings"; + private static final String GLOBALS_KEY = "global"; private final HashMap map; private final HashMap circuitMap; private final Circuit circuit; @@ -128,13 +129,14 @@ public class ResolveGenerics { ArrayList newComponents = new ArrayList<>(); ArrayList newWires = new ArrayList<>(); + Globals globals = new Globals(); for (VisualElement ve : c.getElements()) if (ve.equalsDescription(GenericCode.DESCRIPTION)) - handleVisualElement(c, ve, args, newComponents, newWires); - args.lock(); // allow write only in code components + handleVisualElement(c, ve, args, newComponents, newWires, globals); + globals.lock(); // allow write only in code components for (VisualElement ve : c.getElements()) if (!ve.equalsDescription(GenericCode.DESCRIPTION)) - handleVisualElement(c, ve, args, newComponents, newWires); + handleVisualElement(c, ve, args, newComponents, newWires, globals); c.add(newWires); for (VisualElement ve : newComponents) @@ -143,7 +145,7 @@ public class ResolveGenerics { return new CircuitHolder(c, args); } - private void handleVisualElement(Circuit c, VisualElement ve, Args args, ArrayList newComponents, ArrayList newWires) throws ElementNotFoundException, NodeException { + private void handleVisualElement(Circuit c, VisualElement ve, Args args, ArrayList newComponents, ArrayList newWires, Globals globals) throws ElementNotFoundException, NodeException { ElementAttributes elementAttributes = ve.getElementAttributes(); String gen = elementAttributes.get(Keys.GENERIC).trim(); try { @@ -153,6 +155,7 @@ public class ResolveGenerics { boolean isCustom = elementTypeDescription instanceof ElementTypeDescriptionCustom; Statement genS = getStatement(gen); Context mod = createContext(c, newComponents, newWires, args) + .declareVar(GLOBALS_KEY, globals) .declareVar("args", args); if (isCustom) { mod.declareFunc("setCircuit", new SetCircuitFunc(ve)); @@ -197,11 +200,9 @@ public class ResolveGenerics { */ public static final class Args implements HGSMap { private final Context args; - private boolean writeEnabled; private Args(Context args) { this.args = args; - writeEnabled = true; } @Override @@ -216,18 +217,6 @@ public class ResolveGenerics { return v; } - @Override - public void hgsMapPut(String key, Object val) throws HGSEvalException { - if (writeEnabled) - args.declareVar(key, val); - else - args.hgsMapPut(key, val); - } - - private void lock() { - writeEnabled = false; - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -333,7 +322,7 @@ public class ResolveGenerics { return; } - if (!key.equals(Context.BASE_FILE_KEY) && !key.equals(SETTINGS_KEY)) { + if (!key.equals(Context.BASE_FILE_KEY) && !key.equals(SETTINGS_KEY) && !key.equals(GLOBALS_KEY)) { contentSet.add(key); sb.append(key).append(":="); if (val instanceof String) { @@ -458,4 +447,26 @@ public class ResolveGenerics { return new SubstituteLibrary.AllowSetAttributes(elementAttributes); } } + + private static final class Globals implements HGSMap { + private final HashMap map = new HashMap<>(); + private boolean writeEnable = true; + + @Override + public void hgsMapPut(String key, Object val) throws HGSEvalException { + if (writeEnable) + map.put(key, val); + else + throw new HGSEvalException(Lang.get("err_writeInCodeComponentsOnly")); + } + + @Override + public Object hgsMapGet(String key) throws HGSEvalException { + return map.get(key); + } + + public void lock() { + writeEnable = false; + } + } } diff --git a/src/main/resources/lang/lang_de.xml b/src/main/resources/lang/lang_de.xml index b59952910..015c04670 100644 --- a/src/main/resources/lang/lang_de.xml +++ b/src/main/resources/lang/lang_de.xml @@ -1210,7 +1210,7 @@ Sind evtl. die Namen der Variablen nicht eindeutig? Mehrere Initialisierungscodes für die generischen Elemente. Fehler bei der Analyse des generischen Initialisierungscodes. - + Globale Variablen können nur in Code-Komponenten beschrieben werden. Videomodus wurde nicht erkannt ({0}) Es ist kein Dateiname für das automatische Neuladen verfügbar! diff --git a/src/main/resources/lang/lang_en.xml b/src/main/resources/lang/lang_en.xml index 1fb6eb2fc..15359257c 100644 --- a/src/main/resources/lang/lang_en.xml +++ b/src/main/resources/lang/lang_en.xml @@ -1199,6 +1199,7 @@ Multiple initialization codes for the generic elements. Error in the analysis of the generic initialization code. + Global variables can only be written in code components. There is no file name available for the automatic reload! Virtual signal {0} declared twice in line {1}! From c7b9110893c2679831194bd84d5afbec0718a181 Mon Sep 17 00:00:00 2001 From: hneemann Date: Tue, 23 Feb 2021 18:32:11 +0100 Subject: [PATCH 3/3] allows writing to global field only in the first code component; closes #657 --- src/main/dig/generic/barrelShifter/barrelShifter2.dig | 8 ++++---- .../de/neemann/digital/draw/library/ResolveGenerics.java | 4 +++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/dig/generic/barrelShifter/barrelShifter2.dig b/src/main/dig/generic/barrelShifter/barrelShifter2.dig index 783b8e6fb..c869c7df4 100644 --- a/src/main/dig/generic/barrelShifter/barrelShifter2.dig +++ b/src/main/dig/generic/barrelShifter/barrelShifter2.dig @@ -69,6 +69,7 @@ for (i:=0;i<sh;i++) { addWire(x-1,i+5,x-1,2); addWire(x-1,2,x,2); } +global.shift:=sh; o:=addComponent("Out",sh*5+2,0); o.Bits=args.dataBits; @@ -86,7 +87,7 @@ o.Label="Out"; generic - this.Bits=bitsNeededFor(args.dataBits)-1; + this.Bits=global.shift; @@ -100,9 +101,8 @@ o.Label="Out"; generic - sh:=bitsNeededFor(args.dataBits)-1; -this.'Input Splitting'=""+sh; -this.'Output Splitting'="1*"+sh; + this.'Input Splitting'=""+global.shift; +this.'Output Splitting'="1*"+global.shift; Output Splitting diff --git a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java index 7ba0e1650..a65bd79a3 100644 --- a/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java +++ b/src/main/java/de/neemann/digital/draw/library/ResolveGenerics.java @@ -131,8 +131,10 @@ public class ResolveGenerics { Globals globals = new Globals(); for (VisualElement ve : c.getElements()) - if (ve.equalsDescription(GenericCode.DESCRIPTION)) + if (ve.equalsDescription(GenericCode.DESCRIPTION)) { handleVisualElement(c, ve, args, newComponents, newWires, globals); + globals.lock(); // allow write only in first code component + } globals.lock(); // allow write only in code components for (VisualElement ve : c.getElements()) if (!ve.equalsDescription(GenericCode.DESCRIPTION))