View Javadoc

1   ////////////////////////////////////////////////////////////////////////////////
2   // MillScript: an Open Spice interpreter and batch website creation tool
3   // Copyright (C) 2001-2004 Open World Ltd
4   //
5   // This file is part of MillScript.
6   //
7   // MillScript is free software; you can redistribute it and/or modify it under
8   // the terms of the GNU General Public License as published by the Free
9   // Software Foundation; either version 2 of the License, or (at your option)
10  // any later version.
11  //
12  // MillScript is distributed in the hope that it will be useful, but WITHOUT
13  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  // more details.
16  //
17  // You should have received a copy of the GNU General Public License along with
18  // MillScript; if not, write to the Free Software Foundation, Inc., 59 Temple
19  // Place, Suite 330, Boston, MA  02111-1307  USA
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              // We need to grow the array
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          // "push" the new value on the end
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          // We can simply decrement the doing array index here. However we must
91          // check if it goes below zero as thats a compiler bug.
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 }