FunctionLoader.java 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. package me.hammerle.snuviscript.code;
  2. import java.io.File;
  3. import java.io.IOException;
  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.Collections;
  13. import java.util.Calendar;
  14. import java.util.GregorianCalendar;
  15. import java.util.HashMap;
  16. import java.util.Map;
  17. import java.util.HashSet;
  18. import java.util.Iterator;
  19. import java.util.Objects;
  20. import java.util.Set;
  21. import java.util.function.BiFunction;
  22. import java.util.stream.Collectors;
  23. import me.hammerle.snuviscript.array.DynamicArray;
  24. import me.hammerle.snuviscript.config.SnuviConfig;
  25. import me.hammerle.snuviscript.exceptions.AssertionException;
  26. import me.hammerle.snuviscript.exceptions.FileIOException;
  27. import me.hammerle.snuviscript.variable.ArrayVariable;
  28. import me.hammerle.snuviscript.variable.Variable;
  29. public class FunctionLoader
  30. {
  31. private static final HashMap<String, BasicFunction> FUNCTIONS = new HashMap<>();
  32. protected static void registerFunction(String name, String fname, BiFunction<Script, InputProvider[], Object> f)
  33. {
  34. FUNCTIONS.put(name, new BasicFunction(fname, f));
  35. }
  36. protected static void registerFunction(String name, BiFunction<Script, InputProvider[], Object> f)
  37. {
  38. registerFunction(name, name, f);
  39. }
  40. protected static void registerAlias(String original, String alias)
  41. {
  42. FUNCTIONS.put(alias, FUNCTIONS.get(original));
  43. }
  44. public static BasicFunction getFunction(String f)
  45. {
  46. final String function = f.toLowerCase();
  47. return FUNCTIONS.getOrDefault(function, new BasicFunction(function, (sc, in) ->
  48. {
  49. Script sub = sc.subScripts.get(function);
  50. if(sub == null)
  51. {
  52. throw new NullPointerException("function " + function + " does not exist");
  53. }
  54. // push storage for local vars
  55. HashMap<String, Variable> vars = new HashMap<>();
  56. if(in.length != sub.subScriptInput.length)
  57. {
  58. throw new NullPointerException("invalid number of parameters at function '" + function + "'");
  59. }
  60. // generate local vars
  61. String s;
  62. Variable v;
  63. for(int i = 0; i < in.length; i++)
  64. {
  65. s = sub.subScriptInput[i];
  66. if(in[i].isArray(sc))
  67. {
  68. v = new ArrayVariable(s);
  69. v.set(sc, in[i].getArray(sc));
  70. }
  71. else
  72. {
  73. v = new Variable(s);
  74. v.set(sc, in[i].get(sc));
  75. }
  76. vars.put(s, v);
  77. }
  78. sub.localVars.push(vars);
  79. // saving line for return
  80. int line = sub.currentLine;
  81. // set starting line for current run
  82. sub.currentLine = 0;
  83. // run subscript and save return value
  84. Object r = sub.run();
  85. // return back to previous line
  86. sub.currentLine = line;
  87. // pop storage for local vars
  88. sub.localVars.pop();
  89. return r;
  90. }));
  91. }
  92. static
  93. {
  94. // ---------------------------------------------------------------------
  95. // system stuff
  96. // ---------------------------------------------------------------------
  97. registerFunction("nothing", (sc, in) -> Void.TYPE);
  98. registerFunction("error", (sc, in) ->
  99. {
  100. sc.printStackTrace = !sc.printStackTrace;
  101. return Void.TYPE;
  102. });
  103. registerFunction("", (sc, in) -> in[0].get(sc));
  104. // ---------------------------------------------------------------------
  105. // event
  106. // ---------------------------------------------------------------------
  107. registerFunction("event.load", (sc, in) ->
  108. {
  109. sc.events.add(in[0].getString(sc));
  110. return Void.TYPE;
  111. });
  112. registerFunction("event.unload", (sc, in) ->
  113. {
  114. sc.events.remove(in[0].getString(sc));
  115. return Void.TYPE;
  116. });
  117. registerFunction("event.isloaded", (sc, in) -> sc.isEventLoaded(in[0].getString(sc)));
  118. // ---------------------------------------------------------------------
  119. // bit
  120. // ---------------------------------------------------------------------
  121. registerFunction(">>", (sc, in) -> (double) (in[0].getInt(sc) >> in[1].getInt(sc)));
  122. registerFunction("<<", (sc, in) -> (double) (in[0].getInt(sc) << in[1].getInt(sc)));
  123. registerFunction("&", (sc, in) -> (double) (in[0].getInt(sc) & in[1].getInt(sc)));
  124. registerFunction("|", (sc, in) -> (double) (in[0].getInt(sc) | in[1].getInt(sc)));
  125. registerFunction("^", (sc, in) -> (double) (in[0].getInt(sc) ^ in[1].getInt(sc)));
  126. registerFunction("~", (sc, in) -> (double) (~in[0].getInt(sc)));
  127. registerFunction("bit.set", (sc, in) -> (double) (in[0].getInt(sc) | (1 << (in[1].getInt(sc)))));
  128. registerFunction("bit.unset", (sc, in) -> (double) (in[0].getInt(sc) & (~(1 << (in[1].getInt(sc))))));
  129. registerFunction("bit.get", (sc, in) -> (in[0].getInt(sc) & (1 << (in[1].getInt(sc)))) != 0);
  130. // ---------------------------------------------------------------------
  131. // math
  132. // ---------------------------------------------------------------------
  133. registerFunction("%", (sc, in) -> (double) (in[0].getInt(sc) % in[1].getInt(sc)));
  134. registerAlias("%", "math.mod");
  135. registerFunction("math.abs", (sc, in) -> Math.abs(in[0].getDouble(sc)));
  136. registerFunction("math.pow", (sc, in) -> Math.pow(in[0].getDouble(sc), in[1].getDouble(sc)));
  137. registerFunction("math.root", (sc, in) -> Math.pow(in[0].getDouble(sc), 1.0 / in[1].getDouble(sc)));
  138. registerFunction("math.sqrt", (sc, in) -> Math.sqrt(in[0].getDouble(sc)));
  139. registerFunction("math.hypot", (sc, in) -> Math.hypot(in[0].getDouble(sc), in[1].getDouble(sc)));
  140. registerFunction("math.sin", (sc, in) -> Math.sin(in[0].getDouble(sc)));
  141. registerFunction("math.cos", (sc, in) -> Math.cos(in[0].getDouble(sc)));
  142. registerFunction("math.tan", (sc, in) -> Math.tan(in[0].getDouble(sc)));
  143. registerFunction("math.sin", (sc, in) -> Math.sin(in[0].getDouble(sc)));
  144. registerFunction("math.acos", (sc, in) -> Math.acos(in[0].getDouble(sc)));
  145. registerFunction("math.atan", (sc, in) -> Math.atan(in[0].getDouble(sc)));
  146. registerFunction("math.asin", (sc, in) -> Math.asin(in[0].getDouble(sc)));
  147. registerFunction("math.e", (sc, in) -> Math.E);
  148. registerFunction("math.pi", (sc, in) -> Math.PI);
  149. registerFunction("math.ln", (sc, in) -> Math.log(in[0].getDouble(sc)));
  150. registerFunction("math.log", (sc, in) -> Math.log10(in[0].getDouble(sc)));
  151. registerFunction("math.random", (sc, in) -> (double) SnuviUtils.randomInt(in[0].getInt(sc), in[1].getInt(sc)));
  152. registerFunction("math.round", (sc, in) -> (double) Math.round(in[0].getDouble(sc)));
  153. registerFunction("math.rounddown", (sc, in) -> Math.floor(in[0].getDouble(sc)));
  154. registerFunction("math.roundup", (sc, in) -> Math.ceil(in[0].getDouble(sc)));
  155. registerFunction("math.roundcomma", (sc, in) ->
  156. {
  157. double d = in[0].getDouble(sc);
  158. int factor = (int) Math.pow(10, in[1].getInt(sc));
  159. return (double) (((int) (d * factor)) / factor);
  160. });
  161. // ---------------------------------------------------------------------
  162. // lists
  163. // ---------------------------------------------------------------------
  164. registerFunction("list.new", (sc, in) ->
  165. {
  166. if(in.length == 0)
  167. {
  168. return new ArrayList<>();
  169. }
  170. in[0].set(sc, new ArrayList<>());
  171. return Void.TYPE;
  172. });
  173. registerFunction("list.exists", (sc, in) -> in[0].get(sc) instanceof List);
  174. registerFunction("list.add", (sc, in) -> ((List) in[0].get(sc)).add(in[1].get(sc)));
  175. registerFunction("list.addall", (sc, in) ->
  176. {
  177. List list = ((List) in[0].get(sc));
  178. for(int i = 1; i < in.length; i++)
  179. {
  180. list.add(in[i].get(sc));
  181. }
  182. return Void.TYPE;
  183. });
  184. registerFunction("list.remove", (sc, in) -> ((List) in[0].get(sc)).remove(in[1].get(sc)));
  185. registerFunction("list.removeindex", (sc, in) -> ((List) in[0].get(sc)).remove(in[1].getInt(sc)));
  186. registerFunction("list.contains", (sc, in) -> ((List) in[0].get(sc)).contains(in[1].get(sc)));
  187. registerFunction("list.getsize", (sc, in) -> (double) ((List) in[0].get(sc)).size());
  188. registerFunction("list.getindex", (sc, in) -> ((List) in[0].get(sc)).get(in[1].getInt(sc)));
  189. registerAlias("list.getindex", "list.get");
  190. registerFunction("list.setindex", (sc, in) -> ((List) in[0].get(sc)).set(in[1].getInt(sc), in[2].get(sc)));
  191. registerFunction("list.clear", (sc, in) ->
  192. {
  193. ((List) in[0].get(sc)).clear();
  194. return Void.TYPE;
  195. });
  196. registerFunction("list.getindexof", (sc, in) -> (double) ((List) in[0].get(sc)).indexOf(in[1].get(sc)));
  197. registerFunction("list.sort", (sc, in) ->
  198. {
  199. Collections.sort(((List<Object>) in[0].get(sc)), (Object o1, Object o2) -> ((Comparable) o1).compareTo(o2));
  200. return Void.TYPE;
  201. });
  202. registerFunction("list.reverse", (sc, in) ->
  203. {
  204. Collections.reverse((List<Object>) in[0].get(sc));
  205. return Void.TYPE;
  206. });
  207. registerFunction("list.shuffle", (sc, in) ->
  208. {
  209. Collections.shuffle((List<Object>) in[0].get(sc));
  210. return Void.TYPE;
  211. });
  212. // ---------------------------------------------------------------------
  213. // arrays
  214. // ---------------------------------------------------------------------
  215. registerFunction("array.new", (sc, in) ->
  216. {
  217. for(InputProvider input : in)
  218. {
  219. ((DynamicArray) input).init(sc);
  220. }
  221. return Void.TYPE;
  222. });
  223. registerFunction("array.getsize", (sc, in) -> (double) Array.getLength(in[0].getArray(sc)));
  224. /*
  225. registerFunction("array.swap", (sc, in) ->
  226. {
  227. Object[] o = (Object[]) args[0];
  228. int first = ScriptUtils.getInt(args[1]);
  229. int sec = ScriptUtils.getInt(args[2]);
  230. Object helper = o[first];
  231. o[first] = o[sec];
  232. o[sec] = helper;
  233. });
  234. registerFunction("array.sort", (sc, in) ->
  235. {
  236. if(args.length <= 1)
  237. {
  238. Arrays.sort((Object[]) args[0]);
  239. }
  240. else
  241. {
  242. Arrays.sort((Object[]) args[0], ScriptUtils.getInt(args[1]), ScriptUtils.getInt(args[2]));
  243. }
  244. });
  245. registerFunction("array.copy", (sc, in) ->
  246. {
  247. int first = ScriptUtils.getInt(args[2]);
  248. System.arraycopy((Object[]) args[0], first, (Object[]) args[1],
  249. ScriptUtils.getInt(args[4]), ScriptUtils.getInt(args[3]) - first + 1);
  250. });
  251. registerFunction("array.rsort", (sc, in) ->
  252. {
  253. if(args.length <= 1)
  254. {
  255. Arrays.sort((Object[]) args[0], (Object o, Object o1) -> -((Comparable) o).compareTo(o));
  256. }
  257. else
  258. {
  259. Arrays.sort((Object[]) args[0], ScriptUtils.getInt(args[1]),
  260. ScriptUtils.getInt(args[2]), (Object o, Object o1) -> -((Comparable) o).compareTo(o));
  261. }
  262. });
  263. registerFunction("array.fill", (sc, in) ->
  264. {
  265. if(args.length <= 2)
  266. {
  267. Arrays.fill((Object[]) args[0], args[1]);
  268. }
  269. else
  270. {
  271. Arrays.fill((Object[]) args[0], ScriptUtils.getInt(args[2]), ScriptUtils.getInt(args[3]), args[1]);
  272. }
  273. });*/
  274. // ---------------------------------------------------------------------
  275. // maps
  276. // ---------------------------------------------------------------------
  277. registerFunction("map.new", (sc, in) ->
  278. {
  279. if(in.length == 0)
  280. {
  281. return new HashMap<>();
  282. }
  283. in[0].set(sc, new HashMap<>());
  284. return Void.TYPE;
  285. });
  286. registerFunction("map.exists", (sc, in) -> in[0].get(sc) instanceof Map);
  287. registerFunction("map.add", (sc, in) -> ((Map) in[0].get(sc)).put(in[1].get(sc), in[2].get(sc)));
  288. registerFunction("map.remove", (sc, in) -> ((Map) in[0].get(sc)).remove(in[1].get(sc)));
  289. registerFunction("map.contains", (sc, in) -> ((Map) in[0].get(sc)).containsKey(in[1].get(sc)));
  290. registerFunction("map.getsize", (sc, in) -> (double) ((Map) in[0].get(sc)).size());
  291. registerFunction("map.get", (sc, in) -> ((Map) in[0].get(sc)).get(in[1].get(sc)));
  292. registerFunction("map.getordefault", (sc, in) -> ((Map) in[0].get(sc)).getOrDefault(in[1].get(sc), in[2].get(sc)));
  293. registerFunction("map.clear", (sc, in) ->
  294. {
  295. ((Map) in[0].get(sc)).clear();
  296. return Void.TYPE;
  297. });
  298. registerFunction("map.keys", (sc, in) ->
  299. {
  300. in[0].set(sc, ((Map) in[1].get(sc)).keySet().stream().collect(Collectors.toList()));
  301. return Void.TYPE;
  302. });
  303. registerFunction("map.values", (sc, in) ->
  304. {
  305. in[0].set(sc, ((Map) in[1].get(sc)).values().stream().collect(Collectors.toList()));
  306. return Void.TYPE;
  307. });
  308. // ---------------------------------------------------------------------
  309. // sets
  310. // ---------------------------------------------------------------------
  311. registerFunction("set.new", (sc, in) ->
  312. {
  313. if(in.length == 0)
  314. {
  315. return new HashSet<>();
  316. }
  317. in[0].set(sc, new HashSet<>());
  318. return Void.TYPE;
  319. });
  320. registerFunction("set.exists", (sc, in) -> in[0].get(sc) instanceof Set);
  321. registerFunction("set.add", (sc, in) -> ((Set) in[0].get(sc)).add(in[1].get(sc)));
  322. registerFunction("set.addall", (sc, in) ->
  323. {
  324. Set set = ((Set) in[0].get(sc));
  325. for(int i = 1; i < in.length; i++)
  326. {
  327. set.add(in[i].get(sc));
  328. }
  329. return Void.TYPE;
  330. });
  331. registerFunction("set.remove", (sc, in) -> ((Set) in[0].get(sc)).remove(in[1].get(sc)));
  332. registerFunction("set.contains", (sc, in) -> ((Set) in[0].get(sc)).contains(in[1].get(sc)));
  333. registerFunction("set.getsize", (sc, in) -> (double) ((Set) in[0].get(sc)).size());
  334. registerFunction("set.tolist", (sc, in) ->
  335. {
  336. in[0].set(sc, ((Set) in[1].get(sc)).stream().collect(Collectors.toList()));
  337. return Void.TYPE;
  338. });
  339. // ---------------------------------------------------------------------
  340. // time
  341. // ---------------------------------------------------------------------
  342. registerFunction("time.new", (sc, in) ->
  343. {
  344. GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
  345. cal.setTimeInMillis(in[1].getLong(sc));
  346. in[0].set(sc, cal);
  347. return Void.TYPE;
  348. });
  349. registerFunction("time.getmillis", (sc, in) -> (double) System.currentTimeMillis());
  350. registerFunction("time.getnanos", (sc, in) -> (double) System.nanoTime());
  351. registerFunction("time.from", (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).getTimeInMillis());
  352. registerFunction("time.nextday", (sc, in) ->
  353. {
  354. GregorianCalendar cal = (GregorianCalendar) in[0].get(sc);
  355. cal.add(Calendar.DAY_OF_YEAR, 1);
  356. cal.set(Calendar.HOUR, 0);
  357. cal.set(Calendar.SECOND, 0);
  358. cal.set(Calendar.MINUTE, 0);
  359. cal.set(Calendar.MILLISECOND, 0);
  360. return Void.TYPE;
  361. });
  362. registerFunction("time.getyear", (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.YEAR));
  363. registerFunction("time.getmonth", (sc, in) -> (double) (((GregorianCalendar) in[0].get(sc)).get(Calendar.MONTH) + 1));
  364. registerFunction("time.getday", (sc, in) -> (double) (((GregorianCalendar) in[0].get(sc)).get(Calendar.DAY_OF_MONTH)));
  365. registerFunction("time.gethour", (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.HOUR_OF_DAY));
  366. registerFunction("time.getminute", (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.MINUTE));
  367. registerFunction("time.getsecond", (sc, in) -> (double) ((GregorianCalendar) in[0].get(sc)).get(Calendar.SECOND));
  368. // ---------------------------------------------------------------------
  369. // text
  370. // ---------------------------------------------------------------------
  371. registerFunction("text.matches", (sc, in) -> in[0].getString(sc).matches(in[1].getString(sc)));
  372. registerFunction("text.number", (sc, in) -> SnuviUtils.toString(in[0].getDouble(sc)));
  373. registerFunction("text.class", (sc, in) -> in[0].get(sc).getClass().getSimpleName());
  374. registerFunction("text.tolowercase", (sc, in) -> SnuviUtils.connect(sc, in, 0).toLowerCase());
  375. registerAlias("text.tolowercase", "tolowercase");
  376. registerFunction("text.touppercase", (sc, in) -> SnuviUtils.connect(sc, in, 0).toUpperCase());
  377. registerAlias("text.touppercase", "touppercase");
  378. registerFunction("text.split", (sc, in) ->
  379. {
  380. String[] parts = SnuviUtils.connect(sc, in, 2).split(in[1].getString(sc));
  381. ArrayList<Object> list = new ArrayList<>();
  382. for(String part : parts)
  383. {
  384. list.add(Compiler.convert(part));
  385. }
  386. in[0].set(sc, list);
  387. return Void.TYPE;
  388. });
  389. registerAlias("text.split", "split");
  390. registerFunction("text.concatlist", (sc, in) ->
  391. {
  392. StringBuilder sb = new StringBuilder();
  393. List<Object> list = (List<Object>) in[0].get(sc);
  394. String splitter = in[1].getString(sc);
  395. Iterator<Object> iter = list.iterator();
  396. int from = in[2].getInt(sc);
  397. int to = Math.min(in[3].getInt(sc), list.size() - 1);
  398. to -= from;
  399. while(iter.hasNext() && from > 0)
  400. {
  401. iter.next();
  402. from--;
  403. }
  404. while(iter.hasNext() && to > 0)
  405. {
  406. sb.append(iter.next());
  407. sb.append(splitter);
  408. to--;
  409. }
  410. if(iter.hasNext() && to == 0)
  411. {
  412. sb.append(iter.next());
  413. }
  414. return sb.toString();
  415. });
  416. registerAlias("text.concatlist", "concatlist");
  417. registerFunction("text.concat", (sc, in) -> SnuviUtils.connect(sc, in, 0));
  418. registerAlias("text.concat", "concat");
  419. registerFunction("text", (sc, in) -> String.valueOf(in[0].get(sc)));
  420. registerFunction("text.substring", (sc, in) -> in[0].getString(sc).substring(in[1].getInt(sc), in[2].getInt(sc)));
  421. registerFunction("text.length", (sc, in) -> (double) in[0].getString(sc).length());
  422. registerFunction("text.startswith", (sc, in) -> in[0].getString(sc).startsWith(in[1].getString(sc), in[2].getInt(sc)));
  423. registerFunction("text.endswith", (sc, in) -> in[0].getString(sc).endsWith(in[1].getString(sc)));
  424. registerFunction("text.contains", (sc, in) -> in[0].getString(sc).contains(in[1].getString(sc)));
  425. registerFunction("text.indexof", (sc, in) -> in[0].getString(sc).indexOf(in[1].getString(sc), in[2].getInt(sc)));
  426. registerFunction("text.lastindexof", (sc, in) -> in[0].getString(sc).lastIndexOf(in[1].getString(sc), in[2].getInt(sc)));
  427. registerFunction("text.replace", (sc, in) -> in[0].getString(sc).replace(in[1].getString(sc), in[2].getString(sc)));
  428. registerFunction("text.trim", (sc, in) -> in[0].getString(sc).trim());
  429. registerFunction("text.charat", (sc, in) -> String.valueOf(in[0].getString(sc).charAt(in[1].getInt(sc))));
  430. registerFunction("text.charcode", (sc, in) -> (double) in[0].getString(sc).charAt(in[1].getInt(sc)));
  431. registerFunction("text.fromcode", (sc, in) -> String.valueOf((char) in[0].getInt(sc)));
  432. // -------------------------------------------------------------------------------
  433. // files
  434. // -------------------------------------------------------------------------------
  435. registerFunction("file.new", (sc, in) ->
  436. {
  437. in[0].set(sc, new File(in[1].getString(sc)));
  438. return Void.TYPE;
  439. });
  440. registerFunction("file.exists", (sc, in) -> ((File) in[0].get(sc)).exists());
  441. registerFunction("file.delete", (sc, in) -> ((File) in[0].get(sc)).delete());
  442. registerFunction("file.getname", (sc, in) -> ((File) in[0].get(sc)).getName());
  443. registerFunction("file.getlist", (sc, in) ->
  444. {
  445. in[0].set(sc, Arrays.asList(((File) in[0].get(sc)).listFiles()));
  446. return Void.TYPE;
  447. });
  448. registerFunction("file.read", (sc, in) ->
  449. {
  450. try
  451. {
  452. in[0].set(sc, Files.readAllLines(((File) in[1].get(sc)).toPath()));
  453. }
  454. catch(IOException ex)
  455. {
  456. throw new FileIOException(ex.getMessage());
  457. }
  458. return Void.TYPE;
  459. });
  460. registerFunction("file.write", (sc, in) ->
  461. {
  462. try
  463. {
  464. File f = (File) in[0].get(sc);
  465. if(f.getParentFile() != null)
  466. {
  467. f.getParentFile().mkdirs();
  468. }
  469. if(!f.exists())
  470. {
  471. try
  472. {
  473. f.createNewFile();
  474. }
  475. catch(IOException ex)
  476. {
  477. throw new FileIOException(ex.getMessage());
  478. }
  479. }
  480. Files.write(Paths.get(f.toURI()), ((List<Object>) in[1].get(sc))
  481. .stream().map(o -> String.valueOf(o)).collect(Collectors.toList()), StandardCharsets.UTF_8);
  482. }
  483. catch(UnsupportedOperationException | SecurityException | IOException ex)
  484. {
  485. throw new FileIOException(ex.getMessage());
  486. }
  487. return Void.TYPE;
  488. });
  489. // ---------------------------------------------------------------------
  490. // config
  491. // ---------------------------------------------------------------------
  492. registerFunction("config.new", (sc, in) ->
  493. {
  494. in[0].set(sc, new SnuviConfig(sc, in[1].getString(sc), in[2].getString(sc)));
  495. return Void.TYPE;
  496. });
  497. registerFunction("config.exists", (sc, in) -> ((SnuviConfig) in[0].get(sc)).exists());
  498. registerFunction("config.save", (sc, in) -> ((SnuviConfig) in[0].get(sc)).save());
  499. registerFunction("config.load", (sc, in) ->
  500. {
  501. ((SnuviConfig) in[0].get(sc)).load();
  502. return Void.TYPE;
  503. });
  504. registerFunction("config.delete", (sc, in) -> ((SnuviConfig) in[0].get(sc)).delete());
  505. registerFunction("config.set", (sc, in) ->
  506. {
  507. ((SnuviConfig) in[0].get(sc)).set(in[1].getString(sc), in[2].get(sc));
  508. return Void.TYPE;
  509. });
  510. registerFunction("config.getbool", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getBoolean(in[1].getString(sc), in[2].getBoolean(sc)));
  511. registerFunction("config.getdouble", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getDouble(in[1].getString(sc), in[2].getDouble(sc)));
  512. registerFunction("config.getstring", (sc, in) -> ((SnuviConfig) in[0].get(sc)).getString(in[1].getString(sc), in[2].getString(sc)));
  513. // ---------------------------------------------------------------------
  514. // commands without library
  515. // ---------------------------------------------------------------------
  516. // elementary calculating
  517. registerFunction("+", (sc, in) -> in[0].getDouble(sc) + in[1].getDouble(sc));
  518. registerAlias("+", "add");
  519. registerFunction("-", (sc, in) -> in[0].getDouble(sc) - in[1].getDouble(sc));
  520. registerAlias("-", "sub");
  521. registerFunction("*", (sc, in) -> in[0].getDouble(sc) * in[1].getDouble(sc));
  522. registerAlias("*", "mul");
  523. registerFunction("/", (sc, in) -> in[0].getDouble(sc) / in[1].getDouble(sc));
  524. registerAlias("/", "div");
  525. // var setter
  526. registerFunction("=", (sc, in) ->
  527. {
  528. Object o = in[1].get(sc);
  529. in[0].set(sc, o);
  530. return o;
  531. });
  532. registerFunction("+=", (sc, in) ->
  533. {
  534. Object o = in[0].getDouble(sc) + in[1].getDouble(sc);
  535. in[0].set(sc, o);
  536. return o;
  537. });
  538. registerFunction("p++", (sc, in) ->
  539. {
  540. double d = in[0].getDouble(sc);
  541. in[0].set(sc, d + 1.0);
  542. return d;
  543. });
  544. registerAlias("p++", "inc");
  545. registerFunction("++", (sc, in) ->
  546. {
  547. double d = in[0].getDouble(sc) + 1.0;
  548. in[0].set(sc, d);
  549. return d;
  550. });
  551. registerFunction("-=", (sc, in) ->
  552. {
  553. Object o = in[0].getDouble(sc) - in[1].getDouble(sc);
  554. in[0].set(sc, o);
  555. return o;
  556. });
  557. registerFunction("p--", (sc, in) ->
  558. {
  559. double d = in[0].getDouble(sc);
  560. in[0].set(sc, d - 1.0);
  561. return d;
  562. });
  563. registerAlias("p--", "dec");
  564. registerFunction("--", (sc, in) ->
  565. {
  566. double d = in[0].getDouble(sc) - 1.0;
  567. in[0].set(sc, d);
  568. return d;
  569. });
  570. registerFunction("*=", (sc, in) ->
  571. {
  572. Object o = in[0].getDouble(sc) * in[1].getDouble(sc);
  573. in[0].set(sc, o);
  574. return o;
  575. });
  576. registerFunction("/=", (sc, in) ->
  577. {
  578. Object o = in[0].getDouble(sc) / in[1].getDouble(sc);
  579. in[0].set(sc, o);
  580. return o;
  581. });
  582. registerFunction("%=", (sc, in) ->
  583. {
  584. Object o = (double) (in[0].getInt(sc) % in[1].getInt(sc));
  585. in[0].set(sc, o);
  586. return o;
  587. });
  588. registerFunction("<<=", (sc, in) ->
  589. {
  590. Object o = (double) (in[0].getInt(sc) << in[1].getInt(sc));
  591. in[0].set(sc, o);
  592. return o;
  593. });
  594. registerFunction(">>=", (sc, in) ->
  595. {
  596. Object o = (double) (in[0].getInt(sc) >> in[1].getInt(sc));
  597. in[0].set(sc, o);
  598. return o;
  599. });
  600. registerFunction("&=", (sc, in) ->
  601. {
  602. Object o = (double) (in[0].getInt(sc) & in[1].getInt(sc));
  603. in[0].set(sc, o);
  604. return o;
  605. });
  606. registerFunction("^=", (sc, in) ->
  607. {
  608. Object o = (double) (in[0].getInt(sc) ^ in[1].getInt(sc));
  609. in[0].set(sc, o);
  610. return o;
  611. });
  612. registerFunction("|=", (sc, in) ->
  613. {
  614. Object o = (double) (in[0].getInt(sc) | in[1].getInt(sc));
  615. in[0].set(sc, o);
  616. return o;
  617. });
  618. // var stuff
  619. registerFunction("getvar", (sc, in) -> sc.getVar(in[0].getString(sc)).get(sc));
  620. registerFunction("setvar", (sc, in) ->
  621. {
  622. sc.getVar(in[0].getString(sc)).set(sc, in[1].get(sc));
  623. return Void.TYPE;
  624. });
  625. registerFunction("removevar", (sc, in) ->
  626. {
  627. sc.getVar(in[0].getString(sc)).set(sc, null);
  628. return Void.TYPE;
  629. });
  630. registerFunction("wait", (sc, in) ->
  631. {
  632. sc.isWaiting = true;
  633. return Void.TYPE;
  634. });
  635. // try - catch
  636. registerFunction("try", (sc, in) ->
  637. {
  638. sc.catchLine = sc.currentLine + in[0].getInt(sc);
  639. return Void.TYPE;
  640. });
  641. registerFunction("catch", (sc, in) ->
  642. {
  643. if(sc.catchLine != -1)
  644. {
  645. sc.currentLine += in[0].getInt(sc);
  646. }
  647. return Void.TYPE;
  648. });
  649. // branching
  650. registerFunction("goto", (sc, in) ->
  651. {
  652. sc.currentLine = sc.labels.get(in[0].getString(sc));
  653. return Void.TYPE;
  654. });
  655. registerFunction("ignoregoto", (sc, in) ->
  656. {
  657. Integer i = sc.labels.get(in[0].getString(sc));
  658. if(i != null)
  659. {
  660. sc.currentLine = i;
  661. }
  662. return Void.TYPE;
  663. });
  664. registerFunction("sgoto", (sc, in) ->
  665. {
  666. if(sc.subScript)
  667. {
  668. throw new IllegalStateException("sgoto is not allowed in functions");
  669. }
  670. int time = in[0].getInt(sc);
  671. if(time < 0)
  672. {
  673. throw new IllegalArgumentException("time units can't be negative");
  674. }
  675. int label = sc.labels.get(in[1].getString(sc));
  676. sc.scheduler.scheduleTask(() ->
  677. {
  678. if(!sc.isValid || sc.isHolded)
  679. {
  680. return;
  681. }
  682. sc.currentLine = label + 1;
  683. sc.run();
  684. }, time);
  685. return Void.TYPE;
  686. });
  687. registerFunction("gosub", (sc, in) ->
  688. {
  689. sc.returnStack.push(sc.currentLine);
  690. sc.currentLine = sc.labels.get(in[0].getString(sc));
  691. return Void.TYPE;
  692. });
  693. registerFunction("return", (sc, in) ->
  694. {
  695. if(sc.returnStack.isEmpty())
  696. {
  697. sc.end();
  698. sc.returnValue = in.length > 0 ? in[0].get(sc) : null;
  699. }
  700. else
  701. {
  702. sc.currentLine = sc.returnStack.pop();
  703. }
  704. return Void.TYPE;
  705. });
  706. registerFunction("if", (sc, in) ->
  707. {
  708. sc.ifState = in[0].getBoolean(sc);
  709. if(!sc.ifState)
  710. {
  711. sc.currentLine += in[1].getInt(sc);
  712. }
  713. return Void.TYPE;
  714. });
  715. registerFunction("endif", (sc, in) ->
  716. {
  717. sc.ifState = true;
  718. return Void.TYPE;
  719. });
  720. registerFunction("elseif", (sc, in) ->
  721. {
  722. if(sc.ifState)
  723. {
  724. sc.currentLine += in[1].getInt(sc);
  725. }
  726. else
  727. {
  728. sc.ifState = in[0].getBoolean(sc);
  729. if(!sc.ifState)
  730. {
  731. sc.currentLine += in[1].getInt(sc);
  732. }
  733. }
  734. return Void.TYPE;
  735. });
  736. registerFunction("else", (sc, in) ->
  737. {
  738. if(sc.ifState)
  739. {
  740. sc.currentLine += in[0].getInt(sc);
  741. }
  742. sc.ifState = true;
  743. return Void.TYPE;
  744. });
  745. registerFunction("while", (sc, in) ->
  746. {
  747. if(!in[0].getBoolean(sc))
  748. {
  749. sc.currentLine += in[1].getInt(sc);
  750. }
  751. return Void.TYPE;
  752. });
  753. registerFunction("wend", (sc, in) ->
  754. {
  755. sc.currentLine += in[0].getInt(sc);
  756. return Void.TYPE;
  757. });
  758. registerFunction("for", (sc, in) ->
  759. {
  760. // for(var, start, end, step)
  761. double start = in[1].getDouble(sc);
  762. in[0].set(sc, start);
  763. if(start > in[2].getDouble(sc))
  764. {
  765. sc.currentLine += in[4].getInt(sc);
  766. }
  767. return Void.TYPE;
  768. });
  769. registerFunction("next", (sc, in) ->
  770. {
  771. int line = sc.currentLine + in[0].getInt(sc);
  772. InputProvider[] f = sc.code[line].getArguments();
  773. // for(var, start, end, step)
  774. double current = f[0].getDouble(sc) + f[3].getDouble(sc);
  775. f[0].set(sc, current);
  776. if(current <= f[2].getDouble(sc))
  777. {
  778. sc.currentLine = line;
  779. }
  780. return Void.TYPE;
  781. });
  782. registerFunction("continue", (sc, in) ->
  783. {
  784. sc.currentLine += in[0].getInt(sc);
  785. return Void.TYPE;
  786. });
  787. registerFunction("break", (sc, in) ->
  788. {
  789. sc.currentLine += in[0].getInt(sc);
  790. return Void.TYPE;
  791. });
  792. // comparing
  793. registerFunction("==", (sc, in) -> Objects.equals(in[0].get(sc), in[1].get(sc)));
  794. registerAlias("==", "equal");
  795. registerAlias("==", "equals");
  796. registerFunction("!=", (sc, in) -> !Objects.equals(in[0].get(sc), in[1].get(sc)));
  797. registerAlias("!=", "notequal");
  798. registerFunction("<", (sc, in) -> in[0].getDouble(sc) < in[1].getDouble(sc));
  799. registerAlias("<", "less");
  800. registerFunction(">", (sc, in) -> in[0].getDouble(sc) > in[1].getDouble(sc));
  801. registerAlias(">", "greater");
  802. registerFunction("<=", (sc, in) -> in[0].getDouble(sc) <= in[1].getDouble(sc));
  803. registerAlias("<=", "lessequal");
  804. registerFunction(">=", (sc, in) -> in[0].getDouble(sc) >= in[1].getDouble(sc));
  805. registerAlias(">=", "greaterequal");
  806. registerFunction("!", (sc, in) -> !in[0].getBoolean(sc));
  807. registerAlias("!", "invert");
  808. // logical stuff
  809. registerFunction("&&", (sc, in) ->
  810. {
  811. for(InputProvider i : in)
  812. {
  813. if(!i.getBoolean(sc))
  814. {
  815. return false;
  816. }
  817. }
  818. return true;
  819. });
  820. registerAlias("&&", "and");
  821. registerFunction("||", (sc, in) ->
  822. {
  823. for(InputProvider i : in)
  824. {
  825. if(i.getBoolean(sc))
  826. {
  827. return true;
  828. }
  829. }
  830. return false;
  831. });
  832. registerAlias( "||", "or");
  833. // non grouped stuff
  834. registerFunction("swap", (sc, in) ->
  835. {
  836. Object o = in[0].get(sc);
  837. in[0].set(sc, in[1].get(sc));
  838. in[1].set(sc, o);
  839. return Void.TYPE;
  840. });
  841. registerFunction("print", (sc, in) ->
  842. {
  843. System.out.println(SnuviUtils.connect(sc, in, 0));
  844. return Void.TYPE;
  845. });
  846. registerFunction("waitfor", (sc, in) ->
  847. {
  848. if(sc.subScript)
  849. {
  850. throw new IllegalStateException("waitfor is not allowed in functions");
  851. }
  852. long l = in[0].getInt(sc);
  853. if(l < 0)
  854. {
  855. throw new IllegalArgumentException("time units can't be negative");
  856. }
  857. sc.isHolded = true;
  858. sc.scheduler.scheduleTask(() ->
  859. {
  860. // activate this again on NullPointerException
  861. // if(sc == null || !sc.isValid)
  862. if(sc.isValid)
  863. {
  864. sc.isHolded = false;
  865. sc.run();
  866. }
  867. }, l);
  868. sc.isWaiting = true;
  869. return Void.TYPE;
  870. });
  871. registerFunction("term", (sc, in) ->
  872. {
  873. sc.parser.termSafe(sc);
  874. return Void.TYPE;
  875. });
  876. registerFunction("islong", (sc, in) ->
  877. {
  878. Object o = in[0].get(sc);
  879. if(o instanceof Double)
  880. {
  881. double d = (Double) o;
  882. return d == (long) d;
  883. }
  884. return false;
  885. });
  886. registerFunction("assert", (sc, in) ->
  887. {
  888. if(!in[0].getBoolean(sc))
  889. {
  890. throw new AssertionException("assertion failed");
  891. }
  892. return Void.TYPE;
  893. });
  894. registerFunction("class", (sc, in) -> in[0].get(sc).getClass());
  895. }
  896. }