FunctionRegistry.java 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. package me.hammerle.snuviscript.code;
  2. import me.hammerle.snuviscript.inputprovider.InputProvider;
  3. import java.io.File;
  4. import java.nio.charset.StandardCharsets;
  5. import java.lang.reflect.Array;
  6. import java.nio.file.Files;
  7. import java.nio.file.Paths;
  8. import java.time.ZonedDateTime;
  9. import java.util.List;
  10. import java.util.ArrayList;
  11. import java.util.Arrays;
  12. import java.util.Collection;
  13. import java.util.Collections;
  14. import java.util.Calendar;
  15. import java.util.GregorianCalendar;
  16. import java.util.HashMap;
  17. import java.util.Map;
  18. import java.util.HashSet;
  19. import java.util.Iterator;
  20. import java.util.Objects;
  21. import java.util.Set;
  22. import java.util.stream.Collectors;
  23. import me.hammerle.snuviscript.config.SnuviConfig;
  24. import me.hammerle.snuviscript.inputprovider.Variable;
  25. public class FunctionRegistry {
  26. private static final HashMap<String, Object> GLOBAL_VARS = new HashMap<>();
  27. private static final HashMap<String, NamedFunction> FUNCTIONS = new HashMap<>();
  28. protected static void registerFunction(String name,
  29. ExceptionBiFunction<Script, InputProvider[], Object> f) {
  30. FUNCTIONS.put(name, new NamedFunction(name, f));
  31. }
  32. protected static void registerConsumer(String name,
  33. ExceptionBiConsumer<Script, InputProvider[]> f) {
  34. FUNCTIONS.put(name, new NamedFunction(name, (sc, in) -> {
  35. f.apply(sc, in);
  36. return Void.TYPE;
  37. }));
  38. }
  39. protected static void registerAlias(String original, String alias) {
  40. FUNCTIONS.put(alias, FUNCTIONS.get(original));
  41. }
  42. public static NamedFunction getFunction(String f) {
  43. final String function = f.toLowerCase();
  44. return FUNCTIONS.getOrDefault(function, new NamedFunction(function, (sc, in) -> {
  45. sc.handleFunction(function, in);
  46. return Void.TYPE;
  47. }));
  48. }
  49. static {
  50. register();
  51. }
  52. private static class ScheduledGoto implements Runnable {
  53. private String name;
  54. private Script sc;
  55. private String label;
  56. private int line;
  57. public ScheduledGoto(String name, Script sc, String label, int line) {
  58. this.name = name;
  59. this.sc = sc;
  60. this.label = label;
  61. this.line = line;
  62. }
  63. @Override
  64. public void run() {
  65. if(sc.shouldTerm()) {
  66. return;
  67. } else if(sc.isHolded()) {
  68. sc.getScriptManager().getScheduler().scheduleTask(name,
  69. new ScheduledGoto(name, sc, label, line), 2);
  70. return;
  71. }
  72. try {
  73. sc.gotoLabel(label, true, 1);
  74. sc.run();
  75. } catch(Exception ex) {
  76. sc.logException(ex, "sgoto", line);
  77. }
  78. if(sc.shouldTerm()) {
  79. sc.getScriptManager().removeScript(sc);
  80. }
  81. }
  82. }
  83. @SuppressWarnings({"unchecked", "rawtypes"})
  84. private static void register() {
  85. registerFunction("nothing", (sc, in) -> Void.TYPE);
  86. registerConsumer("modtimer", (sc, in) -> sc.addTimer(in[0].getLong(sc)));
  87. registerConsumer("error", (sc, in) -> sc.setStackTrace(in[0].getBoolean(sc)));
  88. registerConsumer("event.load", (sc, in) -> {
  89. String event = in[0].getString(sc);
  90. sc.loadEvent(event);
  91. sc.getScriptManager().loadEvent(event, sc);
  92. });
  93. registerConsumer("event.unload", (sc, in) -> {
  94. String event = in[0].getString(sc);
  95. sc.unloadEvent(in[0].getString(sc));
  96. sc.getScriptManager().unloadEvent(event, sc);
  97. });
  98. registerFunction("event.isloaded", (sc, in) -> sc.isEventLoaded(in[0].getString(sc)));
  99. registerFunction("script.get", (sc, in) -> {
  100. if(in.length == 0) {
  101. return sc;
  102. }
  103. String name = in[0].getString(sc);
  104. for(Script script : sc.getScriptManager().getScripts()) {
  105. if(script.getName().equals(name)) {
  106. return script;
  107. }
  108. }
  109. return null;
  110. });
  111. registerFunction("script.getfromid",
  112. (sc, in) -> sc.getScriptManager().getScript(in[0].getInt(sc)));
  113. registerFunction("script.getid", (sc, in) -> (double) ((Script) in[0].get(sc)).getId());
  114. registerFunction("script.getvar", (sc, in) -> {
  115. Script other = (Script) in[0].get(sc);
  116. Variable v = other.getVar(in[1].getString(sc));
  117. if(v == null) {
  118. return null;
  119. }
  120. return v.get(other);
  121. });
  122. registerConsumer("script.setvar", (sc, in) -> {
  123. Script other = (Script) in[0].get(sc);
  124. other.getVar(in[1].getString(sc)).set(other, in[2].get(sc));
  125. });
  126. registerFunction("script.getall", (sc, in) -> {
  127. String name = in[0].getString(sc);
  128. return sc.getScriptManager().getScripts().stream()
  129. .filter(script -> script.getName().equals(name)).collect(Collectors.toList());
  130. });
  131. registerConsumer("script.term", (sc, in) -> {
  132. Script other = (Script) in[0].get(sc);
  133. other.term();
  134. sc.getScriptManager().removeScript(other);
  135. });
  136. registerFunction(">>", (sc, in) -> (double) (in[0].getInt(sc) >> in[1].getInt(sc)));
  137. registerFunction("<<", (sc, in) -> (double) (in[0].getInt(sc) << in[1].getInt(sc)));
  138. registerFunction("&", (sc, in) -> (double) (in[0].getInt(sc) & in[1].getInt(sc)));
  139. registerFunction("|", (sc, in) -> (double) (in[0].getInt(sc) | in[1].getInt(sc)));
  140. registerFunction("^", (sc, in) -> (double) (in[0].getInt(sc) ^ in[1].getInt(sc)));
  141. registerFunction("~", (sc, in) -> (double) (~in[0].getInt(sc)));
  142. registerFunction("bit.set",
  143. (sc, in) -> (double) (in[0].getInt(sc) | (1 << (in[1].getInt(sc)))));
  144. registerFunction("bit.unset",
  145. (sc, in) -> (double) (in[0].getInt(sc) & (~(1 << (in[1].getInt(sc))))));
  146. registerFunction("bit.get",
  147. (sc, in) -> (in[0].getInt(sc) & (1 << (in[1].getInt(sc)))) != 0);
  148. registerFunction("%", (sc, in) -> (double) (in[0].getInt(sc) % in[1].getInt(sc)));
  149. registerAlias("%", "math.mod");
  150. registerFunction("math.abs", (sc, in) -> Math.abs(in[0].getDouble(sc)));
  151. registerFunction("math.pow",
  152. (sc, in) -> Math.pow(in[0].getDouble(sc), in[1].getDouble(sc)));
  153. registerFunction("math.root",
  154. (sc, in) -> Math.pow(in[0].getDouble(sc), 1.0 / in[1].getDouble(sc)));
  155. registerFunction("math.sqrt", (sc, in) -> Math.sqrt(in[0].getDouble(sc)));
  156. registerFunction("math.hypot",
  157. (sc, in) -> Math.hypot(in[0].getDouble(sc), in[1].getDouble(sc)));
  158. registerFunction("math.sin", (sc, in) -> Math.sin(in[0].getDouble(sc)));
  159. registerFunction("math.cos", (sc, in) -> Math.cos(in[0].getDouble(sc)));
  160. registerFunction("math.tan", (sc, in) -> Math.tan(in[0].getDouble(sc)));
  161. registerFunction("math.asin", (sc, in) -> Math.asin(in[0].getDouble(sc)));
  162. registerFunction("math.acos", (sc, in) -> Math.acos(in[0].getDouble(sc)));
  163. registerFunction("math.atan", (sc, in) -> Math.atan(in[0].getDouble(sc)));
  164. registerFunction("math.e", (sc, in) -> Math.E);
  165. registerFunction("math.pi", (sc, in) -> Math.PI);
  166. registerFunction("math.ln", (sc, in) -> Math.log(in[0].getDouble(sc)));
  167. registerFunction("math.log", (sc, in) -> Math.log10(in[0].getDouble(sc)));
  168. registerFunction("math.random",
  169. (sc, in) -> (double) SnuviUtils.randomInt(in[0].getInt(sc), in[1].getInt(sc)));
  170. registerFunction("math.round", (sc, in) -> (double) Math.round(in[0].getDouble(sc)));
  171. registerFunction("math.rounddown", (sc, in) -> Math.floor(in[0].getDouble(sc)));
  172. registerFunction("math.roundup", (sc, in) -> Math.ceil(in[0].getDouble(sc)));
  173. registerFunction("math.roundcomma", (sc, in) -> {
  174. double d = in[0].getDouble(sc);
  175. int factor = (int) Math.pow(10, in[1].getInt(sc));
  176. return (double) (((double) Math.round(d * factor)) / factor);
  177. });
  178. registerFunction("math.min",
  179. (sc, in) -> Math.min(in[0].getDouble(sc), in[1].getDouble(sc)));
  180. registerFunction("math.max",
  181. (sc, in) -> Math.max(in[0].getDouble(sc), in[1].getDouble(sc)));
  182. registerFunction("matrix.new", (sc, in) -> new Matrix());
  183. registerFunction("matrix.newrotationy",
  184. (sc, in) -> Matrix.getRotationY(in[0].getDouble(sc)));
  185. registerFunction("matrix.newrotationx",
  186. (sc, in) -> Matrix.getRotationX(in[0].getDouble(sc)));
  187. registerFunction("matrix.mul",
  188. (sc, in) -> ((Matrix) in[0].get(sc)).mul((Matrix) in[1].get(sc)));
  189. registerConsumer("matrix.mulvector",
  190. (sc, in) -> ((Matrix) in[0].get(sc)).mul((Vector) in[1].get(sc)));
  191. registerFunction("vector.new", (sc, in) -> new Vector(in[0].getDouble(sc),
  192. in[1].getDouble(sc), in[2].getDouble(sc)));
  193. registerConsumer("vector.set", (sc, in) -> ((Vector) in[0].get(sc)).set(in[1].getDouble(sc),
  194. in[2].getDouble(sc), in[3].getDouble(sc)));
  195. registerFunction("vector.getx", (sc, in) -> ((Vector) in[0].get(sc)).getX());
  196. registerFunction("vector.gety", (sc, in) -> ((Vector) in[0].get(sc)).getY());
  197. registerFunction("vector.getz", (sc, in) -> ((Vector) in[0].get(sc)).getZ());
  198. registerFunction("list.new", (sc, in) -> new ArrayList<>());
  199. registerFunction("list.exists", (sc, in) -> in[0].get(sc) instanceof List);
  200. registerFunction("list.add", (sc, in) -> ((List) in[0].get(sc)).add(in[1].get(sc)));
  201. registerConsumer("list.addall", (sc, in) -> {
  202. List list = ((List) in[0].get(sc));
  203. for(int i = 1; i < in.length; i++) {
  204. list.add(in[i].get(sc));
  205. }
  206. });
  207. registerFunction("list.remove", (sc, in) -> ((List) in[0].get(sc)).remove(in[1].get(sc)));
  208. registerFunction("list.removeindex",
  209. (sc, in) -> ((List) in[0].get(sc)).remove(in[1].getInt(sc)));
  210. registerFunction("list.contains",
  211. (sc, in) -> ((List) in[0].get(sc)).contains(in[1].get(sc)));
  212. registerFunction("list.getsize", (sc, in) -> (double) ((List) in[0].get(sc)).size());
  213. registerFunction("list.getindex", (sc, in) -> ((List) in[0].get(sc)).get(in[1].getInt(sc)));
  214. registerAlias("list.getindex", "list.get");
  215. registerFunction("list.setindex",
  216. (sc, in) -> ((List) in[0].get(sc)).set(in[1].getInt(sc), in[2].get(sc)));
  217. registerConsumer("list.clear", (sc, in) -> ((List) in[0].get(sc)).clear());
  218. registerFunction("list.getindexof",
  219. (sc, in) -> (double) ((List) in[0].get(sc)).indexOf(in[1].get(sc)));
  220. registerConsumer("list.sort", (sc, in) -> {
  221. Collections.sort(((List<Object>) in[0].get(sc)),
  222. (o1, o2) -> ((Comparable) o1).compareTo(o2));
  223. });
  224. registerConsumer("list.reverse",
  225. (sc, in) -> Collections.reverse((List<Object>) in[0].get(sc)));
  226. registerConsumer("list.shuffle",
  227. (sc, in) -> Collections.shuffle((List<Object>) in[0].get(sc)));
  228. registerFunction("list.iterator", (sc, in) -> ((List) in[0].get(sc)).iterator());
  229. registerFunction("array.new", (sc, in) -> {
  230. if(in.length == 0) {
  231. throw new ArrayIndexOutOfBoundsException("missing array dimension");
  232. }
  233. int[] dim = new int[in.length];
  234. for(int i = 0; i < in.length; i++) {
  235. dim[i] = in[i].getInt(sc);
  236. }
  237. return Array.newInstance(Object.class, dim);
  238. });
  239. registerFunction("array.getsize", (sc, in) -> (double) Array.getLength(in[0].get(sc)));
  240. registerAlias("array.getsize", "array.length");
  241. registerFunction("map.new", (sc, in) -> new HashMap<>());
  242. registerFunction("map.exists", (sc, in) -> in[0].get(sc) instanceof Map);
  243. registerFunction("map.add",
  244. (sc, in) -> ((Map) in[0].get(sc)).put(in[1].get(sc), in[2].get(sc)));
  245. registerFunction("map.remove", (sc, in) -> ((Map) in[0].get(sc)).remove(in[1].get(sc)));
  246. registerFunction("map.contains",
  247. (sc, in) -> ((Map) in[0].get(sc)).containsKey(in[1].get(sc)));
  248. registerFunction("map.getsize", (sc, in) -> (double) ((Map) in[0].get(sc)).size());
  249. registerFunction("map.get", (sc, in) -> ((Map) in[0].get(sc)).get(in[1].get(sc)));
  250. registerFunction("map.getordefault",
  251. (sc, in) -> ((Map) in[0].get(sc)).getOrDefault(in[1].get(sc), in[2].get(sc)));
  252. registerConsumer("map.clear", (sc, in) -> ((Map) in[0].get(sc)).clear());
  253. registerFunction("map.iterator", (sc, in) -> ((Map) in[0].get(sc)).entrySet().iterator());
  254. registerFunction("map.getkey", (sc, in) -> ((Map.Entry) in[0].get(sc)).getKey());
  255. registerFunction("map.getvalue", (sc, in) -> ((Map.Entry) in[0].get(sc)).getValue());
  256. registerFunction("map.setvalue",
  257. (sc, in) -> ((Map.Entry) in[0].get(sc)).setValue(in[1].get(sc)));
  258. registerFunction("set.new", (sc, in) -> new HashSet<>());
  259. registerFunction("set.exists", (sc, in) -> in[0].get(sc) instanceof Set);
  260. registerFunction("set.add", (sc, in) -> ((Set) in[0].get(sc)).add(in[1].get(sc)));
  261. registerConsumer("set.addall", (sc, in) -> {
  262. Set set = ((Set) in[0].get(sc));
  263. for(int i = 1; i < in.length; i++) {
  264. set.add(in[i].get(sc));
  265. }
  266. });
  267. registerFunction("set.remove", (sc, in) -> ((Set) in[0].get(sc)).remove(in[1].get(sc)));
  268. registerFunction("set.contains", (sc, in) -> ((Set) in[0].get(sc)).contains(in[1].get(sc)));
  269. registerFunction("set.getsize", (sc, in) -> (double) ((Set) in[0].get(sc)).size());
  270. registerConsumer("set.clear", (sc, in) -> ((Set) in[0].get(sc)).clear());
  271. registerFunction("set.iterator", (sc, in) -> ((Set) in[0].get(sc)).iterator());
  272. registerFunction("time.new", (sc, in) -> {
  273. GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
  274. cal.setTimeInMillis(in[0].getLong(sc));
  275. return cal;
  276. });
  277. registerFunction("time.getmillis", (sc, in) -> (double) System.currentTimeMillis());
  278. registerFunction("time.getnanos", (sc, in) -> (double) System.nanoTime());
  279. registerFunction("time.from",
  280. (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).getTimeInMillis());
  281. registerConsumer("time.nextday", (sc, in) -> {
  282. GregorianCalendar cal = (GregorianCalendar) in[0].get(sc);
  283. cal.add(Calendar.DAY_OF_YEAR, 1);
  284. cal.set(Calendar.HOUR_OF_DAY, 0);
  285. cal.set(Calendar.SECOND, 0);
  286. cal.set(Calendar.MINUTE, 0);
  287. cal.set(Calendar.MILLISECOND, 0);
  288. });
  289. registerFunction("time.getyear",
  290. (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.YEAR));
  291. registerFunction("time.getmonth",
  292. (sc, in) -> (double) (((GregorianCalendar) in[0].get(sc)).get(Calendar.MONTH) + 1));
  293. registerFunction("time.getday", (sc,
  294. in) -> (double) (((GregorianCalendar) in[0].get(sc)).get(Calendar.DAY_OF_MONTH)));
  295. registerFunction("time.gethour",
  296. (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.HOUR_OF_DAY));
  297. registerFunction("time.getminute",
  298. (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.MINUTE));
  299. registerFunction("time.getsecond",
  300. (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.SECOND));
  301. registerFunction("text.matches",
  302. (sc, in) -> in[0].getString(sc).matches(in[1].getString(sc)));
  303. registerFunction("text.number", (sc, in) -> SnuviUtils.toString(in[0].getDouble(sc)));
  304. registerFunction("text.class", (sc, in) -> in[0].get(sc).getClass().getSimpleName());
  305. registerFunction("text.tolowercase",
  306. (sc, in) -> SnuviUtils.connect(sc, in, 0).toLowerCase());
  307. registerAlias("text.tolowercase", "tolowercase");
  308. registerFunction("text.touppercase",
  309. (sc, in) -> SnuviUtils.connect(sc, in, 0).toUpperCase());
  310. registerAlias("text.touppercase", "touppercase");
  311. registerFunction("text.split", (sc, in) -> {
  312. String[] parts = in[1].getString(sc).split(in[0].getString(sc));
  313. ArrayList<Object> list = new ArrayList<>();
  314. for(String part : parts) {
  315. list.add(SnuviUtils.convert(part));
  316. }
  317. return list;
  318. });
  319. registerAlias("text.split", "split");
  320. registerFunction("text.convert", (sc, in) -> SnuviUtils.convert(in[0].getString(sc)));
  321. registerFunction("text.concatlist", (sc, in) -> {
  322. StringBuilder sb = new StringBuilder();
  323. List<Object> list = (List<Object>) in[0].get(sc);
  324. String splitter = in[1].getString(sc);
  325. Iterator<Object> iter = list.iterator();
  326. int from = in[2].getInt(sc);
  327. int to = Math.min(in[3].getInt(sc), list.size() - 1);
  328. to -= from;
  329. while(iter.hasNext() && from > 0) {
  330. iter.next();
  331. from--;
  332. }
  333. while(iter.hasNext() && to > 0) {
  334. sb.append(iter.next());
  335. sb.append(splitter);
  336. to--;
  337. }
  338. if(iter.hasNext() && to == 0) {
  339. sb.append(iter.next());
  340. }
  341. return sb.toString();
  342. });
  343. registerAlias("text.concatlist", "concatlist");
  344. registerFunction("text.concat", (sc, in) -> SnuviUtils.connect(sc, in, 0));
  345. registerAlias("text.concat", "concat");
  346. registerFunction("text.concatspace", (sc, in) -> SnuviUtils.connect(sc, in, " ", 0));
  347. registerFunction("text", (sc, in) -> String.valueOf(in[0].get(sc)));
  348. registerFunction("text.substring",
  349. (sc, in) -> in[0].getString(sc).substring(in[1].getInt(sc), in[2].getInt(sc)));
  350. registerFunction("text.length", (sc, in) -> (double) in[0].getString(sc).length());
  351. registerFunction("text.startswith",
  352. (sc, in) -> in[0].getString(sc).startsWith(in[1].getString(sc), in[2].getInt(sc)));
  353. registerFunction("text.endswith",
  354. (sc, in) -> in[0].getString(sc).endsWith(in[1].getString(sc)));
  355. registerFunction("text.contains",
  356. (sc, in) -> in[0].getString(sc).contains(in[1].getString(sc)));
  357. registerFunction("text.indexof", (sc,
  358. in) -> (double) in[0].getString(sc).indexOf(in[1].getString(sc), in[2].getInt(sc)));
  359. registerFunction("text.lastindexof", (sc, in) -> (double) in[0].getString(sc)
  360. .lastIndexOf(in[1].getString(sc), in[2].getInt(sc)));
  361. registerFunction("text.replace",
  362. (sc, in) -> in[0].getString(sc).replace(in[1].getString(sc), in[2].getString(sc)));
  363. registerFunction("text.trim", (sc, in) -> in[0].getString(sc).trim());
  364. registerFunction("text.charat",
  365. (sc, in) -> String.valueOf(in[0].getString(sc).charAt(in[1].getInt(sc))));
  366. registerFunction("text.charcode",
  367. (sc, in) -> (double) in[0].getString(sc).charAt(in[1].getInt(sc)));
  368. registerFunction("text.fromcode", (sc, in) -> String.valueOf((char) in[0].getInt(sc)));
  369. registerFunction("text.onlyletters", (sc, in) -> {
  370. for(char c : in[0].getString(sc).toCharArray()) {
  371. if(!Character.isLetter(c)) {
  372. return false;
  373. }
  374. }
  375. return true;
  376. });
  377. registerFunction("file.new", (sc, in) -> new File(in[0].getString(sc)));
  378. registerFunction("file.exists", (sc, in) -> ((File) in[0].get(sc)).exists());
  379. registerFunction("file.isfile", (sc, in) -> ((File) in[0].get(sc)).isFile());
  380. registerFunction("file.isdirectory", (sc, in) -> ((File) in[0].get(sc)).isDirectory());
  381. registerFunction("file.delete", (sc, in) -> ((File) in[0].get(sc)).delete());
  382. registerFunction("file.getname", (sc, in) -> ((File) in[0].get(sc)).getName());
  383. registerFunction("file.getlist",
  384. (sc, in) -> Arrays.asList(((File) in[0].get(sc)).listFiles()));
  385. registerFunction("file.read",
  386. (sc, in) -> Files.readAllLines(((File) in[0].get(sc)).toPath()));
  387. registerConsumer("file.write", (sc, in) -> {
  388. File f = (File) in[0].get(sc);
  389. if(f.getParentFile() != null) {
  390. f.getParentFile().mkdirs();
  391. }
  392. if(!f.exists()) {
  393. f.createNewFile();
  394. }
  395. Files.write(
  396. Paths.get(f.toURI()), ((List<Object>) in[1].get(sc)).stream()
  397. .map(o -> String.valueOf(o)).collect(Collectors.toList()),
  398. StandardCharsets.UTF_8);
  399. });
  400. registerFunction("config.new",
  401. (sc, in) -> new SnuviConfig(in[0].getString(sc), in[1].getString(sc)));
  402. registerFunction("config.exists", (sc, in) -> ((SnuviConfig) in[0].get(sc)).exists());
  403. registerFunction("config.save", (sc, in) -> ((SnuviConfig) in[0].get(sc)).save(sc));
  404. registerConsumer("config.load", (sc, in) -> ((SnuviConfig) in[0].get(sc)).load(sc));
  405. registerFunction("config.delete", (sc, in) -> ((SnuviConfig) in[0].get(sc)).delete());
  406. registerConsumer("config.set",
  407. (sc, in) -> ((SnuviConfig) in[0].get(sc)).set(in[1].getString(sc), in[2].get(sc)));
  408. registerFunction("config.getbool", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getBoolean(sc,
  409. in[1].getString(sc), in[2].getBoolean(sc)));
  410. registerFunction("config.getdouble", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getDouble(sc,
  411. in[1].getString(sc), in[2].getDouble(sc)));
  412. registerFunction("config.getstring", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getString(sc,
  413. in[1].getString(sc), in[2].getString(sc)));
  414. registerFunction("read.number", (sc, in) -> Double.parseDouble(in[0].getString(sc)));
  415. registerFunction("+", (sc, in) -> in[0].getDouble(sc) + in[1].getDouble(sc));
  416. registerAlias("+", "add");
  417. registerFunction("-", (sc, in) -> in.length == 1 ? -in[0].getDouble(sc)
  418. : in[0].getDouble(sc) - in[1].getDouble(sc));
  419. registerAlias("-", "sub");
  420. registerFunction("*", (sc, in) -> in[0].getDouble(sc) * in[1].getDouble(sc));
  421. registerAlias("*", "mul");
  422. registerFunction("/", (sc, in) -> in[0].getDouble(sc) / in[1].getDouble(sc));
  423. registerAlias("/", "div");
  424. registerFunction("=", (sc, in) -> {
  425. Object o = in[1].get(sc);
  426. in[0].set(sc, o);
  427. return o;
  428. });
  429. registerFunction("+=", (sc, in) -> {
  430. Object o = in[0].getDouble(sc) + in[1].getDouble(sc);
  431. in[0].set(sc, o);
  432. return o;
  433. });
  434. registerFunction("p++", (sc, in) -> {
  435. double d = in[0].getDouble(sc);
  436. in[0].set(sc, d + 1.0);
  437. return d;
  438. });
  439. registerAlias("p++", "inc");
  440. registerFunction("++", (sc, in) -> {
  441. double d = in[0].getDouble(sc) + 1.0;
  442. in[0].set(sc, d);
  443. return d;
  444. });
  445. registerFunction("-=", (sc, in) -> {
  446. Object o = in[0].getDouble(sc) - in[1].getDouble(sc);
  447. in[0].set(sc, o);
  448. return o;
  449. });
  450. registerFunction("p--", (sc, in) -> {
  451. double d = in[0].getDouble(sc);
  452. in[0].set(sc, d - 1.0);
  453. return d;
  454. });
  455. registerAlias("p--", "dec");
  456. registerFunction("--", (sc, in) -> {
  457. double d = in[0].getDouble(sc) - 1.0;
  458. in[0].set(sc, d);
  459. return d;
  460. });
  461. registerFunction("*=", (sc, in) -> {
  462. Object o = in[0].getDouble(sc) * in[1].getDouble(sc);
  463. in[0].set(sc, o);
  464. return o;
  465. });
  466. registerFunction("/=", (sc, in) -> {
  467. Object o = in[0].getDouble(sc) / in[1].getDouble(sc);
  468. in[0].set(sc, o);
  469. return o;
  470. });
  471. registerFunction("%=", (sc, in) -> {
  472. Object o = (double) (in[0].getInt(sc) % in[1].getInt(sc));
  473. in[0].set(sc, o);
  474. return o;
  475. });
  476. registerFunction("<<=", (sc, in) -> {
  477. Object o = (double) (in[0].getInt(sc) << in[1].getInt(sc));
  478. in[0].set(sc, o);
  479. return o;
  480. });
  481. registerFunction(">>=", (sc, in) -> {
  482. Object o = (double) (in[0].getInt(sc) >> in[1].getInt(sc));
  483. in[0].set(sc, o);
  484. return o;
  485. });
  486. registerFunction("&=", (sc, in) -> {
  487. Object o = (double) (in[0].getInt(sc) & in[1].getInt(sc));
  488. in[0].set(sc, o);
  489. return o;
  490. });
  491. registerFunction("^=", (sc, in) -> {
  492. Object o = (double) (in[0].getInt(sc) ^ in[1].getInt(sc));
  493. in[0].set(sc, o);
  494. return o;
  495. });
  496. registerFunction("|=", (sc, in) -> {
  497. Object o = (double) (in[0].getInt(sc) | in[1].getInt(sc));
  498. in[0].set(sc, o);
  499. return o;
  500. });
  501. registerFunction("getvar", (sc, in) -> sc.getVar(in[0].getString(sc)).get(sc));
  502. registerConsumer("setvar",
  503. (sc, in) -> sc.getVar(in[0].getString(sc)).set(sc, in[1].get(sc)));
  504. registerConsumer("removevar", (sc, in) -> sc.getVar(in[0].getString(sc)).set(sc, null));
  505. registerConsumer("wait", (sc, in) -> sc.setWaiting());
  506. registerConsumer("goto", (sc, in) -> sc.gotoLabel(in[0].getString(sc), true));
  507. registerConsumer("ignoregoto", (sc, in) -> sc.gotoLabel(in[0].getString(sc), false));
  508. registerAlias("ignoregoto", "igoto");
  509. registerConsumer("sgoto", (sc, in) -> {
  510. int time = in[0].getInt(sc);
  511. if(time < 0) {
  512. throw new IllegalArgumentException("time units can't be negative");
  513. }
  514. String label = in[1].getString(sc);
  515. int line = sc.getLine();
  516. sc.getScriptManager().getScheduler().scheduleTask("sgoto",
  517. new ScheduledGoto("sgoto", sc, label, line), time);
  518. });
  519. registerConsumer("gosub", (sc, in) -> sc.goSub(in[0].getString(sc)));
  520. registerFunction("==", (sc, in) -> Objects.equals(in[0].get(sc), in[1].get(sc)));
  521. registerAlias("==", "equal");
  522. registerAlias("==", "equals");
  523. registerFunction("!=", (sc, in) -> !Objects.equals(in[0].get(sc), in[1].get(sc)));
  524. registerAlias("!=", "notequal");
  525. registerFunction("<",
  526. (sc, in) -> ((Comparable) in[0].get(sc)).compareTo(in[1].get(sc)) < 0);
  527. registerAlias("<", "less");
  528. registerFunction(">",
  529. (sc, in) -> ((Comparable) in[0].get(sc)).compareTo(in[1].get(sc)) > 0);
  530. registerAlias(">", "greater");
  531. registerFunction("<=",
  532. (sc, in) -> ((Comparable) in[0].get(sc)).compareTo(in[1].get(sc)) <= 0);
  533. registerAlias("<=", "lessequal");
  534. registerFunction(">=",
  535. (sc, in) -> ((Comparable) in[0].get(sc)).compareTo(in[1].get(sc)) >= 0);
  536. registerAlias(">=", "greaterequal");
  537. registerFunction("!", (sc, in) -> !in[0].getBoolean(sc));
  538. registerAlias("!", "invert");
  539. registerFunction("&&", (sc, in) -> {
  540. for(InputProvider i : in) {
  541. if(!i.getBoolean(sc)) {
  542. return false;
  543. }
  544. }
  545. return true;
  546. });
  547. registerAlias("&&", "and");
  548. registerFunction("||", (sc, in) -> {
  549. for(InputProvider i : in) {
  550. if(i.getBoolean(sc)) {
  551. return true;
  552. }
  553. }
  554. return false;
  555. });
  556. registerAlias("||", "or");
  557. registerFunction("getscriptvar", (sc, in) -> GLOBAL_VARS.get(in[0].getString(sc)));
  558. registerFunction("setscriptvar",
  559. (sc, in) -> GLOBAL_VARS.put(in[0].getString(sc), in[1].get(sc)));
  560. registerFunction("delscriptvar", (sc, in) -> GLOBAL_VARS.remove(in[0].getString(sc)));
  561. registerConsumer("clearscriptvars", (sc, in) -> GLOBAL_VARS.clear());
  562. registerFunction("hasnext", (sc, in) -> ((Iterator) in[0].get(sc)).hasNext());
  563. registerFunction("next", (sc, in) -> ((Iterator) in[0].get(sc)).next());
  564. registerConsumer("remove", (sc, in) -> ((Iterator) in[0].get(sc)).remove());
  565. registerFunction("iterator", (sc, in) -> ((Collection) in[0].get(sc)).iterator());
  566. registerConsumer("swap", (sc, in) -> {
  567. Object o = in[0].get(sc);
  568. in[0].set(sc, in[1].get(sc));
  569. in[1].set(sc, o);
  570. });
  571. registerConsumer("print", (sc, in) -> {
  572. sc.getScriptManager().getLogger().print(SnuviUtils.connect(sc, in, 0), null, "print",
  573. sc.getName(), sc, sc.getStackTrace());
  574. });
  575. registerConsumer("rprint", (sc, in) -> System.out.println(SnuviUtils.connect(sc, in, 0)));
  576. registerConsumer("waitfor", (sc, in) -> {
  577. long l = in[0].getInt(sc);
  578. if(l < 0) {
  579. throw new IllegalArgumentException("time units can't be negative");
  580. }
  581. sc.setHolded(true);
  582. sc.setWaiting();
  583. sc.getScriptManager().getScheduler().scheduleTask("waitfor", () -> {
  584. if(sc.shouldTerm()) {
  585. return;
  586. }
  587. sc.setHolded(false);
  588. sc.run();
  589. if(sc.shouldTerm()) {
  590. sc.getScriptManager().removeScript(sc);
  591. }
  592. }, l);
  593. });
  594. registerConsumer("term", (sc, in) -> {
  595. sc.term();
  596. sc.getScriptManager().removeScript(sc);
  597. });
  598. registerFunction("isbool", (sc, in) -> (in[0].get(sc) instanceof Boolean));
  599. registerFunction("isdouble", (sc, in) -> (in[0].get(sc) instanceof Double));
  600. registerFunction("islong", (sc, in) -> {
  601. Object o = in[0].get(sc);
  602. if(o instanceof Double) {
  603. double d = (Double) o;
  604. return d == (long) d;
  605. }
  606. return false;
  607. });
  608. registerConsumer("assert", (sc, in) -> {
  609. if(!in[0].getBoolean(sc)) {
  610. throw new IllegalArgumentException("assertion failed");
  611. }
  612. });
  613. registerFunction("class", (sc, in) -> in[0].get(sc).getClass());
  614. registerFunction("usedmemory", (sc, in) -> {
  615. Runtime runtime = Runtime.getRuntime();
  616. double usedMemory = (runtime.totalMemory() - runtime.freeMemory()) / 1048576;
  617. return usedMemory;
  618. });
  619. registerFunction("allocatedmemory",
  620. (sc, in) -> Runtime.getRuntime().totalMemory() / 1048576.0);
  621. }
  622. }