|
@@ -1,9 +1,12 @@
|
|
|
package me.hammerle.code;
|
|
|
|
|
|
+import java.io.File;
|
|
|
+import java.io.IOException;
|
|
|
import java.lang.reflect.InvocationTargetException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
+import java.nio.file.Files;
|
|
|
+import java.nio.file.Paths;
|
|
|
import me.hammerle.exceptions.HoldCodeException;
|
|
|
-import java.math.BigDecimal;
|
|
|
-import java.math.RoundingMode;
|
|
|
import java.time.ZonedDateTime;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
@@ -19,9 +22,11 @@ import java.util.Set;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.BiConsumer;
|
|
|
import java.util.function.Consumer;
|
|
|
+import java.util.function.Predicate;
|
|
|
import java.util.stream.Collectors;
|
|
|
+import me.hammerle.exceptions.FileIOException;
|
|
|
import me.hammerle.exceptions.PreScriptException;
|
|
|
-import me.hammerle.exceptions.SnuviException;
|
|
|
+import me.hammerle.math.Fraction;
|
|
|
|
|
|
public class SnuviParser
|
|
|
{
|
|
@@ -105,64 +110,76 @@ public class SnuviParser
|
|
|
// bit
|
|
|
// -------------------------------------------------------------------------------
|
|
|
|
|
|
- registerFunction("bit.rightshift", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) >> getInt(args[1])));
|
|
|
- registerFunction("bit.leftshift", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) << getInt(args[1])));
|
|
|
+ registerFunction("bit.rightshiftn", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).rightShiftNumerator(getInt(args[1])));
|
|
|
+ registerFunction("bit.rightshiftd", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).rightShiftDenominator(getInt(args[1])));
|
|
|
+ registerFunction("bit.leftshiftn", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).leftShiftNumerator(getInt(args[1])));
|
|
|
+ registerFunction("bit.leftshiftd", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).leftShiftDenominator(getInt(args[1])));
|
|
|
registerFunction("bit.and", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) & getInt(args[1])));
|
|
|
+ ((Fraction) args[0]).and((Fraction) args[1]));
|
|
|
registerFunction("bit.or", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) | getInt(args[1])));
|
|
|
+ ((Fraction) args[0]).or((Fraction) args[1]));
|
|
|
registerFunction("bit.xor", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) ^ getInt(args[1])));
|
|
|
+ ((Fraction) args[0]).xor((Fraction) args[1]));
|
|
|
registerFunction("bit.invert", (args, qd) ->
|
|
|
- (double) (~getInt(args[0])));
|
|
|
- registerFunction("bit.set", (args, qd) ->
|
|
|
- (double) (getInt(args[0]) | (getInt(args[2]) << getInt(args[1]))));
|
|
|
- registerFunction("bit.get", (args, qd) ->
|
|
|
- (double) ((getInt(args[0]) & (1 << getInt(args[1])))) != 0);
|
|
|
+ ((Fraction) args[0]).invert());
|
|
|
+ registerFunction("bit.setn", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).setNumeratorBit(getInt(args[1])));
|
|
|
+ registerFunction("bit.setd", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).setDenominatorBit(getInt(args[1])));
|
|
|
+ registerFunction("bit.unsetn", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).unsetNumeratorBit(getInt(args[1])));
|
|
|
+ registerFunction("bit.unsetd", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).unsetDenominatorBit(getInt(args[1])));
|
|
|
+ registerFunction("bit.getn", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).getNumeratorBit(getInt(args[1])));
|
|
|
+ registerFunction("bit.getd", (args, qd) ->
|
|
|
+ ((Fraction) args[0]).getDenominatorBit(getInt(args[1])));
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
|
// math
|
|
|
// -------------------------------------------------------------------------------
|
|
|
registerFunction("math.mod", (args, sc) ->
|
|
|
- ((double) args[0]) % ((double) args[1]));
|
|
|
+ new Fraction(getInt(args[0]) % getInt(args[1])));
|
|
|
registerFunction("math.abs", (args, sc) ->
|
|
|
- Math.abs((double) args[0]));
|
|
|
+ ((Fraction) args[0]).abs());
|
|
|
registerFunction("math.pow", (args, sc) ->
|
|
|
- Math.pow((double) args[0], (double) args[1]));
|
|
|
+ ((Fraction) args[0]).power((Fraction) args[1]));
|
|
|
registerFunction("math.root", (args, sc) ->
|
|
|
- Math.pow((double) args[0], 1d / ((double) args[1])));
|
|
|
+ ((Fraction) args[0]).power(((Fraction) args[1]).invert()));
|
|
|
registerFunction("math.sin", (args, sc) ->
|
|
|
- Math.sin((double) args[0]));
|
|
|
+ ((Fraction) args[0]).sin());
|
|
|
registerFunction("math.cos", (args, sc) ->
|
|
|
- Math.cos((double) args[0]));
|
|
|
+ ((Fraction) args[0]).cos());
|
|
|
registerFunction("math.tan", (args, sc) ->
|
|
|
- Math.tan((double) args[0]));
|
|
|
+ ((Fraction) args[0]).tan());
|
|
|
registerFunction("math.asin", (args, sc) ->
|
|
|
- Math.asin((double) args[0]));
|
|
|
+ ((Fraction) args[0]).asin());
|
|
|
registerFunction("math.acos", (args, sc) ->
|
|
|
- Math.acos((double) args[0]));
|
|
|
+ ((Fraction) args[0]).acos());
|
|
|
registerFunction("math.atan", (args, sc) ->
|
|
|
- Math.atan((double) args[0]));
|
|
|
+ ((Fraction) args[0]).atan());
|
|
|
registerFunction("math.e", (args, sc) ->
|
|
|
- Math.E);
|
|
|
+ Fraction.E);
|
|
|
registerFunction("math.pi", (args, sc) ->
|
|
|
- Math.PI);
|
|
|
+ Fraction.PI);
|
|
|
registerFunction("math.ln", (args, sc) ->
|
|
|
- Math.log((double) args[0]));
|
|
|
+ ((Fraction) args[0]).log());
|
|
|
registerFunction("math.log", (args, sc) ->
|
|
|
- Math.log10((double) args[0]));
|
|
|
+ ((Fraction) args[0]).log());
|
|
|
registerFunction("math.random", (args, sc) ->
|
|
|
- (double) ScriptUtils.randomInt(getInt(args[0]), getInt(args[1])));
|
|
|
+ new Fraction(ScriptUtils.randomInt(getInt(args[0]), getInt(args[1]))));
|
|
|
registerFunction("math.round", (args, sc) ->
|
|
|
- Math.round((double) args[0]));
|
|
|
+ ((Fraction) args[0]).round());
|
|
|
registerFunction("math.rounddown", (args, sc) ->
|
|
|
- Math.floor((double) args[0]));
|
|
|
+ ((Fraction) args[0]).floor());
|
|
|
registerFunction("math.roundup", (args, sc) ->
|
|
|
- Math.ceil((double) args[0]));
|
|
|
+ ((Fraction) args[0]).ceil());
|
|
|
registerFunction("math.roundcomma", (args, sc) ->
|
|
|
- new BigDecimal(((double) args[0])).setScale(getInt(args[1]), RoundingMode.HALF_UP).doubleValue());
|
|
|
+ ((Fraction) args[0]).round(getInt(args[1])));
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
|
// lists
|
|
@@ -180,7 +197,7 @@ public class SnuviParser
|
|
|
registerFunction("list.contains", (args, sc) ->
|
|
|
((List) args[0]).contains(args[1]));
|
|
|
registerFunction("list.getsize", (args, sc) ->
|
|
|
- (double) ((List) args[0]).size());
|
|
|
+ new Fraction(((List) args[0]).size()));
|
|
|
registerFunction("list.getindex", (args, sc) ->
|
|
|
((List) args[0]).get(getInt(args[1])));
|
|
|
registerConsumer("list.setindex", (args, sc) ->
|
|
@@ -188,7 +205,7 @@ public class SnuviParser
|
|
|
registerConsumer("list.clear", (args, sc) ->
|
|
|
((List) args[0]).clear());
|
|
|
registerFunction("list.getindexof", (args, sc) ->
|
|
|
- (double) ((List) args[0]).indexOf(args[1]));
|
|
|
+ new Fraction(((List) args[0]).indexOf(args[1])));
|
|
|
registerConsumer("list.sort", (args, sc) ->
|
|
|
sortList((List<Object>) args[0], sc));
|
|
|
registerConsumer("list.reverse", (args, sc) ->
|
|
@@ -210,7 +227,7 @@ public class SnuviParser
|
|
|
registerFunction("map.contains", (args, sc) ->
|
|
|
((HashMap) args[0]).containsKey(args[1]));
|
|
|
registerFunction("map.getsize", (args, sc) ->
|
|
|
- (double) ((HashMap) args[0]).size());
|
|
|
+ new Fraction(((HashMap) args[0]).size()));
|
|
|
registerFunction("map.get", (args, sc) ->
|
|
|
((HashMap) args[0]).get(args[1]));
|
|
|
registerConsumer("map.clear", (args, sc) ->
|
|
@@ -230,51 +247,111 @@ public class SnuviParser
|
|
|
registerFunction("set.contains", (args, sc) ->
|
|
|
((HashSet) args[0]).contains(args[1]));
|
|
|
registerFunction("set.getsize", (args, sc) ->
|
|
|
- (double) ((HashSet) args[0]).size());
|
|
|
+ new Fraction(((HashSet) args[0]).size()));
|
|
|
+ registerConsumer("set.tolist", (args, sc) ->
|
|
|
+ sc.setVar(args[0].toString(), ((HashSet) args[1]).stream().collect(Collectors.toList())));
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
|
// time
|
|
|
// -------------------------------------------------------------------------------
|
|
|
registerFunction("time.get", (args, sc) ->
|
|
|
- getDouble(System.currentTimeMillis()));
|
|
|
+ new Fraction(System.currentTimeMillis()));
|
|
|
registerFunction("time.nextday", (args, sc) ->
|
|
|
- getDouble(getNextDay(args)));
|
|
|
+ getNextDay(args));
|
|
|
registerFunction("time.getyear", (args, sc) ->
|
|
|
- (double) getYear(args));
|
|
|
+ getYear(args));
|
|
|
registerFunction("time.getmonth", (args, sc) ->
|
|
|
- (double) getMonth(args));
|
|
|
+ getMonth(args));
|
|
|
registerFunction("time.getday", (args, sc) ->
|
|
|
- (double) getDay(args));
|
|
|
+ getDay(args));
|
|
|
registerFunction("time.gethour", (args, sc) ->
|
|
|
- (double) getHour(args));
|
|
|
+ getHour(args));
|
|
|
registerFunction("time.getminute", (args, sc) ->
|
|
|
- (double) getMinute(args));
|
|
|
+ getMinute(args));
|
|
|
registerFunction("time.getsecond", (args, sc) ->
|
|
|
- (double) getSecond(args));
|
|
|
+ getSecond(args));
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
|
// text
|
|
|
// -------------------------------------------------------------------------------
|
|
|
registerFunction("text.number", (args, sc) ->
|
|
|
- doubleToString(getDouble(args[0])));
|
|
|
+ fractionToDoubleString((Fraction) args[0]));
|
|
|
registerFunction("text.class", (args, sc) ->
|
|
|
args[0].getClass().getSimpleName());
|
|
|
+ registerFunction("text.tolowercase", (args, sc) ->
|
|
|
+ ScriptUtils.connect(args, 0).toLowerCase());
|
|
|
+ registerAlias("tolowercase", "text.tolowercase");
|
|
|
+ registerFunction("text.touppercase", (args, sc) ->
|
|
|
+ ScriptUtils.connect(args, 0).toUpperCase());
|
|
|
+ registerAlias("touppercase", "text.touppercase");
|
|
|
+ registerConsumer("text.split", (args, sc) ->
|
|
|
+ split(args, sc));
|
|
|
+ registerAlias("split", "text.split");
|
|
|
+ registerFunction("text.concatlist", (args, sc) ->
|
|
|
+ ((List<Object>) args[0]).stream().limit(getInt(args[3]) + 1).skip(getInt(args[2])).map(o -> o.toString()).collect(Collectors.joining(args[1].toString())));
|
|
|
+ registerAlias("concatlist", "text.concatlist");
|
|
|
+ registerFunction("text.concat", (args, sc) ->
|
|
|
+ ScriptUtils.connect(args, 0));
|
|
|
+ registerAlias("concat", "text.concat");
|
|
|
+ registerFunction("text", (args, sc) ->
|
|
|
+ String.valueOf(args[0]));
|
|
|
+ registerFunction("text.substring", (args, sc) ->
|
|
|
+ args[0].toString().substring(getInt(args[1]), getInt(args[2])));
|
|
|
+ registerFunction("text.length", (args, sc) ->
|
|
|
+ args[0].toString().length());
|
|
|
+ registerFunction("text.startswith", (args, sc) ->
|
|
|
+ args[0].toString().startsWith(args[1].toString(), getInt(args[2])));
|
|
|
+ registerFunction("text.endswith", (args, sc) ->
|
|
|
+ args[0].toString().endsWith(args[1].toString()));
|
|
|
+ registerFunction("text.contains", (args, sc) ->
|
|
|
+ args[0].toString().contains(args[1].toString()));
|
|
|
+ registerFunction("text.indexof", (args, sc) ->
|
|
|
+ args[0].toString().indexOf(args[1].toString(), getInt(args[2])));
|
|
|
+ registerFunction("text.lastindexof", (args, sc) ->
|
|
|
+ args[0].toString().lastIndexOf(args[1].toString(), getInt(args[2])));
|
|
|
+ registerFunction("text.replace", (args, sc) ->
|
|
|
+ args[0].toString().replace(args[1].toString(), args[2].toString()));
|
|
|
+ registerFunction("text.trim", (args, sc) ->
|
|
|
+ args[0].toString().trim());
|
|
|
+ registerFunction("text.charat", (args, sc) ->
|
|
|
+ String.valueOf(args[0].toString().charAt(getInt(args[1]))));
|
|
|
+
|
|
|
+ // -------------------------------------------------------------------------------
|
|
|
+ // files
|
|
|
+ // -------------------------------------------------------------------------------
|
|
|
+
|
|
|
+ registerFunction("file.new", (args, sc) ->
|
|
|
+ new File(args[0].toString()));
|
|
|
+ registerFunction("file.exists", (args, sc) ->
|
|
|
+ ((File) args[0]).exists());
|
|
|
+ registerFunction("file.delete", (args, sc) ->
|
|
|
+ ((File) args[0]).delete());
|
|
|
+ registerFunction("file.getname", (args, sc) ->
|
|
|
+ ((File) args[0]).getName());
|
|
|
+ registerFunction("file.", (args, sc) ->
|
|
|
+ ((File) args[0]).renameTo(new File(args[1].toString())));
|
|
|
+ registerConsumer("file.getlist", (args, sc) ->
|
|
|
+ sc.setVar(args[0].toString(), Arrays.asList(((File) args[0]).listFiles())));
|
|
|
+ registerConsumer("file.read", (args, sc) ->
|
|
|
+ readFile(args, sc));
|
|
|
+ registerConsumer("file.write", (args, sc) ->
|
|
|
+ writeFile(args, sc));
|
|
|
|
|
|
// -------------------------------------------------------------------------------
|
|
|
// commands without library
|
|
|
// -------------------------------------------------------------------------------
|
|
|
registerFunction("add", (args, sc) ->
|
|
|
- Arrays.stream(args).mapToDouble(s -> (double) s).sum());
|
|
|
+ ((Fraction) args[0]).add((Fraction) args[1]));
|
|
|
registerFunction("sub", (args, sc) ->
|
|
|
- ((double) args[0]) - ((double) args[1]));
|
|
|
+ ((Fraction) args[0]).sub((Fraction) args[1]));
|
|
|
registerFunction("inc", (args, sc) ->
|
|
|
increaseVar(args[0], sc, 1));
|
|
|
registerFunction("dec", (args, sc) ->
|
|
|
increaseVar(args[0], sc, -1));
|
|
|
registerFunction("mul", (args, sc) ->
|
|
|
- ((double) args[0]) * ((double) args[1]));
|
|
|
+ ((Fraction) args[0]).mul((Fraction) args[1]));
|
|
|
registerFunction("div", (args, sc) ->
|
|
|
- ((double) args[0]) / ((double) args[1]));
|
|
|
+ ((Fraction) args[0]).div((Fraction) args[1]));
|
|
|
registerFunction("getvar", (args, sc) ->
|
|
|
sc.getVar(args[0].toString()));
|
|
|
registerConsumer("setvar", (args, sc) ->
|
|
@@ -286,9 +363,7 @@ public class SnuviParser
|
|
|
registerConsumer("wait", (args, sc) ->
|
|
|
{ sc.resetLoopCounter(); throw new HoldCodeException(); });
|
|
|
registerConsumer("goto", (args, sc) ->
|
|
|
- sc.gotoLabel(args[0].toString(), false));
|
|
|
- registerConsumer("gotoline", (args, sc) ->
|
|
|
- { sc.gotoSpecialJumpLine(); sc.incLoopCounter(); });
|
|
|
+ goTo(args, sc));
|
|
|
registerConsumer("sgoto", (args, sc) ->
|
|
|
scheduleGoto(args, sc));
|
|
|
registerConsumer("gosub", (args, sc) ->
|
|
@@ -296,44 +371,34 @@ public class SnuviParser
|
|
|
registerConsumer("return", (args, sc) ->
|
|
|
sc.doReturn());
|
|
|
registerConsumer("try", (args, sc) ->
|
|
|
- sc.saveTryJumpLine());
|
|
|
+ {sc.saveTryJumpLine(); sc.jump(1);});
|
|
|
registerConsumer("catch", (args, sc) ->
|
|
|
- {sc.gotoSpecialJumpLine(); sc.resetTryJumpLine();});
|
|
|
+ sc.resetTryJumpLine());
|
|
|
registerConsumer("if", (args, sc) ->
|
|
|
ifFunction(args, sc));
|
|
|
registerConsumer("else", (args, sc) ->
|
|
|
- sc.gotoSpecialJumpLine());
|
|
|
+ {});
|
|
|
registerConsumer("while", (args, sc) ->
|
|
|
whileFunction(args, sc));
|
|
|
registerFunction("equal", (args, sc) ->
|
|
|
isEqual(args));
|
|
|
registerAlias("equals", "equal");
|
|
|
registerFunction("less", (args, sc) ->
|
|
|
- (double) args[0] < (double) args[1]);
|
|
|
+ ((Fraction) args[0]).compareTo((Fraction) args[1]) < 0);
|
|
|
registerFunction("greater", (args, sc) ->
|
|
|
- (double) args[0] > (double) args[1]);
|
|
|
+ ((Fraction) args[0]).compareTo((Fraction) args[1]) > 0);
|
|
|
registerFunction("notequal", (args, sc) ->
|
|
|
!isEqual(args));
|
|
|
registerFunction("lessequal", (args, sc) ->
|
|
|
- (double) args[0] <= (double) args[1]);
|
|
|
+ ((Fraction) args[0]).compareTo((Fraction) args[1]) <= 0);
|
|
|
registerFunction("greaterequal", (args, sc) ->
|
|
|
- (double) args[0] >= (double) args[1]);
|
|
|
+ ((Fraction) args[0]).compareTo((Fraction) args[1]) >= 0);
|
|
|
registerFunction("invert", (args, sc) ->
|
|
|
!((boolean) args[0]));
|
|
|
registerFunction("and", (args, sc) ->
|
|
|
Arrays.stream(args).allMatch(s -> s.equals(true)));
|
|
|
registerFunction("or", (args, sc) ->
|
|
|
Arrays.stream(args).anyMatch(s -> s.equals(true)));
|
|
|
- registerFunction("concatlist", (args, sc) ->
|
|
|
- ((List<Object>) args[0]).stream().limit(getInt(args[3]) + 1).skip(getInt(args[2])).map(o -> o.toString()).collect(Collectors.joining(args[1].toString())));
|
|
|
- registerConsumer("split", (args, sc) ->
|
|
|
- split(args, sc));
|
|
|
- registerFunction("concat", (args, sc) ->
|
|
|
- ScriptUtils.connect(args, 0));
|
|
|
- registerFunction("tolowercase", (args, sc) ->
|
|
|
- ScriptUtils.connect(args, 0).toLowerCase());
|
|
|
- registerFunction("touppercase", (args, sc) ->
|
|
|
- ScriptUtils.connect(args, 0).toUpperCase());
|
|
|
registerConsumer("waitfor", (args, sc) ->
|
|
|
waitFor(args, sc));
|
|
|
registerConsumer("term", (args, sc) ->
|
|
@@ -364,14 +429,7 @@ public class SnuviParser
|
|
|
sc.resetTryJumpLine();
|
|
|
return Void.TYPE;
|
|
|
}
|
|
|
- if(ex instanceof SnuviException)
|
|
|
- {
|
|
|
- logger.printException((SnuviException) ex, sc);
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- logger.printException(new SnuviException(ex, sc), sc);
|
|
|
- }
|
|
|
+ logger.printException(ex, sc, sc.getActiveRealCodeLine());
|
|
|
sc.resetLoopCounter();
|
|
|
throw new HoldCodeException();
|
|
|
}
|
|
@@ -451,7 +509,7 @@ public class SnuviParser
|
|
|
}
|
|
|
catch(PreScriptException ex)
|
|
|
{
|
|
|
- logger.printException(ex, script);
|
|
|
+ logger.printException(ex, script, ex.getLine());
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
@@ -475,9 +533,9 @@ public class SnuviParser
|
|
|
if(ex instanceof InvocationTargetException)
|
|
|
{
|
|
|
Throwable t = ((InvocationTargetException) ex).getCause();
|
|
|
- if(t != null && t instanceof SnuviException)
|
|
|
+ if(t != null && t instanceof Exception)
|
|
|
{
|
|
|
- logger.printException((SnuviException) t);
|
|
|
+ logger.printException((Exception) t);
|
|
|
return null;
|
|
|
}
|
|
|
}
|
|
@@ -490,11 +548,12 @@ public class SnuviParser
|
|
|
// event
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
|
- public void callEvent(String name, Consumer<Script> before, Consumer<Script> after)
|
|
|
+ public void callEvent(String name, Consumer<Script> before, Consumer<Script> after, Predicate<Script> check)
|
|
|
{
|
|
|
scripts.values().stream()
|
|
|
- .filter(script -> script.receiveEventBroadcast)
|
|
|
- .filter(script -> script.isLoadedEvent(name))
|
|
|
+ .filter(sc -> sc.receiveEventBroadcast && !sc.isHalt() && !sc.isRunning())
|
|
|
+ .filter(sc -> sc.isLoadedEvent(name))
|
|
|
+ .filter(check)
|
|
|
.forEach(sc ->
|
|
|
{
|
|
|
sc.setVar("event", name);
|
|
@@ -513,9 +572,14 @@ public class SnuviParser
|
|
|
term();
|
|
|
}
|
|
|
|
|
|
- public boolean callEvent(String name, Script sc, Consumer<Script> before, Consumer<Script> after)
|
|
|
+ public void callEvent(String name, Consumer<Script> before, Consumer<Script> after)
|
|
|
+ {
|
|
|
+ callEvent(name, before, after, sc -> true);
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean callEvent(String name, Script sc, Consumer<Script> before, Consumer<Script> after, boolean check)
|
|
|
{
|
|
|
- if(sc.isLoadedEvent(name))
|
|
|
+ if(sc.isLoadedEvent(name) && !sc.isHalt() && !sc.isRunning() && check)
|
|
|
{
|
|
|
sc.setVar("event", name);
|
|
|
if(before != null)
|
|
@@ -535,33 +599,41 @@ public class SnuviParser
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+ public boolean callEvent(String name, Script sc, Consumer<Script> before, Consumer<Script> after)
|
|
|
+ {
|
|
|
+ return callEvent(name, sc, before, after, true);
|
|
|
+ }
|
|
|
+
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
// functions
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
|
- private String doubleToString(Double d)
|
|
|
+ private String fractionToDoubleString(Fraction f)
|
|
|
{
|
|
|
- if(d.doubleValue() == d.longValue())
|
|
|
+ if(f.doubleValue() == f.longValue())
|
|
|
{
|
|
|
- return String.valueOf(d.longValue());
|
|
|
+ return String.valueOf(f.longValue());
|
|
|
}
|
|
|
- return d.toString();
|
|
|
+ return String.valueOf(f.doubleValue());
|
|
|
}
|
|
|
|
|
|
private void ifFunction(Object[] args, Script sc)
|
|
|
{
|
|
|
if(Arrays.stream(args).anyMatch(s -> !((boolean) s)))
|
|
|
{
|
|
|
- sc.gotoSpecialJumpLine();
|
|
|
- sc.jumpNextIfElse();
|
|
|
+ sc.jumpNextDoElse();
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ sc.jump(1);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
private void whileFunction(Object[] args, Script sc)
|
|
|
{
|
|
|
- if(Arrays.stream(args).anyMatch(s -> !((boolean) s)))
|
|
|
+ if(Arrays.stream(args).allMatch(s -> ((boolean) s)))
|
|
|
{
|
|
|
- sc.gotoSpecialJumpLine();
|
|
|
+ sc.jump(1);
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -575,19 +647,18 @@ public class SnuviParser
|
|
|
{
|
|
|
scheduler.scheduleTask(() ->
|
|
|
{
|
|
|
- if(!sc.isValid())
|
|
|
+ if(!sc.isValid() && !sc.isHalt())
|
|
|
{
|
|
|
return;
|
|
|
}
|
|
|
try
|
|
|
{
|
|
|
sc.gotoLabel(args[1].toString(), true);
|
|
|
- sc.setHalt(false);
|
|
|
sc.runCode();
|
|
|
}
|
|
|
catch(Exception ex)
|
|
|
{
|
|
|
- logger.printException(new SnuviException(ex, sc.getName(), "scheduled goto"), sc);
|
|
|
+ logger.printException(ex, sc, sc.getActiveRealCodeLine());
|
|
|
}
|
|
|
}, getInt(args[0]));
|
|
|
}
|
|
@@ -611,11 +682,12 @@ public class SnuviParser
|
|
|
sc.setHalt(false);
|
|
|
sc.runCode();
|
|
|
}, l);
|
|
|
+ throw new HoldCodeException();
|
|
|
}
|
|
|
|
|
|
private Number increaseVar(Object var, Script sc, int value)
|
|
|
{
|
|
|
- double n = ((double) sc.getVar(var.toString())) + value;
|
|
|
+ Fraction n = ((Fraction) sc.getVar(var.toString())).add(new Fraction(value));
|
|
|
sc.setVar(var.toString(), n);
|
|
|
return n;
|
|
|
}
|
|
@@ -630,12 +702,6 @@ public class SnuviParser
|
|
|
{
|
|
|
return false;
|
|
|
}
|
|
|
- // this is needed for comparing different number types (e.g. Integer and Double)
|
|
|
- // allthough there should be no numbers except doubles...
|
|
|
- else if(args[1] instanceof Number && args[0] instanceof Number)
|
|
|
- {
|
|
|
- return ((Number) args[0]).doubleValue() == ((Number) args[1]).doubleValue();
|
|
|
- }
|
|
|
return args[0].equals(args[1]);
|
|
|
}
|
|
|
|
|
@@ -643,33 +709,83 @@ public class SnuviParser
|
|
|
{
|
|
|
sc.setVar(args[0].toString(),
|
|
|
Arrays.stream(ScriptUtils.connect(args, 2).split(args[1].toString()))
|
|
|
- .map(s -> Code.convertInput(s, false)).collect(Collectors.toList()));
|
|
|
+ .map(s -> Code.convertInput(null, s, false)).collect(Collectors.toList()));
|
|
|
+ }
|
|
|
+
|
|
|
+ private void goTo(Object[] args, Script sc)
|
|
|
+ {
|
|
|
+ if(args.length == 0)
|
|
|
+ {
|
|
|
+ sc.gotoLabel(null, false);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ sc.gotoLabel(args[0].toString(), false);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void readFile(Object[] args, Script sc)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ sc.setVar(args[0].toString(), Files.readAllLines(((File) args[1]).toPath()));
|
|
|
+ }
|
|
|
+ catch(IOException ex)
|
|
|
+ {
|
|
|
+ throw new FileIOException(ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeFile(Object[] args, Script sc)
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ File f = (File) args[0];
|
|
|
+ if(!f.getParentFile().exists())
|
|
|
+ {
|
|
|
+ f.getParentFile().mkdirs();
|
|
|
+ }
|
|
|
+ if(!f.exists())
|
|
|
+ {
|
|
|
+ try
|
|
|
+ {
|
|
|
+ f.createNewFile();
|
|
|
+ }
|
|
|
+ catch(IOException ex)
|
|
|
+ {
|
|
|
+ throw new FileIOException(ex.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Files.write(Paths.get(f.toURI()), (List<String>) args[1], StandardCharsets.UTF_8);
|
|
|
+ }
|
|
|
+ catch(UnsupportedOperationException | SecurityException | IOException ex)
|
|
|
+ {
|
|
|
+ throw new FileIOException(ex.getMessage());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
// number handlers, cause primitive types transform into their classes all the time
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
|
- private int getInt(Object o)
|
|
|
+ public static int getInt(Object o)
|
|
|
{
|
|
|
- return ((Number) o).intValue();
|
|
|
+ return ScriptUtils.getInt(o);
|
|
|
}
|
|
|
|
|
|
- private long getLong(Object o)
|
|
|
+ public static long getLong(Object o)
|
|
|
{
|
|
|
- return ((Number) o).longValue();
|
|
|
+ return ScriptUtils.getLong(o);
|
|
|
}
|
|
|
|
|
|
- private double getDouble(Object o)
|
|
|
+ public static double getDouble(Object o)
|
|
|
{
|
|
|
- return ((Number) o).doubleValue();
|
|
|
+ return ScriptUtils.getDouble(o);
|
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
// time handler
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
|
|
- private long getNextDay(Object[] args)
|
|
|
+ private Fraction getNextDay(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
@@ -678,48 +794,48 @@ public class SnuviParser
|
|
|
cal.set(Calendar.SECOND, 0);
|
|
|
cal.set(Calendar.MINUTE, 0);
|
|
|
cal.set(Calendar.MILLISECOND, 0);
|
|
|
- return cal.getTimeInMillis();
|
|
|
+ return new Fraction(cal.getTimeInMillis());
|
|
|
}
|
|
|
|
|
|
- private int getYear(Object[] args)
|
|
|
+ private Fraction getYear(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.YEAR);
|
|
|
+ return new Fraction(cal.get(Calendar.YEAR));
|
|
|
}
|
|
|
|
|
|
- private int getMonth(Object[] args)
|
|
|
+ private Fraction getMonth(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.MONTH) + 1;
|
|
|
+ return new Fraction(cal.get(Calendar.MONTH) + 1);
|
|
|
}
|
|
|
|
|
|
- private int getDay(Object[] args)
|
|
|
+ private Fraction getDay(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.DAY_OF_MONTH);
|
|
|
+ return new Fraction(cal.get(Calendar.DAY_OF_MONTH));
|
|
|
}
|
|
|
|
|
|
- private int getHour(Object[] args)
|
|
|
+ private Fraction getHour(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.HOUR_OF_DAY);
|
|
|
+ return new Fraction(cal.get(Calendar.HOUR_OF_DAY));
|
|
|
}
|
|
|
|
|
|
- private int getMinute(Object[] args)
|
|
|
+ private Fraction getMinute(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.MINUTE);
|
|
|
+ return new Fraction(cal.get(Calendar.MINUTE));
|
|
|
}
|
|
|
|
|
|
- private int getSecond(Object[] args)
|
|
|
+ private Fraction getSecond(Object[] args)
|
|
|
{
|
|
|
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
|
|
|
cal.setTimeInMillis(getLong(args[0]));
|
|
|
- return cal.get(Calendar.SECOND);
|
|
|
+ return new Fraction(cal.get(Calendar.SECOND));
|
|
|
}
|
|
|
}
|