diff --git a/midica.jar b/midica.jar
index 4bf9537..46e32f1 100644
Binary files a/midica.jar and b/midica.jar differ
diff --git a/src/org/midica/Midica.java b/src/org/midica/Midica.java
index a28bf45..9960b78 100644
--- a/src/org/midica/Midica.java
+++ b/src/org/midica/Midica.java
@@ -36,7 +36,7 @@ public class Midica {
private static final int VERSION_MINOR = 11;
/** UNIX timestamp of the last commit */
- public static final int COMMIT_TIME = 1708970595;
+ public static final int COMMIT_TIME = 1709317508;
/** Branch name. Automatically changed by precommit.pl */
public static final String BRANCH = "sound-effects";
diff --git a/src/org/midica/config/Dict.java b/src/org/midica/config/Dict.java
index 89074ac..2994a12 100644
--- a/src/org/midica/config/Dict.java
+++ b/src/org/midica/config/Dict.java
@@ -1761,6 +1761,7 @@ public class Dict {
public static final String ERROR_FL_NOTE_NOT_SET = "error_fl_note_not_set";
public static final String ERROR_FL_NOTE_PAT_IDX_NAN = "error_fl_note_pat_idx_nan";
public static final String ERROR_FL_NOTE_PAT_IDX_TOO_HIGH = "error_fl_note_pat_idx_too_high";
+ public static final String ERROR_FL_PENDING = "error_fl_pending";
public static final String ERROR_FUNC_NOT_SUPPORTED_BY_EFF = "error_func_not_supported_by_eff";
public static final String ERROR_FUNC_VAL_LOWER_MIN = "error_func_val_lower_min";
public static final String ERROR_FUNC_VAL_GREATER_MAX = "error_func_val_greater_max";
@@ -3587,6 +3588,7 @@ private static void initLanguageEnglish() {
set( ERROR_FL_NOTE_NOT_SET, "The chosen effect needs a note to be set before you can use this function: " );
set( ERROR_FL_NOTE_PAT_IDX_NAN, "pattern index '%s' is not a number in this element: %s" );
set( ERROR_FL_NOTE_PAT_IDX_TOO_HIGH, "pattern index '%s' too high in this element: %s" );
+ set( ERROR_FL_PENDING, "Pending effect flow found before this line.
Delete the useless parts of the flow." );
set( ERROR_FUNC_NOT_SUPPORTED_BY_EFF, "The chosen effect does not support this function: " );
set( ERROR_FUNC_VAL_LOWER_MIN, "Parameter '%s' is smaller than the minimum value (%s)" );
set( ERROR_FUNC_VAL_GREATER_MAX, "Parameter '%s' is greater than the maximum value (%s)" );
diff --git a/src/org/midica/file/read/Effect.java b/src/org/midica/file/read/Effect.java
index 750ccb3..6277789 100644
--- a/src/org/midica/file/read/Effect.java
+++ b/src/org/midica/file/read/Effect.java
@@ -67,6 +67,7 @@ public class Effect {
*/
public static void init(MidicaPLParser rootParser) {
parser = rootParser;
+ flow = null;
// create and initialize special structures
{
@@ -434,8 +435,29 @@ else if (numberStr != null) {
/**
* Closes the current flow, if there is an open flow.
+ *
+ * @throws ParseException if the current flow is pending.
+ */
+ public static void closeFlowIfPossible() throws ParseException {
+
+ // check if there is a pending flow
+ if (flow != null && flow.isPending()) {
+ throw new ParseException(Dict.get(Dict.ERROR_FL_PENDING));
+ }
+
+ flow = null;
+ }
+
+ /**
+ * Closes the current flow, if there is an open flow.
+ *
+ * Does **not** check if the flow is pending or not.
+ *
+ * Called after all parsing runs are finished, no matter if an exception is thrown or not.
+ *
+ * Does **not** throw a further exception.
*/
- public static void closeFlowIfPossible() {
+ public static void closeFlowAfterParsingFinished() {
flow = null;
}
@@ -546,6 +568,8 @@ private static int parseGenericNumber(String numberStr, String numberLsb, int ma
*/
private static void applyFlowElement(String elemName, int number, String paramStr) throws ParseException {
+ flow.setPending(true);
+
// check presence of params
if (functionNames.contains(elemName)) {
if (paramStr == null && ! MidicaPLParser.FUNC_WAIT.equals(elemName))
@@ -707,6 +731,7 @@ private static void applyFunction(String funcName, String[] params) throws Parse
// for all other functions we need the effect type
int valueType = flow.getValueType(funcName);
+ flow.setPending(false);
// note required but not set?
if (flow.needsNote() && flow.getNote() < 0)
diff --git a/src/org/midica/file/read/EffectFlow.java b/src/org/midica/file/read/EffectFlow.java
index a948120..5b9779f 100644
--- a/src/org/midica/file/read/EffectFlow.java
+++ b/src/org/midica/file/read/EffectFlow.java
@@ -91,6 +91,7 @@ public class EffectFlow {
private long ticksPerAction;
private int effectType = 0;
private int effectNumber = -1;
+ private boolean isPending = true;
private boolean isDouble = false;
private int note = -1;
@@ -157,6 +158,32 @@ public int getEffectNumber() {
return effectNumber;
}
+ /**
+ * Marks the flow as pending or not pending.
+ *
+ * "Pending" means that the last called function was something like length(), wait(), note(), src(), dest() etc.
+ *
+ * "Not pending" means that the last called function was something like set(), on(), off(), line(), sin(), etc.
+ *
+ * @param isPending **true** for pending, **false** for not pending
+ */
+ public void setPending(boolean isPending) {
+ this.isPending = isPending;
+ }
+
+ /**
+ * Indicates if the flow is pending.
+ *
+ * "Pending" means that the last called function was something like length(), wait(), note(), src(), dest() etc.
+ *
+ * "Not pending" means that the last called function was something like set(), on(), off(), line(), sin(), etc.
+ *
+ * @return **true** if the flow is pending, otherwise: **false**.
+ */
+ public boolean isPending() {
+ return isPending;
+ }
+
/**
* Return all functions that are supported by the current effect type.
*
diff --git a/src/org/midica/file/read/MidicaPLParser.java b/src/org/midica/file/read/MidicaPLParser.java
index 57e2e96..be68eaf 100644
--- a/src/org/midica/file/read/MidicaPLParser.java
+++ b/src/org/midica/file/read/MidicaPLParser.java
@@ -717,6 +717,12 @@ public void parse(Object fileAsObj) throws ParseException {
e.printStackTrace();
throw new ParseException(e.toString());
}
+ finally {
+ // Close the flow.
+ // Avoids problems in the NEXT parsing attempt.
+ if (isRootParser)
+ Effect.closeFlowAfterParsingFinished();
+ }
// allow an empty sequence?
if (isRootParser) {
@@ -1017,6 +1023,9 @@ private void parsingRun(ArrayList lines) throws ParseException, IOExcept
// In case of wrong block nesting make sure that the correct
// error message and line number is shown
nestableBlkDepth = 0;
+
+ // check if a pending flow was the last command
+ Effect.closeFlowIfPossible();
}
catch (ParseException e) {
// Add file name and line number to exception and throw it again
diff --git a/test/org/midica/file/read/MidicaPLParserTest.java b/test/org/midica/file/read/MidicaPLParserTest.java
index 497162b..f2683e1 100644
--- a/test/org/midica/file/read/MidicaPLParserTest.java
+++ b/test/org/midica/file/read/MidicaPLParserTest.java
@@ -4116,32 +4116,32 @@ void testParseFilesFailing() {
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-var")) );
assertEquals( 6, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-const")) );
assertEquals( 6, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-call")) );
assertEquals( 6, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-function")) );
assertEquals( 7, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-note")) );
assertEquals( 6, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-broken-by-other-channel")) );
assertEquals( 6, e.getLineNumber() );
- assertEquals( "0: .set(50)", e.getLineContent() );
+ assertEquals( "0: .wait.set(50)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(String.format(Dict.get(Dict.ERROR_FL_NOT_OPEN), ".")));
e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-missing-dot-1")) );
@@ -4658,6 +4658,26 @@ void testParseFilesFailing() {
assertEquals( 4, e.getLineNumber() );
assertEquals( "0: mono_mode.set(+5)", e.getLineContent() );
assertTrue( e.getMessage().startsWith(Dict.get(Dict.ERROR_FUNC_SIGNED_FORBIDDEN) + "+5"));
+
+ e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-pending-1")) );
+ assertEquals( 5, e.getLineNumber() );
+ assertEquals( "1: c", e.getLineContent() );
+ assertTrue( e.getMessage().startsWith(Dict.get(Dict.ERROR_FL_PENDING)));
+
+ e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-pending-2")) );
+ assertEquals( 5, e.getLineNumber() );
+ assertEquals( "0: hold.wait", e.getLineContent() );
+ assertTrue( e.getMessage().startsWith(Dict.get(Dict.ERROR_FL_PENDING)));
+
+ e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-pending-3")) );
+ assertEquals( 6, e.getLineNumber() );
+ assertEquals( "", e.getLineContent() );
+ assertTrue( e.getMessage().startsWith(Dict.get(Dict.ERROR_FL_PENDING)));
+
+ e = assertThrows( ParseException.class, () -> parse(getFailingFile("eff-flow-pending-4")) );
+ assertEquals( 23, e.getLineNumber() );
+ assertEquals( "0: c", e.getLineContent() );
+ assertTrue( e.getMessage().startsWith(Dict.get(Dict.ERROR_FL_PENDING)));
}
/**
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-call.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-call.midica
index b072989..e179352 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-call.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-call.midica
@@ -1,9 +1,9 @@
INCLUDE inc/instruments.midica
-0: vol.wait()
+0: vol.wait().set(50)
CALL func
-0: .set(50)
+0: .wait.set(50)
FUNCTION func
END
\ No newline at end of file
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-const.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-const.midica
index 8454964..10c7023 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-const.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-const.midica
@@ -1,7 +1,7 @@
INCLUDE inc/instruments.midica
-0: vol.wait()
+0: vol.wait().set(50)
CONST $x = y
-0: .set(50)
+0: .wait.set(50)
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-function.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-function.midica
index 189b692..cf3094d 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-function.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-function.midica
@@ -1,9 +1,9 @@
INCLUDE inc/instruments.midica
-0: vol.wait()
+0: vol.wait().set(50)
FUNCTION func
END
-0: .set(50)
+0: .wait.set(50)
CALL func
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-note.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-note.midica
index 98b53db..3c9549c 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-note.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-note.midica
@@ -1,7 +1,7 @@
INCLUDE inc/instruments.midica
-0: vol.wait()
+0: vol.wait().set(50)
0: c
-0: .set(50)
+0: .wait.set(50)
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-other-channel.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-other-channel.midica
index 9fab4ae..27f4223 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-other-channel.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-other-channel.midica
@@ -1,7 +1,7 @@
INCLUDE inc/instruments.midica
-0: vol.wait()
-1: balance.wait()
-0: .set(50)
+0: vol.wait().set(50)
+1: balance.wait().set(+50)
+0: .wait.set(50)
diff --git a/test/org/midica/testfiles/failing/eff-flow-broken-by-var.midica b/test/org/midica/testfiles/failing/eff-flow-broken-by-var.midica
index b65d12a..b373c90 100644
--- a/test/org/midica/testfiles/failing/eff-flow-broken-by-var.midica
+++ b/test/org/midica/testfiles/failing/eff-flow-broken-by-var.midica
@@ -1,7 +1,7 @@
INCLUDE inc/instruments.midica
-0: vol.double
+0: vol.double.set(50)
VAR $x = y
-0: .set(50)
+0: .wait.set(50)
diff --git a/test/org/midica/testfiles/failing/eff-flow-pending-1.midica b/test/org/midica/testfiles/failing/eff-flow-pending-1.midica
new file mode 100644
index 0000000..44f8906
--- /dev/null
+++ b/test/org/midica/testfiles/failing/eff-flow-pending-1.midica
@@ -0,0 +1,5 @@
+INCLUDE inc/instruments.midica
+
+
+0: vol.wait
+1: c
diff --git a/test/org/midica/testfiles/failing/eff-flow-pending-2.midica b/test/org/midica/testfiles/failing/eff-flow-pending-2.midica
new file mode 100644
index 0000000..a2b3981
--- /dev/null
+++ b/test/org/midica/testfiles/failing/eff-flow-pending-2.midica
@@ -0,0 +1,4 @@
+INCLUDE inc/instruments.midica
+
+
+0: hold.wait
\ No newline at end of file
diff --git a/test/org/midica/testfiles/failing/eff-flow-pending-3.midica b/test/org/midica/testfiles/failing/eff-flow-pending-3.midica
new file mode 100644
index 0000000..f9af5d0
--- /dev/null
+++ b/test/org/midica/testfiles/failing/eff-flow-pending-3.midica
@@ -0,0 +1,5 @@
+INCLUDE inc/instruments.midica
+
+
+0: hold.wait
+
diff --git a/test/org/midica/testfiles/failing/eff-flow-pending-4.midica b/test/org/midica/testfiles/failing/eff-flow-pending-4.midica
new file mode 100644
index 0000000..d6f45ad
--- /dev/null
+++ b/test/org/midica/testfiles/failing/eff-flow-pending-4.midica
@@ -0,0 +1,24 @@
+INCLUDE inc/instruments.midica
+
+
+
+FUNCTION func
+ {
+ {
+ 0: hold.wait
+
+ 0: c
+
+ }
+ }
+END
+
+{
+ {
+
+ CALL func
+ 0: a
+
+ }
+}
+