Script.java 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. package me.hammerle.code;
  2. import java.util.ArrayList;
  3. import java.util.Arrays;
  4. import java.util.HashMap;
  5. import java.util.HashSet;
  6. import java.util.List;
  7. import java.util.Stack;
  8. import me.hammerle.exceptions.CodeTooLongException;
  9. import me.hammerle.exceptions.GotoLabelNotFoundException;
  10. import me.hammerle.exceptions.HoldCodeException;
  11. import me.hammerle.exceptions.SnuviException;
  12. public class Script
  13. {
  14. private final SnuviParser parser;
  15. protected final boolean receiveEventBroadcast;
  16. protected final ArrayList<String> eventVars;
  17. private final int id;
  18. private final String name;
  19. private final HashMap<String, Object> variables;
  20. private final HashMap<String, Integer> gotos;
  21. private final HashSet<String> events;
  22. private final Stack<Object> valueStack;
  23. private final Stack<Integer> returnStack;
  24. private Code[] code;
  25. private int position;
  26. private int loopCounter;
  27. private boolean halt;
  28. private boolean valid;
  29. private int tryJumpLine;
  30. public Script(SnuviParser parser, int id, String name, String code, boolean receiveEventBroadcast)
  31. {
  32. this.eventVars = new ArrayList<>();
  33. this.receiveEventBroadcast = receiveEventBroadcast;
  34. this.parser = parser;
  35. this.id = id;
  36. this.name = name;
  37. variables = new HashMap<>();
  38. gotos = new HashMap<>();
  39. events = new HashSet<>();
  40. valueStack = new Stack<>();
  41. returnStack = new Stack<>();
  42. this.code = Code.generate(parser, name, code, gotos);
  43. /*for(Code c : this.code)
  44. {
  45. System.out.println(c);
  46. }*/
  47. position = 0;
  48. loopCounter = 0;
  49. halt = false;
  50. valid = true;
  51. tryJumpLine = -1;
  52. }
  53. public Script(SnuviParser parser, int id, String name, String code)
  54. {
  55. this(parser, id, name, code, true);
  56. }
  57. protected void initExpansion(Object... o)
  58. {
  59. }
  60. public void overload(String code)
  61. {
  62. gotos.clear();
  63. valueStack.clear();
  64. returnStack.clear();
  65. this.code = Code.generate(parser, name, code, gotos);
  66. position = 0;
  67. halt = false;
  68. valid = true;
  69. tryJumpLine = -1;
  70. }
  71. public Code[] getCode(int line)
  72. {
  73. int start = 0;
  74. int end = code.length;
  75. int helper;
  76. while(end - start > 1)
  77. {
  78. helper = (start + end) >> 1;
  79. if(code[helper].line > line)
  80. {
  81. end = helper;
  82. }
  83. else if(code[helper].line <= line)
  84. {
  85. start = helper;
  86. }
  87. }
  88. int realEnd = start;
  89. start = 0;
  90. end = code.length;
  91. while(end - start > 1)
  92. {
  93. helper = (start + end) >> 1;
  94. if(code[helper].line >= line)
  95. {
  96. end = helper;
  97. }
  98. else if(code[helper].line < line)
  99. {
  100. start = helper;
  101. }
  102. }
  103. return Arrays.copyOfRange(code, end, realEnd + 1);
  104. }
  105. // -----------------------------------------------------------------------------------
  106. // Script-Daten
  107. // -----------------------------------------------------------------------------------
  108. public int getId()
  109. {
  110. return id;
  111. }
  112. public String getName()
  113. {
  114. return name;
  115. }
  116. public boolean isHalt()
  117. {
  118. return halt;
  119. }
  120. public void setHalt(boolean b)
  121. {
  122. halt = b;
  123. }
  124. public boolean isValid()
  125. {
  126. return valid;
  127. }
  128. public void setInvalid()
  129. {
  130. valid = false;
  131. }
  132. public int getActiveCodeLine()
  133. {
  134. return code[position].line;
  135. }
  136. // -----------------------------------------------------------------------------------
  137. // Event-Handling
  138. // -----------------------------------------------------------------------------------
  139. public void loadEvent(String s)
  140. {
  141. events.add(s);
  142. }
  143. public boolean isLoadedEvent(String s)
  144. {
  145. return events.contains(s);
  146. }
  147. public void unloadEvent(String s)
  148. {
  149. events.remove(s);
  150. }
  151. // -----------------------------------------------------------------------------------
  152. // Script-Flow
  153. // -----------------------------------------------------------------------------------
  154. public void onTerm()
  155. {
  156. }
  157. public void runCode()
  158. {
  159. if(this.isValid())
  160. {
  161. try
  162. {
  163. while(position < code.length)
  164. {
  165. code[position].executeFunction(parser, this, valueStack);
  166. position++;
  167. if(isHalt())
  168. {
  169. return;
  170. }
  171. }
  172. parser.termSafe(this);
  173. }
  174. catch(Exception ex)
  175. {
  176. if(ex.getClass() != HoldCodeException.class)
  177. {
  178. parser.logger.printException(new SnuviException(ex, this));
  179. }
  180. position++;
  181. }
  182. }
  183. }
  184. // -----------------------------------------------------------------------------------
  185. // Variablen
  186. // -----------------------------------------------------------------------------------
  187. public void setEventVar(String var, Object value)
  188. {
  189. variables.put(var, value);
  190. eventVars.add(var);
  191. }
  192. public void setVar(String var, Object value)
  193. {
  194. variables.put(var, value);
  195. }
  196. public Object getVar(String var)
  197. {
  198. return variables.get(var);
  199. }
  200. public HashMap<String, Object> getVars()
  201. {
  202. return variables;
  203. }
  204. public boolean getBooleanVar(String var)
  205. {
  206. try
  207. {
  208. return (boolean) getVar(var);
  209. }
  210. catch(ClassCastException | NullPointerException ex)
  211. {
  212. return false;
  213. }
  214. }
  215. public void removeVar(String var)
  216. {
  217. variables.remove(var);
  218. }
  219. // -----------------------------------------------------------------------------------
  220. // Goto, Return
  221. // -----------------------------------------------------------------------------------
  222. public void incLoopCounter()
  223. {
  224. loopCounter++;
  225. if(loopCounter > 50)
  226. {
  227. resetLoopCounter();
  228. throw new CodeTooLongException(this);
  229. }
  230. }
  231. public void gotoLabel(String label)
  232. {
  233. try
  234. {
  235. int i = gotos.get(label);
  236. incLoopCounter();
  237. position = i - 1;
  238. }
  239. catch(NullPointerException ex)
  240. {
  241. throw new GotoLabelNotFoundException(this, label);
  242. }
  243. }
  244. public void resetLoopCounter()
  245. {
  246. loopCounter = 0;
  247. }
  248. public void gotoLabelWithReturn(String label)
  249. {
  250. returnStack.push(position);
  251. gotoLabel(label);
  252. }
  253. public void doReturn()
  254. {
  255. position = returnStack.pop();
  256. }
  257. public void gotoSpecialJumpLine(int i)
  258. {
  259. position += code[position].getJumpLine() + i;
  260. }
  261. public void gotoSpecialJumpLine()
  262. {
  263. gotoSpecialJumpLine(-1);
  264. }
  265. public void jumpNextIfElse()
  266. {
  267. if(code.length <= position + 1)
  268. {
  269. return;
  270. }
  271. String s = code[position + 1].getFunction();
  272. if(s == null || !s.equals("else"))
  273. {
  274. return;
  275. }
  276. position++;
  277. }
  278. // -----------------------------------------------------------------------------------
  279. // try
  280. // -----------------------------------------------------------------------------------
  281. public void gotoTryJumpLine()
  282. {
  283. position = tryJumpLine;
  284. }
  285. public void saveTryJumpLine()
  286. {
  287. tryJumpLine = position + code[position].getJumpLine();
  288. }
  289. public void resetTryJumpLine()
  290. {
  291. tryJumpLine = -1;
  292. }
  293. public int getTryJumpLine()
  294. {
  295. return tryJumpLine;
  296. }
  297. }