diff --git a/src/com/characterforming/jrte/engine/ModelCompiler.java b/src/com/characterforming/jrte/engine/ModelCompiler.java
index e3da77a..93f59b5 100755
--- a/src/com/characterforming/jrte/engine/ModelCompiler.java
+++ b/src/com/characterforming/jrte/engine/ModelCompiler.java
@@ -367,7 +367,6 @@ private boolean createModelFile(File riboseModelFile, Logger rtcLogger) {
private boolean compileTransducer(File inrFile) throws RiboseException {
int size = (int)inrFile.length();
byte[] bytes = null;
- boolean fail = true;
try (DataInputStream f = new DataInputStream(new FileInputStream(inrFile))) {
this.reset(inrFile);
int position = 0, length = size;
@@ -381,11 +380,11 @@ private boolean compileTransducer(File inrFile) throws RiboseException {
} catch (FileNotFoundException e) {
this.addError(String.format("%1$s: File not found '%2$s'",
this.transducerName, inrFile.getPath()));
- return !fail;
+ return false;
} catch (IOException e) {
this.addError(String.format("%1$s: IOException compiling '%2$s'; %3$s",
this.transducerName, inrFile.getPath(), e.getMessage()));
- return !fail;
+ return false;
}
try {
Bytes automaton = Codec.encode("Automaton");
@@ -397,15 +396,11 @@ private boolean compileTransducer(File inrFile) throws RiboseException {
this.transductor.stop();
assert this.transductor.status().isStopped();
this.saveTransducer();
- fail = false;
- } catch (ModelException | EffectorException | DomainErrorException e) {
+ } catch (ModelException | EffectorException | DomainErrorException | CharacterCodingException e) {
this.addError(String.format("%1$s: Failed to compile '%2$s'; %3$s",
this.transducerName, inrFile.getPath(), e.getMessage()));
- } catch (CharacterCodingException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
}
- return !fail;
+ return true;
}
private boolean validate() {
@@ -414,7 +409,7 @@ private boolean validate() {
this.addError(String.format("Error: Invalid %2$s token '%1$s' on tape 0",
token.asString(), token.getTypeName()));
} else if (token.getSymbol().bytes().length > 1
- && !this.tapeTokens.get(2).contains(token)) {
+ && !this.tapeTokens.get(2).contains(token)) {
this.addError(String.format("Error: Unrecognized signal reference '%1$s' on tape 0",
token.asString()));
}
@@ -445,9 +440,8 @@ private boolean validate() {
if (super.transducerNameIndex[ordinal] == null
|| !super.transducerNameIndex[ordinal].equals(e.getKey())
|| super.transducerOffsetIndex[ordinal] <= 0) {
- this.addError(String.format("'%1$s': referenced but not compiled in model",
+ this.addError(String.format("'%1$s': referenced but not compiled in model",
e.getKey().asString()));
-
}
}
@@ -467,13 +461,10 @@ void saveTransducer() throws ModelException, CharacterCodingException {
int nInputs = this.kernelMatrix.length;
int nStates = this.kernelMatrix[0].length;
int nTransitions = 0;
- for (int input = 0; input < nInputs; input++) {
- for (int state = 0; state < nStates; state++) {
- if (this.kernelMatrix[input][state][1] != 0) {
+ for (int input = 0; input < nInputs; input++)
+ for (int state = 0; state < nStates; state++)
+ if (this.kernelMatrix[input][state][1] != 0)
nTransitions++;
- }
- }
- }
final int transitionCount = nTransitions;
final int fieldCount = super.getFieldCount(this.transducerOrdinal);
double sparsity = 100 * (1 - ((double)nTransitions / (double)(nStates * nInputs)));
@@ -569,12 +560,7 @@ void putAutomaton() throws CharacterCodingException {
this.effectorVectorMap.put(new Ints(new int[] { 0 }), 0);
for (final Integer inrInputState : inrInputStates) {
for (final Transition t : this.getTransitions(inrInputState)) {
- if (!t.isFinal) {
- if (t.tape != 0) {
- this.addError(String.format(ModelCompiler.AMBIGUOUS_STATE_MESSAGE,
- this.getTransducerName(), t.from));
- continue;
- }
+ if (t.tape == 0 && !t.isFinal) {
try {
final int rteState = this.inputStateMap.get(t.from);
final int inputOrdinal = super.getInputOrdinal(t.symbol.bytes());
@@ -589,19 +575,18 @@ void putAutomaton() throws CharacterCodingException {
} else if (chain.isParameterizedEffector()) {
transitionMatrix[inputOrdinal][rteState][1] = Transducer.action(-1 * effectVector[0], effectVector[1]);
} else {
- Ints vector = new Ints(effectVector);
- Integer vectorOrdinal = this.effectorVectorMap.get(vector);
- if (vectorOrdinal == null) {
- vectorOrdinal = this.effectorVectorMap.size();
- this.effectorVectorMap.put(vector, vectorOrdinal);
- }
- transitionMatrix[inputOrdinal][rteState][1] = -vectorOrdinal;
+ Integer vectorOrdinal = this.effectorVectorMap.computeIfAbsent(
+ new Ints(effectVector), absent -> this.effectorVectorMap.size());
+ transitionMatrix[inputOrdinal][rteState][1] = -1 * vectorOrdinal;
}
}
} catch (CompilationException e) {
this.addError(String.format("%1$s: %2$s",
this.getTransducerName(), e.getMessage()));
}
+ } else if (t.tape != 0) {
+ this.addError(String.format(ModelCompiler.AMBIGUOUS_STATE_MESSAGE,
+ this.getTransducerName(), t.from));
}
}
}
@@ -985,8 +970,8 @@ private int[][] instrumentSumVectors(int msumOrdinal, int[][] effectVectors, int
|| (effectVectors[-1 * vectorOrdinal][effectVectors[-1 * vectorOrdinal].length - vectorLength] != msumOrdinal)) {
int[] effect = msumEffects[cell[0]];
int[] vector = vectorOrdinal > 0
- ? (vectorOrdinal > 1 ? new int[] { vectorOrdinal, 0 } : new int[] { vectorOrdinal })
- : effectVectors[-1 * vectorOrdinal];
+ ? (vectorOrdinal > 1 ? new int[] { vectorOrdinal, 0 } : new int[] { vectorOrdinal })
+ : effectVectors[-1 * vectorOrdinal];
int[] vectorex = Arrays.copyOf(vector, vector.length + effect.length - 1);
System.arraycopy(effect, 0, vectorex, vector.length - 1, effect.length);
Ints vxkey = new Ints(vectorex);
diff --git a/src/com/characterforming/ribose/IParameterizedEffector.java b/src/com/characterforming/ribose/IParameterizedEffector.java
index 6260c8e..0058262 100644
--- a/src/com/characterforming/ribose/IParameterizedEffector.java
+++ b/src/com/characterforming/ribose/IParameterizedEffector.java
@@ -81,11 +81,12 @@
* P[] precompiled by the respective proxy effector when the model
* is loaded into the runtime. Live effectors are not otherwise involved
* in parameter compilation or decompilation and are never passivated. They
- * select their parameters by array index in their {@link #invoke(int p)}
- * methods, which normally return {@link IEffector#RTX_NONE} to indicate
- * no special condition. They may also return a {@link Signal} encoded by
- * {@link IOutput#signal(int)}. See the javadoc comments for {@link
- * IEffector} for more information regarding effector {@code RTX} codes.
+ * select their parameters by array index by calling {@link #getParameter(int p)}
+ * in their {@link #invoke(int p)} methods, which normally return {@link
+ * IEffector#RTX_NONE} to indicate no special condition. They may also return
+ * a {@link Signal} encoded by {@link IOutput#signal(int)}. See the javadoc
+ * comments for {@link IEffector} for more information regarding effector
+ * {@code RTX} codes.
*
* All {@code IParameterizedEffector} implementations must be subclasses of
* {@link BaseParameterizedEffector}. Other than immutability ribose places
diff --git a/src/com/characterforming/ribose/base/BaseParameterizedEffector.java b/src/com/characterforming/ribose/base/BaseParameterizedEffector.java
index ca0eb5b..dd31240 100644
--- a/src/com/characterforming/ribose/base/BaseParameterizedEffector.java
+++ b/src/com/characterforming/ribose/base/BaseParameterizedEffector.java
@@ -37,11 +37,13 @@
*
the effector parameter type, constructible from IToken[] (eg new P(IToken[]))
@@ -50,7 +52,7 @@
*/
public abstract class BaseParameterizedEffector