001: /*
002: * @(#)Function.java 1.6 05/06/21
003: *
004: * Copyright (c) 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.lang;
010:
011: import java.io.IOException;
012: import java.io.ObjectInputStream;
013: import java.io.ObjectOutputStream;
014: import java.io.Serializable;
015: import java.util.Enumeration;
016:
017: import org.pnuts.util.Cell;
018:
019: /**
020: * This class represents a function with a certain number of parameters. In
021: * Pnuts, functions should be accessed through PnutsFunction. This class is used
022: * mainly by compiler implementors. Note that there is no way to create a
023: * Function object through public API.
024: *
025: */
026: public class Function extends Runtime implements Serializable {
027:
028: static final long serialVersionUID = -997304045111474857L;
029:
030: /**
031: * name of the function including the scope information
032: *
033: * @serial
034: */
035: protected String funcName;
036:
037: /**
038: * name of the function without the scope information
039: *
040: * @serial
041: */
042: protected String name;
043:
044: boolean anonymous;
045:
046: /**
047: * the number of arguments
048: *
049: * @serial
050: */
051: protected int nargs;
052:
053: /**
054: * variable length arugments
055: *
056: * @serial
057: */
058: protected boolean varargs;
059:
060: /**
061: * local parameters
062: *
063: * @serial
064: */
065: protected String locals[];
066:
067: /**
068: * file name in which this function is defined
069: *
070: */
071: transient protected Object file;
072:
073: /**
074: * reference to the definition
075: *
076: */
077: protected SimpleNode node;
078:
079: /**
080: * @serial
081: */
082: SymbolTable lexicalScope;
083:
084: /**
085: * "import" environment
086: *
087: * @serial
088: */
089: protected ImportEnv importEnv;
090:
091: /**
092: * Used modules
093: *
094: * @serial
095: */
096: protected ModuleList moduleList;
097:
098: /**
099: * reference to the outer function
100: *
101: * @serial
102: */
103: protected Function outer;
104:
105: /**
106: * the package name in which this function is defined
107: *
108: * @serial
109: */
110: protected String pkgName;
111:
112: /**
113: * reference to PnutsFunction
114: *
115: * @serial
116: */
117: protected PnutsFunction function;
118:
119: protected transient Package pkg;
120:
121: protected Configuration config;
122:
123: boolean finallySet;
124:
125: protected Function() {
126: }
127:
128: Function(Function func) {
129: this .funcName = func.funcName;
130: this .name = func.name;
131: this .anonymous = func.anonymous;
132: this .locals = func.locals;
133: this .nargs = func.nargs;
134: this .varargs = func.varargs;
135: this .pkg = func.pkg;
136: this .pkgName = func.pkgName;
137: this .lexicalScope = func.lexicalScope;
138: this .importEnv = func.importEnv;
139: this .moduleList = func.moduleList;
140: this .file = func.file;
141: this .outer = func.outer;
142: this .node = func.node;
143: this .config = func.config;
144: this .function = func.function;
145: }
146:
147: protected Function(String func, String[] locals, int nargs,
148: SimpleNode node, Package pkg, Context context) {
149: this (func, locals, nargs, false, node, pkg, context);
150: }
151:
152: protected Function(String func, String[] locals, int nargs,
153: boolean varargs, SimpleNode node, Package pkg,
154: Context context) {
155: if (context.frame != null) {
156: this .outer = context.frame;
157: this .file = outer.file;
158: this .importEnv = outer.importEnv;
159: } else {
160: Cell c = context.loadingResource;
161: if (c != null) {
162: this .file = c.object;
163: }
164: this .importEnv = context.importEnv;
165: }
166: this .config = context.config;
167: this .moduleList = context.localModuleList();
168:
169: if (func != null) {
170: this .name = func;
171: } else {
172: this .name = "";
173: this .anonymous = true;
174: }
175: this .nargs = nargs;
176: this .varargs = varargs;
177: this .locals = locals;
178: this .node = node;
179: this .pkg = pkg;
180: this .pkgName = pkg.getName();
181:
182: StackFrame lex = context.stackFrame;
183: if (lex != null) {
184: this .lexicalScope = lex.makeLexicalScope();
185: }
186: }
187:
188: /**
189: * Returns the name of the function
190: */
191: public synchronized String getName() {
192: if (this .funcName == null) {
193: Function of = outer;
194: if (of != null) {
195: this .funcName = of.getName() + "." + this .name;
196: } else {
197: this .funcName = this .name;
198: }
199: }
200: return funcName;
201: }
202:
203: /**
204: * Returns the number of parameters
205: */
206: public int getNumberOfParameter() {
207: return nargs;
208: }
209:
210: public Object getScriptSource() {
211: return file;
212: }
213:
214: protected Object exec(Object[] args, Context context) {
215: try {
216: context.open(this , args);
217: return node.accept(PnutsInterpreter.instance, context);
218: } catch (ThreadDeath td) {
219: throw td;
220: } catch (Throwable t) {
221: Runtime.checkException(context, t);
222: return null;
223: } finally {
224: if (finallySet) {
225: Value b = context.stackFrame
226: .lookup(Context.finallyFunctionSymbol);
227: if (b != null) {
228: ((PnutsFunction) b.get()).call(new Object[] {},
229: context);
230: }
231: }
232: context.close(this , args);
233: }
234: }
235:
236: public Package getPackage() {
237: return pkg;
238: }
239:
240: public void setPackage(Package pkg) {
241: this .pkg = pkg;
242: }
243:
244: public String[] getImportEnv() {
245: return importEnv.list();
246: }
247:
248: String paramString() {
249: StringBuffer sbuf = new StringBuffer("");
250:
251: sbuf.append("(");
252: if (nargs != 0) {
253: sbuf.append(locals[0]);
254: }
255: for (int i = 1; i < nargs; i++) {
256: sbuf.append(",");
257: sbuf.append(locals[i]);
258: }
259: if (varargs) {
260: sbuf.append("[]");
261: }
262: sbuf.append(")");
263: return sbuf.toString();
264: }
265:
266: protected PnutsFunction register(PnutsFunction pf) {
267: return register(pf, false);
268: }
269:
270: protected PnutsFunction register(PnutsFunction pf, boolean isChild) {
271: if (pf == null) {
272: if (anonymous) {
273: pf = new PnutsFunction();
274: } else {
275: pf = new PnutsFunction(name);
276: }
277: pf.pkg = pkg;
278: } else if (isChild || pf.count == 0 || pf.pkg != pkg) {
279: PnutsFunction func = new PnutsFunction(name, pf);
280: func.pkg = pkg;
281: if (varargs) {
282: func.put(-1, this );
283: } else {
284: func.put(nargs, this );
285: }
286: return func;
287: }
288: if (varargs) {
289: pf.put(-1, this );
290: } else {
291: pf.put(nargs, this );
292: }
293: return pf;
294: }
295:
296: protected SimpleNode getNode() {
297: if (node != null) {
298: return node.jjtGetParent();
299: } else {
300: return null;
301: }
302: }
303:
304: protected Object accept(Visitor visitor, Context context) {
305: return getNode().accept(visitor, context);
306: }
307:
308: protected String unparse(Context context) {
309: return Runtime.unparse(getNode(), context);
310: }
311:
312: public String toString() {
313: String s = "function ";
314: s += getName();
315: s += paramString();
316: return s;
317: }
318:
319: void readAttributes(ObjectInputStream s) throws IOException,
320: ClassNotFoundException {
321: this .name = s.readUTF().intern();
322: this .anonymous = s.readBoolean();
323: this .finallySet = s.readBoolean();
324: this .nargs = s.readInt();
325: this .varargs = s.readBoolean();
326: String[] locals = (String[]) s.readObject();
327: this .locals = locals;
328: for (int j = 0; j < locals.length; j++) {
329: locals[j] = locals[j].intern();
330: }
331: this .importEnv = (ImportEnv) s.readObject();
332: this .moduleList = (ModuleList) s.readObject();
333: this .pkgName = (String) s.readUTF();
334: this .config = (Configuration) s.readObject();
335: this .file = s.readObject();
336: }
337:
338: void writeAttributes(ObjectOutputStream s) throws IOException {
339: s.writeUTF(name);
340: s.writeBoolean(anonymous);
341: s.writeBoolean(finallySet);
342: s.writeInt(nargs);
343: s.writeBoolean(varargs);
344: s.writeObject(locals);
345: s.writeObject(importEnv);
346: s.writeObject(moduleList);
347: s.writeUTF(pkgName);
348: s.writeObject(config);
349: s.writeObject(file);
350: }
351:
352: private void readObject(ObjectInputStream s) throws IOException,
353: ClassNotFoundException {
354: s.defaultReadObject();
355: for (int i = 0; i < locals.length; i++) {
356: locals[i] = locals[i].intern();
357: }
358: pkg = Package.getPackage(pkgName, null);
359: file = s.readObject();
360: }
361:
362: private void writeObject(ObjectOutputStream s) throws IOException {
363: s.defaultWriteObject();
364: s.writeObject(file);
365: }
366: }
|