1 package de.lathanda.eos.vm;
 
    3 import de.lathanda.eos.base.event.CleanupListener;
 
    4 import de.lathanda.eos.vm.exceptions.MemoryAccessViolation;
 
    5 import de.lathanda.eos.vm.exceptions.ProgramTerminationException;
 
    7 import java.util.ArrayList;
 
    8 import java.util.LinkedList;
 
   10 import java.util.Map.Entry;
 
   11 import java.util.TreeMap;
 
   21     private final LinkedList<Object> stack;
 
   22     private final LinkedList<Context> callstack;
 
   26     private Context context;
 
   30     private Context global;
 
   31     private final TreeMap<String, MProcedure> userfunction;
 
   32     private final Executer executer = 
new Executer();
 
   33     private final SpeedExecuter speedexecuter = 
new SpeedExecuter();
 
   35     private volatile boolean executing = 
false;
 
   36     private volatile boolean running = 
false;
 
   37     private volatile boolean isStarting = 
true;
 
   38     private volatile boolean isFinished = 
false;
 
   39     private volatile long delay = 5000;
 
   42     private final LinkedList<CleanupListener> gc = 
new LinkedList<>();
 
   43     private TreeMap<Integer, DebugPoint> breakpoints = 
new TreeMap<>();
 
   45     LinkedList<MachineListener> machineListeners = 
new LinkedList<>();
 
   48         stack = 
new LinkedList<>();
 
   49         callstack = 
new LinkedList<>();
 
   50         context = 
new Context();
 
   52         userfunction = 
new TreeMap<>();
 
   55         machineListeners.add(m);
 
   58         machineListeners.remove(m);
 
   77         if (!breakpoints.containsKey(linenumber)) {
 
   78             breakpoints.put(linenumber, debugPoint);
 
  101     private DebugPoint getDebugPoint(
int linenumber) {
 
  102         if (breakpoints.containsKey(linenumber)) {
 
  103             return breakpoints.get(linenumber);
 
  105             Map.Entry<Integer, DebugPoint> entry = breakpoints.higherEntry(linenumber);
 
  109                 return entry.getValue();
 
  115         userfunction.clear();
 
  116         global = 
new Context();
 
  120     private void reset() {
 
  132         gc.forEach(w -> w.terminate());
 
  139         if (stack.isEmpty()) {
 
  153     public Object 
get(String variable) {
 
  154         if (context.memory.containsKey(variable)) {
 
  155             return context.memory.get(variable).get();
 
  156         } 
else if (context.globalAccess && global.memory.containsKey(variable)) {
 
  157             return global.memory.get(variable).get();
 
  163     public void set(String variable, Object data) {
 
  164         if (context.memory.containsKey(variable)) {
 
  165             context.memory.get(variable).set(data);
 
  166         } 
else if (context.globalAccess && global.memory.containsKey(variable)) {
 
  167             global.memory.get(variable).set(data);
 
  174         LinkedList<MemoryEntry> result = 
new LinkedList<>();
 
  175         for (Entry<String, Variable> entry : global.memory.entrySet()) {
 
  179         if (context != global) {
 
  180             for (Entry<String, Variable> entry : context.memory.entrySet()) {
 
  188     public void jump(
int relativ) {
 
  189         context.index += relativ;
 
  192     public void create(String variable, 
MType type) 
throws Exception {
 
  194         context.memory.put(variable, v);
 
  197     public void define(String variable, 
MType type) 
throws Exception {
 
  199         context.memory.put(variable, v);
 
  204         if (!type.isAbstract()) {
 
  205             v.
set(type.newInstance(
this));
 
  213     public void create(String variable, 
MType type, Object data) 
throws Exception {
 
  216         context.memory.put(variable, v);
 
  219     private boolean microStep() throws Exception {
 
  220         Context actcontext = context;
 
  222             if (actcontext.program[actcontext.index].execute(
this)) {
 
  225         } 
catch (ArrayIndexOutOfBoundsException aiobe) {
 
  226             machineListeners.forEach((ml)->ml.missingProgram());
 
  227         } 
catch (ProgramTerminationException pte) {
 
  228             machineListeners.forEach((ml)->ml.handleError(pte));
 
  231         } 
catch (Exception e) {
 
  232             machineListeners.forEach((ml)->ml.handleOrThrowException(e));
 
  238     private boolean update() {
 
  240         while (context.program.length <= context.index) {
 
  241             if (callstack.size() == 0) {
 
  246                 context = callstack.pop();
 
  282         } 
catch (Exception e) {
 
  283             machineListeners.forEach((ml)->ml.handleException(e));
 
  287     private void messageStarting() {
 
  289             machineListeners.forEach((ml)->ml.startProgram());
 
  294     private void messageFinishing() {
 
  296             machineListeners.forEach((ml)->ml.stopProgram());
 
  301     public synchronized void skip() {
 
  305         new Thread(speedexecuter).start();
 
  308     private void debugStep() throws Exception {
 
  314         while (executing && running) {
 
  327     public synchronized void stop() {
 
  339     private boolean check() {
 
  340         return context.program != 
null;
 
  353         new Thread(executer).start();
 
  364     public void call(String signature) {
 
  370         callstack.push(context);
 
  371         context = 
new Context();
 
  372         context.program = proc.
getOps();
 
  379         userfunction.put(signature, proc);
 
  384             command.prepare(
this);
 
  386         context.program = 
new Command[ops.size()];
 
  387         context.program = ops.toArray(context.program);
 
  391     private class Context {
 
  393         public int index = 0;
 
  395         public boolean globalAccess;
 
  396         public TreeMap<String, Variable> memory = 
new TreeMap<>();
 
  398         public void reset() {
 
  404     private class Executer 
implements Runnable {
 
  407             long laststep = System.nanoTime();
 
  412                     int diff = (int) (laststep + delay - System.nanoTime());
 
  413                     if (diff > 1000000) {
 
  415                             Machine.this.wait(diff / 1000000);
 
  427             } 
catch (ProgramTerminationException pte) {
 
  430                 machineListeners.forEach((ml)->ml.handleError(pte));
 
  432             } 
catch (Exception e) {
 
  435                 machineListeners.forEach((ml)->ml.handleException(e));
 
  441     private class SpeedExecuter 
implements Runnable {
 
  454             } 
catch (ProgramTerminationException pte) {
 
  457                 machineListeners.forEach((ml)->ml.handleError(pte));
 
  459             } 
catch (Exception e) {
 
  462                 machineListeners.forEach((ml)->ml.handleException(e));
 
void setCodeRange(Marker codeRange)
void remove(DebugListener cl)
void fireDebugPoint(DebugInfo debug)
void add(DebugListener cl)
void setActiveBreakpoint(boolean activeBreakpoint)
boolean isActiveBreakpoint()
boolean getGlobalAccess()
void call(String signature)
LinkedList< MemoryEntry > getMemory()
void create(String variable, MType type)
void setDelay(long delay)
int getBreakpointPosition(int linenumber)
boolean hasBreakpoint(int linenumber)
synchronized void pause()
synchronized void singleStep()
Variable createInitVariable(String name, MType type)
void removeMachineListener(MachineListener m)
void setBreakpoint(int linenumber, boolean active)
void setProgram(ArrayList< Command > ops)
void debugStop(Marker codeRange)
void addPossibleBreakpoint(DebugPoint debugPoint, int linenumber)
void create(String variable, MType type, Object data)
void addUserFunction(String signature, MProcedure proc)
void addMachineListener(MachineListener m)
void removeDebugListener(DebugListener dl)
void addDebugListener(DebugListener dl)
void call(MProcedure proc)
void define(String variable, MType type)