001: /*=============================================================================
002: * Copyright Texas Instruments 2000. All Rights Reserved.
003: *
004: * This program is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2 of the License, or (at your option) any later version.
008: *
009: * This program is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the Free Software
016: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
017: *
018: * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $
019: */
020:
021: package oscript.data;
022:
023: import oscript.exceptions.*;
024:
025: import java.util.Hashtable;
026: import java.io.*;
027:
028: /**
029: * The Symbol is a type used internally by the scripting engine to represent
030: * identifiers, ie. variable or function names. Each symbol has a unique
031: * integer id. Furthermore, the mapping between symbols and ids is preserved
032: * in <i>/cache</i> so any cache entries (ie. compiled code, etc.) can assume
033: * that the same mapping between symbol and id exists as when it was created.
034: * (In other words, compiled code can discard the symbol object, and put the
035: * symbol's id in it's constant table.)
036: *
037: * @author Rob Clark (rob@ti.com)
038: * @version 1.56
039: */
040: public class Symbol extends OString implements Externalizable {
041: /**
042: * This symbol's unique id.
043: */
044: private int id;
045:
046: /**
047: * Class Constructor. In order to ensure that the str to id mapping is
048: * consistent, you cannot directly create an instance of a symbol. Instead
049: * you must go through {@link #getSymbol}.
050: *
051: * @param str the string representation
052: * @param id the unique id
053: */
054: private Symbol(String str, int id) {
055: super (str);
056: this .id = id;
057: }
058:
059: public Symbol() {
060: } // for serialization
061:
062: /**
063: * Get the unique id for this symbol. If two symbols are equal (in
064: * terms of {@link #bopEquals}), then they will map to the same id,
065: * and likewise the id will always map to symbols that are equal.
066: *
067: * @return the integer id
068: */
069: public int getId() {
070: return id;
071: }
072:
073: /**
074: * Derived class that implements {@link java.io.Externalizable} must
075: * call this if it overrides it. It should override it to save/restore
076: * it's own state.
077: */
078: public void readExternal(ObjectInput in) throws IOException {
079: super .readExternal(in);
080: id = in.readInt();
081: }
082:
083: /**
084: * Derived class that implements {@link java.io.Externalizable} must
085: * call this if it overrides it. It should override it to save/restore
086: * it's own state.
087: */
088: public void writeExternal(ObjectOutput out) throws IOException {
089: super .writeExternal(out);
090: out.writeInt(id);
091: }
092:
093: /* probably should have readResolve(), so symbols that are equal will
094: * be equal in terms of the java == operator... for now that doesn't
095: * matter anywhere, so for now I'll leave out readResolve()
096: */
097:
098: /**
099: * Maps string to symbol. Also contains a few extra fields which contain
100: * characters that are not legal identifiers:
101: * <ul>
102: * <li> "<lastId>" - tracks the last used id value
103: * <li> "<#>" - where # is some integer id number, maps to the
104: * symbol object with the same id
105: * </ul>
106: */
107: private static Symbols tbl = new Symbols();
108:
109: private static class Symbols {
110: int lastId;
111: Hashtable strToIdTable;
112: Symbol[] symbols;
113:
114: // note: don't initialize fields in constructor, because (hopefully)
115: // the common case will be serialization, not construction
116: Symbols() {
117: lastId = oscript.util.SymbolTable.MIN_SYMBOL_ID;
118: strToIdTable = new Hashtable();
119: symbols = new Symbol[100];
120: }
121: }
122:
123: /**
124: * Given a script object, return a symbol object. If two objects have
125: * the same string representation ({@link #castToString}) then they will
126: * always map to the same symbol.
127: */
128: public static Symbol getSymbol(Value val) {
129: if (val instanceof Symbol)
130: return (Symbol) val;
131: return getSymbol(val.castToString());
132: }
133:
134: /**
135: * Given a string, return a symbol object. If two strings are equals()
136: * then they will always map to the same symbol.
137: */
138: public synchronized static Symbol getSymbol(String str) {
139: Integer iid = (Integer) (tbl.strToIdTable.get(str));
140:
141: if (iid == null) {
142: int id = ++tbl.lastId;
143: iid = new Integer(id);
144:
145: if (id >= tbl.symbols.length) {
146: Symbol[] tmp = new Symbol[2 * id];
147: System.arraycopy(tbl.symbols, 0, tmp, 0,
148: tbl.symbols.length);
149: tbl.symbols = tmp;
150: }
151:
152: tbl.symbols[id] = new Symbol(str, id);
153: tbl.strToIdTable.put(str, iid);
154: }
155:
156: return tbl.symbols[iid.intValue()];
157: }
158:
159: /**
160: * Given a symbol id, return the symbol object. The same integer id will
161: * always map to the same symbol. If a symbol with the specified id does
162: * not exist, this will return <code>null</code>.
163: */
164: public static Symbol getSymbol(int id) {
165: if (id >= tbl.symbols.length)
166: return null;
167: return tbl.symbols[id];
168: }
169: }
170:
171: /*
172: * Local Variables:
173: * tab-width: 2
174: * indent-tabs-mode: nil
175: * mode: java
176: * c-indentation-style: java
177: * c-basic-offset: 2
178: * eval: (c-set-offset 'substatement-open '0)
179: * eval: (c-set-offset 'case-label '+)
180: * eval: (c-set-offset 'inclass '+)
181: * eval: (c-set-offset 'inline-open '0)
182: * End:
183: */
|