001: /*=============================================================================
002: * Copyright Texas Instruments 2000-2004. 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: import oscript.util.*;
025:
026: /**
027: * Scope is an internal object use to represent a scope of execution. It is
028: * used to implement nested scope, ie. if a lookup in this scope fails, the
029: * lookup will procedue in the <code>previous</code> scope, and so on.
030: *
031: * @author Rob Clark (rob@ti.com)
032: */
033: public abstract class Scope extends Value {
034: /**
035: * Previous in object scope chain. This is used to <code>lookupInScope</code>,
036: * when the member being looked-up doesn't exist in this object (ie scope
037: * chain node)
038: */
039: protected Scope previous;
040:
041: /*=======================================================================*/
042: /**
043: * Class Constructor. Construct a element in the scope chain. This
044: * constructs a "function" element in the scope chain. This is
045: * called from the Function class when a function is evaluateded.
046: *
047: * @param previous previous in environment scope chain
048: */
049: protected Scope(Scope previous) {
050: super ();
051:
052: this .previous = previous;
053: }
054:
055: /*=======================================================================*/
056: /**
057: * Get the previous scope in the scope chain.
058: *
059: * @return the parent scope, or <code>null</code> if this is the global-
060: * scope (ie. topmost scope in the scope chain)
061: */
062: public Scope getPreviousScope() {
063: return previous;
064: }
065:
066: /*=======================================================================*/
067: /**
068: * Set the java-object associated with a script object... this is used
069: * when a script type subclasses a java type.
070: *
071: * @param javaObject the java-object
072: */
073: public void __setJavaObject(Object javaObject) {
074: previous.__setJavaObject(javaObject);
075: }
076:
077: /*=======================================================================*/
078: /**
079: * Lookup the "super" within a scope. Within a function body, "super"
080: * is the overriden function (if there is one).
081: *
082: * @return the "this" ScriptObject within this scope
083: */
084: public Value getSuper() {
085: return previous.getSuper();
086: }
087:
088: /*=======================================================================*/
089: /**
090: * Lookup the "this" within a scope. The "this" is the first scope chain
091: * node that is an object, rather than a regular scope chain node.
092: *
093: * @return the "this" ScriptObject within this scope
094: */
095: public Value getThis() {
096: return previous.getThis();
097: }
098:
099: /*=======================================================================*/
100: /**
101: * Lookup the qualified "this" within a scope. The qualified "this" is
102: * the first scope chain node that is an object and an instance of the
103: * specified type, rather than a regular scope chain node.
104: *
105: * @param val the type that the "this" qualifies
106: * @return the qualified "this" ScriptObject within this scope
107: */
108: public Value getThis(Value val) {
109: return previous.getThis(val);
110: }
111:
112: /*=======================================================================*/
113: /**
114: * Lookup the "callee" within a scope. The "callee" is the first scope
115: * chain node that is a function-scope, rather than a regular scope chain
116: * node.
117: *
118: * @return the "callee" Function within callee scope
119: */
120: public Value getCallee() {
121: return previous.getCallee();
122: }
123:
124: /*=======================================================================*/
125: /**
126: * Create a member of this object with the specified value. This method
127: * is provided for convenience.
128: *
129: * @param name the name of the member
130: * @param attr the attributes of the object (see <code>Reference</code>.)
131: * @see Reference
132: */
133: public final Value createMember(String name, int attr) {
134: return createMember(Symbol.getSymbol(name).getId(), attr);
135: }
136:
137: /*=======================================================================*/
138: /**
139: * Create a member of this object with the specified value.
140: *
141: * @param name the name of the member
142: * @param attr the attributes of the object (see <code>Reference</code>.)
143: * @see Reference
144: */
145: public final Value createMember(Value name, int attr) {
146: return createMember(Symbol.getSymbol(name).getId(), attr);
147: }
148:
149: /*=======================================================================*/
150: /**
151: * Create a member of this object with the specified value.
152: *
153: * @param id the id of the symbol that maps to the member
154: * @param attr the attributes of the object (see <code>Reference</code>.)
155: * @see Reference
156: */
157: public abstract Value createMember(int id, int attr);
158:
159: /*=======================================================================*/
160: /**
161: * "mixin" the specified variable into the current scope. When a object
162: * is mixed in, all of it's members are mixed in to the current scope.
163: * Members created within this scope will take precedence over a member
164: * of a mixed in object. The following script code example gives an idea
165: * of how this works:
166: * <pre>
167: * mixin java.lang.Math; // defines "min", "max", etc
168: * var c = min( a, b );
169: * var d = max( a, b );
170: * </pre>
171: * Mixins can also be used to implement OO composition, so a constructor
172: * function can mixin members of another object. (Note that this will
173: * not make the resulting object an instanceof this mixed in object's
174: * type... this could be made to work at some point in the future for
175: * script code, but not for java code, if that was deemed a good thing..)
176: * <pre>
177: * function ListAndStuff()
178: * {
179: * public function foo() { ... }
180: * var list = new java.util.LinkedList();
181: * mixin list;
182: * }
183: * var obj = new ListAndStuff();
184: * obj.foo();
185: * obj.add(1);
186: * obj.add("two");
187: * for( var o : obj )
188: * writeln("list member: " + o);
189: * </pre>
190: *
191: * @param val the value to mixin to this scope
192: */
193: public abstract void mixin(Value val);
194:
195: /*=======================================================================*/
196: // XXX hack
197: protected Value getMemberImpl(int id) {
198: return null;
199: }
200:
201: protected Value getInstanceMemberImpl(int id) {
202: return null;
203: }
204:
205: // only for use by wrapper class (oscript.classwrap.ClassWrapGen)
206: public abstract Value __getInstanceMember(int id);
207:
208: /*=======================================================================*/
209: /**
210: * Get a member from this scope. This is used to access local variables
211: * and object attributes from methods of the object. If the attribute
212: * isn't in this node in the scope chain, then the <code>previous</code>
213: * node in the scope chain is checked. This method is provided for
214: * convenience.
215: *
216: * @param name the name of the member
217: * @throws PackagedScriptObjectException(NoSuchMemberException)
218: */
219: public final Value lookupInScope(String name)
220: throws PackagedScriptObjectException {
221: return lookupInScope(Symbol.getSymbol(name).getId());
222: }
223:
224: /*=======================================================================*/
225: /**
226: * Get a member from this scope. This is used to access local variables
227: * and object attributes from methods of the object. If the attribute
228: * isn't in this node in the scope chain, then the <code>previous</code>
229: * node in the scope chain is checked.
230: *
231: * @param name the name of the member
232: * @throws PackagedScriptObjectException(NoSuchMemberException)
233: */
234: public final Value lookupInScope(Value name)
235: throws PackagedScriptObjectException {
236: return lookupInScope(Symbol.getSymbol(name).getId());
237: }
238:
239: /*=======================================================================*/
240: /**
241: * Get a member from this scope. This is used to access local variables
242: * and object attributes from methods of the object. If the attribute
243: * isn't in this node in the scope chain, then the <code>previous</code>
244: * node in the scope chain is checked.
245: *
246: * @param id the id of the symbol that maps to the member
247: * @throws PackagedScriptObjectException(NoSuchMemberException)
248: */
249: public abstract Value lookupInScope(int id)
250: throws PackagedScriptObjectException;
251:
252: /*=======================================================================*/
253: /**
254: * In case a scope has any resource allocated from a source which will
255: * no long be valid after a stack frame has returned (ie. resource
256: * allocated from stack), return a copy of the scope that is safe to
257: * keep after the stack frame returns.
258: */
259: public Scope getSafeCopy() {
260: previous = previous.getSafeCopy();
261: return this ;
262: }
263:
264: /*=======================================================================*/
265: // XXX for debugging, determine if this is a scope that is safe to hold
266: // a reference to after it is left
267: public abstract boolean isSafe();
268:
269: /*=======================================================================*/
270: /**
271: * Indicate that this scope is no longer needed. This should only be called
272: * in cases of scopes allocated from the stack.
273: */
274: public abstract void free();
275:
276: /*=======================================================================*/
277: protected final static String findDesc(Scope scope) {
278: for (java.util.Iterator itr = StackFrame.currentStackFrame()
279: .iterator(); itr.hasNext();) {
280: StackFrame sf = (StackFrame) (itr.next());
281: if (sf.getScope() == scope)
282: return sf.toString();
283: }
284: return "??unknown??";
285: }
286: }
287:
288: /*
289: * Local Variables:
290: * tab-width: 2
291: * indent-tabs-mode: nil
292: * mode: java
293: * c-indentation-style: java
294: * c-basic-offset: 2
295: * eval: (c-set-offset 'substatement-open '0)
296: * eval: (c-set-offset 'case-label '+)
297: * eval: (c-set-offset 'inclass '+)
298: * eval: (c-set-offset 'inline-open '0)
299: * End:
300: */
|