1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.millscript.millscript.vm;
22
23
24 import org.millscript.commons.util.IList;
25 import org.millscript.commons.util.list.ELinkedList;
26 import org.millscript.millscript.alert.Alerts;
27
28 /**
29 * This class provides the basis for a traceable machine. This class provides
30 * the skeletal implementation for a function call trace, similar to a Java
31 * stack trace.
32 */
33 public abstract class TraceableMachine {
34
35 /**
36 * The stack of function applications.
37 */
38 private Object[] doing = new Object[ 1024 ];
39
40 /**
41 * The index of the next value in the doing stack. Note this is also the
42 * number of values in the doing stack.
43 */
44 protected int doingIndex = 0;
45
46 /**
47 * Returns a list of function applications, in reverse order. This has to be
48 * returned in reverse order, so that the last item we were doing is
49 * reported first in the trace.
50 *
51 * @return a list containing the current function call stack, in reverse
52 * order.
53 */
54 public IList doingList() {
55 ELinkedList< Object > list = new ELinkedList< Object >();
56 for ( int i = 0; i < this.doingIndex; i++ ) {
57 list.addFirst( this.doing[ i ] );
58 }
59 return list;
60 }
61
62 /**
63 * Called when entering a function, this adds the specified object to the
64 * function call stack. To keep the call stack consistent, calls to this
65 * method should be paired with a call to {@link #exitFunction}.
66 *
67 * @param x the object to be added to the function call stack, specifically
68 * the function being entered
69 */
70 public void enterFunction( final Object x ) {
71 if ( this.doingIndex >= this.doing.length ) {
72
73 final Object[] newArray = new Object[ (int) ( this.doing.length * 1.5 ) ];
74 System.arraycopy( this.doing, 0, newArray, 0, this.doing.length );
75 this.doing = newArray;
76 }
77
78 this.doing[ this.doingIndex++ ] = x;
79 }
80
81 /**
82 * Called when exiting a function, this removes the last object from the
83 * function call stack. To keep the call stack consistent, calls to this
84 * method should be paired with a call to {@link #enterFunction}.
85 *
86 * @param x the object to be removed from the function call stack,
87 * specifically the function being exited.
88 */
89 public void exitFunction( final Object x ) {
90
91
92 if ( --this.doingIndex < 0 ) {
93 throw(
94 Alerts.fault( "Compiler bug - trying to exit a function we haven't entered" ).mishap()
95 );
96 }
97 }
98
99 /**
100 * Called when entering a function updater.
101 *
102 * @param x the object to be entered, e.g. the function whose updater is
103 * being entered.
104 */
105 public void enterUpdater( final Object x ) {
106 }
107
108 /**
109 * Called when exiting a function updater.
110 *
111 * @param x the object to be exited, e.g. the function whose updater is
112 * being exited.
113 */
114 public void exitUpdater( final Object x ) {
115 }
116
117 }