123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448 |
- package me.hammerle.code;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.HashMap;
- import java.util.HashSet;
- import java.util.Stack;
- import java.util.TreeMap;
- import me.hammerle.exceptions.CodeTooLongException;
- import me.hammerle.exceptions.GotoLabelNotFoundException;
- import me.hammerle.exceptions.HoldCodeException;
- import me.hammerle.exceptions.PreScriptException;
- import me.hammerle.math.Fraction;
- public class Script
- {
- private final SnuviParser parser;
- protected final boolean receiveEventBroadcast;
- protected final ArrayList<String> eventVars;
-
- private final int id;
- private final String name;
- private final HashMap<String, Object> variables;
- private final HashMap<String, Integer> gotos;
- private final HashSet<String> events;
- private final Stack<Object> valueStack;
- private final Stack<Object> functionStack;
- private final Stack<Integer> returnStack;
- private final TreeMap<Integer, Fraction> forMap;
-
- private Code[] code;
- private int position;
- private int loopCounter;
-
-
- private boolean halt;
- private boolean isRunning;
- private boolean valid;
-
- private int tryJumpLine;
-
- public Script(SnuviParser parser, int id, String name, String code, boolean receiveEventBroadcast)
- {
- this.eventVars = new ArrayList<>();
- this.receiveEventBroadcast = receiveEventBroadcast;
- this.parser = parser;
- this.id = id;
- this.name = name;
-
- variables = new HashMap<>();
- gotos = new HashMap<>();
- events = new HashSet<>();
- valueStack = new Stack<>();
- functionStack = new Stack<>();
- returnStack = new Stack<>();
- forMap = new TreeMap<>();
-
- this.code = Code.generate(parser, name, code, gotos);
- if(this.code.length == 0)
- {
- throw new PreScriptException(name, 0, "empty file");
- }
-
- position = 0;
- loopCounter = 0;
-
- halt = false;
- isRunning = false;
- valid = true;
-
- tryJumpLine = -1;
- }
-
- public Script(SnuviParser parser, int id, String name, String code)
- {
- this(parser, id, name, code, true);
- }
-
- protected void initExpansion(Object... o)
- {
-
- }
-
- public void overload(String code)
- {
- gotos.clear();
- valueStack.clear();
- functionStack.clear();
- returnStack.clear();
- forMap.clear();
- this.code = Code.generate(parser, name, code, gotos);
- position = -1;
- halt = false;
- valid = true;
- tryJumpLine = -1;
- }
-
- public Code[] getCode(int line)
- {
- line = code[line].realLine;
- int start = 0;
- int end = code.length;
- int helper;
- while(end - start > 1)
- {
- helper = (start + end) >> 1;
- if(code[helper].realLine > line)
- {
- end = helper;
- }
- else if(code[helper].realLine <= line)
- {
- start = helper;
- }
- }
- int realEnd = start;
- start = 0;
- end = code.length;
- while(end - start > 1)
- {
- helper = (start + end) >> 1;
- if(code[helper].realLine >= line)
- {
- end = helper;
- }
- else if(code[helper].realLine < line)
- {
- start = helper;
- }
- }
- return Arrays.copyOfRange(code, end, realEnd + 1);
- }
-
-
-
-
-
- public ISnuviLogger getLogger()
- {
- return parser.logger;
- }
-
- public int getId()
- {
- return id;
- }
- public String getName()
- {
- return name;
- }
-
- public boolean isHalt()
- {
- return halt;
- }
-
- public void setHalt(boolean b)
- {
- halt = b;
- }
-
- public boolean isRunning()
- {
- return isRunning;
- }
-
- public boolean isValid()
- {
- return valid;
- }
-
- public void setInvalid()
- {
- valid = false;
- }
-
- public int getActiveRealCodeLine()
- {
- if(position < 0 || position >= code.length)
- {
- return 0;
- }
- return code[position].realLine;
- }
-
-
-
-
-
- public void loadEvent(String s)
- {
- events.add(s);
- }
-
- public boolean isLoadedEvent(String s)
- {
- return events.contains(s);
- }
-
- public void unloadEvent(String s)
- {
- events.remove(s);
- }
-
-
-
-
-
- public void onTerm()
- {
- }
-
- public void runCode()
- {
- if(this.isValid())
- {
- try
- {
- isRunning = true;
- while(position < code.length)
- {
- code[position].executeFunction(parser, this, valueStack);
- position++;
- }
- isRunning = false;
- parser.termSafe(this);
- }
- catch(Exception ex)
- {
- isRunning = false;
- if(ex.getClass() != HoldCodeException.class)
- {
- parser.logger.printException(ex, code[position].function, this, getActiveRealCodeLine());
- }
- position++;
- }
- }
- }
-
-
-
-
-
- public void setEventVar(String var, Object value)
- {
- variables.put(var, value);
- eventVars.add(var);
- }
-
- public void setVar(String var, Object value)
- {
- variables.put(var, value);
- }
-
- public Object getVar(String var)
- {
- return variables.get(var);
- }
-
- public HashMap<String, Object> getVars()
- {
- return variables;
- }
-
- public boolean getBooleanVar(String var)
- {
- try
- {
- return (boolean) getVar(var);
- }
- catch(ClassCastException | NullPointerException ex)
- {
- return false;
- }
- }
-
- public void removeVar(String var)
- {
- variables.remove(var);
- }
-
-
-
-
-
- public void incLoopCounter()
- {
- loopCounter++;
- if(loopCounter > 50)
- {
- resetLoopCounter();
- throw new CodeTooLongException();
- }
- }
-
- public void gotoLabel(String label, boolean scheduled, boolean resetFor)
- {
- Integer i = gotos.get(label);
- if(i == null)
- {
- throw new GotoLabelNotFoundException(label);
- }
- if(resetFor)
- {
- forMap.clear();
- }
- incLoopCounter();
- position = i - (scheduled ? 0 : 1);
- }
-
- public void resetLoopCounter()
- {
- loopCounter = 0;
- }
-
- public void gotoLabelWithReturn(String label)
- {
- returnStack.push(position);
- gotoLabel(label, false, false);
- }
-
- public void doReturn()
- {
- position = returnStack.pop();
- }
-
- public void jump()
- {
- position += (int) code[position].value;
- }
-
- public void jumpDoElse()
- {
- position += (int) code[position].value;
- if(code.length <= position + 1)
- {
- return;
- }
- if("else".equals(code[position + 1].function))
- {
- position++;
- }
- }
-
-
-
-
-
- public void gotoTryJumpLine()
- {
- position = tryJumpLine;
- }
-
- public void saveTryJumpLine()
- {
- tryJumpLine = position + ((int) code[position].value) + 1;
- if(!"catch".equals(code[tryJumpLine].function))
- {
- throw new IllegalStateException("try without catch");
- }
- }
-
- public void resetTryJumpLine()
- {
- tryJumpLine = -1;
- }
-
- public int getTryJumpLine()
- {
- return tryJumpLine;
- }
-
-
-
-
-
- public boolean repeatFinished(Fraction value, Fraction step, Fraction border)
- {
- return (step.isNegative() && border.compareTo(value) > 0) || border.compareTo(value) < 0;
- }
-
- public Fraction nextRepeatData(Fraction start, Fraction step)
- {
- Fraction f = forMap.get(position);
- if(f == null)
- {
- forMap.put(position, start);
- return start;
- }
- f = f.add(step);
- forMap.put(position, f);
- return f;
- }
-
- public void clearRepeatData()
- {
- forMap.remove(position);
- }
-
- public void clearLastRepeatData()
- {
- forMap.pollLastEntry();
- }
-
-
-
-
-
- public void pushFunctionInput(Object[] o)
- {
- for(Object ob : o)
- {
- valueStack.push(ob);
- }
- }
-
- public void pushFunctionInput(Object[] o, Fraction f)
- {
- pushFunctionInput(o);
- valueStack.push(f);
- }
-
- public Object popFunctionInput()
- {
- return valueStack.pop();
- }
-
- public void push(int start, Object... o)
- {
- for(int i = start; i < o.length; i++)
- {
- functionStack.push(o[i]);
- }
- }
-
- public void pop(Object... o)
- {
- for(int i = o.length - 1; i >= 0; i--)
- {
- setVar(o[i].toString(), functionStack.pop());
- }
- }
- }
|