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)