FunctionLoader.java 37 KB

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