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.compiler;
022:
023: import oscript.data.*;
024: import oscript.util.*;
025: import oscript.*;
026: import oscript.fs.AbstractFile;
027: import oscript.exceptions.PackagedScriptObjectException;
028: import oscript.parser.ParseException;
029:
030: /**
031: * This is the base class for all compiled script functions. I could have
032: * used an interface, but there was no need for a compiled script function
033: * object to subclass any other object.
034: * <p>
035: * A compiled function does not store the scope the script function was
036: * defined in, but simply a compiled version of the function's syntaxtree.
037: * This means that once a function is compiled for one scope, it does not
038: * need to be recompiled for a different scope.
039: *
040: * @author Rob Clark (rob@ti.com)
041: * <!--$Format: " * @version $Revision$"$-->
042: * @version 1.19
043: */
044: public abstract class CompiledNodeEvaluator extends NodeEvaluator {
045: private String name;
046:
047: private String desc = "compiled code";
048:
049: /**
050: * if the desc is a file path, then this won't be null... eventually
051: * i'd like the desc to be a file, so we won't need this, but that
052: * will require parser mods, so for now:
053: */
054: private AbstractFile file;
055:
056: // protected CompiledNodeEvaluator() {}
057:
058: // protected final static Object _readObject( java.io.ObjectInput in )
059: // throws java.io.IOException, ClassNotFoundException
060: // {
061: // return in.readObject();
062: // }
063: //
064: // protected final static void _writeObject( java.io.ObjectOutput out, Object obj )
065: // throws java.io.IOException
066: // {
067: // out.writeObject(obj);
068: // }
069: /*=======================================================================*/
070:
071: /*=======================================================================*/
072: /**
073: * Class Constructor.
074: *
075: * @param name the name of this function
076: * @param desc the description of input source (ie. filename)
077: */
078: protected CompiledNodeEvaluator(String name, String desc) {
079: super ();
080: this .name = name;
081: this .desc = desc;
082: }
083:
084: /*=======================================================================*/
085: /**
086: * Get the file that this node was parsed from.
087: *
088: * @return the file
089: */
090: public AbstractFile getFile() {
091: if (file == null) {
092: try {
093: if ((desc != null) && (desc.length() > 0))
094: file = OscriptInterpreter.resolve(desc, false);
095: } catch (java.io.IOException e) {
096: }
097: }
098:
099: return file;
100: }
101:
102: /*=======================================================================*/
103: /**
104: * Get the function symbol (name), if this node evaluator is a function,
105: * otherwise return <code>-1</code>.
106: *
107: * @return the symbol, or <code>-1</code>
108: */
109: public int getId() {
110: /* name is going to be a class name... currently the class name will
111: * either be a function name, or a translated path (for a node that
112: * corresponds to a file) in which case it will start with "root.":
113: */
114: return name.startsWith("root.") ? -1 : Symbol.getSymbol(name)
115: .getId();
116: }
117:
118: /*=======================================================================*/
119: /**
120: * Evaluate, in the specified scope. If this is a function, the Arguments
121: * to the function, etc., are defined in the <code>scope</code> that the
122: * function is evaluated in.
123: *
124: * @param sf the stack frame to evaluate the node in
125: * @param scope the scope to evaluate the function in
126: * @return the result of evaluating the function
127: */
128: public Object evalNode(StackFrame sf, Scope scope)
129: throws PackagedScriptObjectException {
130: // this node evaluator is always index 0. For inner-nodes, a non-zero
131: // index is used, which is passed to the CompiledInnerNodeEvaluator (which
132: // passes it back when it calls this object's evalInnerNode())
133: return evalInnerNode(0, sf, scope);
134: }
135:
136: /*=======================================================================*/
137: /**
138: * Evaluate, in the specified scope. If this is a function, the Arguments
139: * to the function, etc., are defined in the <code>scope</code> that the
140: * function is evaluated in.
141: *
142: * @param sf the stack frame to evaluate the node in
143: * @param scope the scope to evaluate the function in
144: * @return the result of evaluating the function
145: */
146: public abstract Object evalInnerNode(int idx, StackFrame sf,
147: Scope scope) throws PackagedScriptObjectException;
148:
149: /*=======================================================================*/
150: /**
151: * Get the SMIT for the scope(s) created when invoking this node evaluator.
152: *
153: * @param perm <code>PRIVATE</code>, <code>PUBPROT</code>,
154: * <code>ALL</code>
155: */
156: public SymbolTable getSharedMemberIndexTable(int perm) {
157: // this node evaluator is always index 0. For inner-nodes, a non-zero
158: // index is used, which is passed to the CompiledInnerNodeEvaluator (which
159: // passes it back when it calls this object's evalInnerNode())
160: return getInnerSharedMemberIndexTable(0, perm);
161: }
162:
163: /*=======================================================================*/
164: /**
165: * Get the SMIT for the scope(s) created when invoking this node evaluator.
166: */
167: public abstract SymbolTable getInnerSharedMemberIndexTable(int idx,
168: int perm);
169:
170: /*=======================================================================*/
171: /**
172: * A helper function for evaluating an <i>EvalBlock</i>.
173: *
174: * @param str the string to evaluate
175: * @param scope the scope to evaluate in
176: * @return the result
177: */
178: protected static final Value evalHelper(String str, Scope scope) {
179: try {
180: return OscriptInterpreter.eval(str, scope);
181: } catch (ParseException e) {
182: throw PackagedScriptObjectException
183: .makeExceptionWrapper(new OException(e.getMessage()));
184: }
185: }
186:
187: /*=======================================================================*/
188: /**
189: * A helper function for evaluating an <i>ImportBlock</i>.
190: *
191: * @param path the string identifying what to import
192: * @param scope the scope to evaluate in
193: * @return the result
194: */
195: protected static final Value importHelper(String path, Scope scope) {
196: return OscriptInterpreter.importHelper(path, scope);
197: }
198:
199: /*=======================================================================*/
200: /**
201: * A helper function for evaluating an <i>ReturnStatement</i> or
202: * <i>ThrowBlock</i>, to ensure that the value being returned/thrown
203: * is not <code>(undefined)</code>.
204: */
205: public static final Value returnHelper(Value val) {
206: // XXX work around bug that results in null on the stack...
207: if (val == null)
208: val = Value.NULL;
209:
210: val = val.unhand();
211:
212: if (val == Value.UNDEFINED) {
213: if (!"warning".equals(System
214: .getProperty("oscript.undefined.return")))
215: throw PackagedScriptObjectException
216: .makeExceptionWrapper(new OException(
217: "cannot return or throw (undefined)"));
218:
219: String desc = "";
220:
221: //////////////////////////////////////////////////////////////////////////
222: // the following code is a hack to attempt to determine what script called
223: // this, so we can print a more informative warning message:
224: try {
225: oscript.util.StackFrame sf = oscript.util.StackFrame
226: .currentStackFrame();
227: desc = " at " + sf.toString();
228: } catch (Throwable t) {
229: // ignore... an exception may be thrown if not called from script
230: }
231: //////////////////////////////////////////////////////////////////////////
232: oscript.util.ErrorHandler
233: .warning("warning: cannot return or throw (undefined)"
234: + desc);
235: }
236:
237: return val;
238: }
239: }
240:
241: /*
242: * Local Variables:
243: * tab-width: 2
244: * indent-tabs-mode: nil
245: * mode: java
246: * c-indentation-style: java
247: * c-basic-offset: 2
248: * eval: (c-set-offset 'substatement-open '0)
249: * eval: (c-set-offset 'case-label '+)
250: * eval: (c-set-offset 'inclass '+)
251: * eval: (c-set-offset 'inline-open '0)
252: * End:
253: */
|