001 /* Copyright 2000, 2001, Compaq Computer Corporation */
002
003 package javafe.ast;
004
005 import javafe.util.Assert;
006
007
008 /** Provides an extensible way to add 'fields' to the
009 <code>ASTNode</code>.
010
011 Each <code>ASTDecoration</code> object essentially corresponds to an
012 additional field in the <code>ASTNode</code> class. The value of this
013 field for a particular <code>ASTNode</code> object is accessed and
014 mutated via the instance methods <code>get</code> and
015 <code>set</code>, respectively (see below). Each
016 <code>ASTDecoration</code> object also has an associated
017 <code>String</code>, which 'names' the corresponding field.
018
019 @see javafe.ast.ASTNode
020 */
021
022 public class ASTDecoration {
023
024 /***************************************************
025 * *
026 * Class variables: *
027 * *
028 **************************************************/
029
030 //@ invariant allocated >= 0;
031 //@ spec_public
032 private static int allocated=0;
033
034 //@ invariant 0<=my_slot && my_slot<allocated;
035 //@ spec_public
036 private int my_slot;
037
038
039 /***************************************************
040 * *
041 * Instance variables: *
042 * *
043 **************************************************/
044
045 /** The name of our decoration */
046 //@ invariant name != null;
047 //@ spec_public
048 private String name;
049
050 /** Our decoration's actual "static" type */
051 //@ ghost public \TYPE decorationType;
052
053
054 /***************************************************
055 * *
056 * Creation: *
057 * *
058 **************************************************/
059
060 /**
061 * Creates a new <code>ASTDecoration</code> object with the given
062 * name. <p>
063 *
064 * The caller should set the decorationType field of the result.<p>
065 */
066 //@ requires s != null;
067 public ASTDecoration(String s) {
068 name = s;
069 my_slot = allocated;
070 allocated++;
071 }
072
073
074 /***************************************************
075 * *
076 * Methods: *
077 * *
078 **************************************************/
079
080 /**
081 * Return the decoration value of an <code>ASTNode</code>, or <code> null
082 * if the <code>ASTNode</code> has no decoration.
083 */
084 //@ requires n != null;
085 //@ ensures \typeof(\result) <: decorationType;
086 public Object get(ASTNode n) {
087 Assert.notNull(n);
088 Object[] v=n.getDecorations();
089 if( v != null && my_slot < v.length )
090 return v[my_slot];
091 else
092 return null;
093 } //@ nowarn Post;
094
095
096 /**
097 * Set the decoration value of an <code>ASTNode</code>.
098 */
099 //@ requires n != null;
100 //@ requires \typeof(val) <: decorationType;
101 public void set(ASTNode n, Object val) {
102 Object[] v = n.getDecorations();
103 if (v==null) {
104 v = new Object[allocated];
105 n.setDecorations(v);
106 } else if (my_slot >= v.length) {
107 Object[] _new = new Object[allocated];
108 System.arraycopy( v, 0, _new, 0, v.length );
109 v = _new;
110 n.setDecorations(v);
111 }
112 v[my_slot] = val;
113 }
114
115
116 /**
117 * Return the name associated with <code>this</code>.
118 */
119 public /*@non_null*/String toString() {
120 return name;
121 }
122
123 /**
124 * Return a string containing the decoration's name, and the
125 * decoration value for this <code>ASTNode</code>.
126 */
127 //@ requires n != null;
128 public /*@non_null*/ String toString(/*@non_null*/ASTNode n) {
129 Object val = get(n);
130 return "[Decoration "+name+" "+ ( val==null? "" : val.toString() )
131 +"]";
132 }
133 }