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;
022:
023: import oscript.data.*;
024: import oscript.exceptions.*;
025: import oscript.visitor.*;
026: import oscript.syntaxtree.*;
027: import oscript.interpreter.*;
028: import oscript.compiler.*;
029: import oscript.util.StackFrame;
030: import oscript.util.MemberTable;
031:
032: import java.io.*;
033: import java.util.*;
034:
035: /**
036: * Built in functions, etc...
037: *
038: * @author Rob Clark (rob@ti.com)
039: * <!--$Format: " * @version $Revision$"$-->
040: * @version 1.14
041: */
042: public class OscriptBuiltins {
043: private static InputStream in = System.in;
044: private static PrintStream out = System.out;
045: private static PrintStream err = System.err;
046:
047: /**
048: * sorted by priority, values are list of runnables at that
049: * priority level.
050: */
051: private static TreeMap atExitRunnableMap = null;
052:
053: static {
054: Runtime.getRuntime().addShutdownHook(new Thread() {
055: public void run() {
056: runAtExitRunnables();
057: }
058: });
059: }
060:
061: private static void runAtExitRunnables() {
062: while (atExitRunnableMap != null) {
063: TreeMap map = atExitRunnableMap;
064: atExitRunnableMap = null;
065:
066: for (Iterator mitr = map.values().iterator(); mitr
067: .hasNext();) {
068: LinkedList list = (LinkedList) (mitr.next());
069: // System.err.println("run: " + list);
070:
071: for (Iterator litr = list.iterator(); litr.hasNext();) {
072: try {
073: ((Runnable) (litr.next())).run();
074: } catch (Throwable t) {
075: t.printStackTrace();
076: }
077: }
078: }
079: }
080: }
081:
082: /*=======================================================================*/
083: /**
084: *
085: */
086: static final void init() {
087: Scope globalScope = OscriptInterpreter.getGlobalScope();
088:
089: // add built-in types:
090: int attr = Reference.ATTR_CONST;
091: globalScope.createMember("JavaPackage", attr).opAssign(
092: JavaPackageWrapper.TYPE);
093: globalScope.createMember("Array", attr).opAssign(OArray.TYPE);
094: globalScope.createMember("Boolean", attr).opAssign(
095: OBoolean.TYPE);
096: globalScope.createMember("ExactNumber", attr).opAssign(
097: OExactNumber.TYPE);
098: globalScope.createMember("Exception", attr).opAssign(
099: OException.TYPE);
100: globalScope.createMember("NoSuchMemberException", attr)
101: .opAssign(ONoSuchMemberException.TYPE);
102: globalScope.createMember("NullReferenceException", attr)
103: .opAssign(ONullReferenceException.TYPE);
104: globalScope.createMember("IllegalArgumentException", attr)
105: .opAssign(OIllegalArgumentException.TYPE);
106: globalScope.createMember("UnsupportedOperationException", attr)
107: .opAssign(OUnsupportedOperationException.TYPE);
108: globalScope.createMember("JavaException", attr).opAssign(
109: OJavaException.TYPE);
110: globalScope.createMember("InexactNumber", attr).opAssign(
111: OInexactNumber.TYPE);
112: globalScope.createMember("String", attr).opAssign(OString.TYPE);
113: globalScope.createMember("Object", attr).opAssign(OObject.TYPE);
114: globalScope.createMember("Database", attr).opAssign(
115: Database.TYPE);
116: globalScope.createMember("Function", attr).opAssign(
117: Function.TYPE);
118: globalScope.createMember("JavaClass", attr).opAssign(
119: JavaClassWrapper.TYPE);
120: globalScope.createMember("JavaMethod", attr).opAssign(
121: JavaMethodWrapper.TYPE);
122: globalScope.createMember("Debugger", attr).opAssign(
123: Debugger.TYPE);
124: globalScope.createMember("ScriptPackage", attr).opAssign(
125: ScriptPackage.TYPE);
126: globalScope.createMember("Proxy", attr).opAssign(Proxy.TYPE);
127:
128: // add built-in functions:
129: // writeln:
130: {
131: final OString argNames[] = { OString.makeString("str") };
132:
133: globalScope.createMember("writeln", 0).opAssign(
134: new OBuiltinFunction(OString.makeString("writeln"),
135: argNames) {
136: public Value callAsFunction(StackFrame sf,
137: MemberTable args) {
138: if ((args == null)
139: || (args.length() != argNames.length))
140: throw PackagedScriptObjectException
141: .makeExceptionWrapper(new OIllegalArgumentException(
142: "wrong number of args!"));
143:
144: out.println(args.referenceAt(0)
145: .castToString());
146: out.flush();
147: return null;
148: }
149: });
150: }
151:
152: // write:
153: {
154: final OString argNames[] = { OString.makeString("str") };
155:
156: globalScope.createMember("write", 0).opAssign(
157: new OBuiltinFunction(OString.makeString("write"),
158: argNames) {
159: public Value callAsFunction(StackFrame sf,
160: MemberTable args) {
161: if ((args == null)
162: || (args.length() != argNames.length))
163: throw PackagedScriptObjectException
164: .makeExceptionWrapper(new OIllegalArgumentException(
165: "wrong number of args!"));
166:
167: out.print(args.referenceAt(0)
168: .castToString());
169: out.flush();
170: return null;
171: }
172: });
173: }
174:
175: // errln:
176: {
177: final OString argNames[] = { OString.makeString("str") };
178:
179: globalScope.createMember("errln", 0).opAssign(
180: new OBuiltinFunction(OString.makeString("errln"),
181: argNames) {
182: public Value callAsFunction(StackFrame sf,
183: MemberTable args) {
184: if ((args == null)
185: || (args.length() != argNames.length))
186: throw PackagedScriptObjectException
187: .makeExceptionWrapper(new OIllegalArgumentException(
188: "wrong number of args!"));
189:
190: err.println(args.referenceAt(0)
191: .castToString());
192: return null;
193: }
194: });
195: }
196:
197: // err:
198: {
199: final OString argNames[] = { OString.makeString("str") };
200:
201: globalScope.createMember("err", 0).opAssign(
202: new OBuiltinFunction(OString.makeString("err"),
203: argNames) {
204: public Value callAsFunction(StackFrame sf,
205: MemberTable args) {
206: if ((args == null)
207: || (args.length() != argNames.length))
208: throw PackagedScriptObjectException
209: .makeExceptionWrapper(new OIllegalArgumentException(
210: "wrong number of args!"));
211:
212: err.print(args.referenceAt(0)
213: .castToString());
214: return null;
215: }
216: });
217: }
218:
219: // useCompiler:
220: {
221: final OString argNames[] = { OString.makeString("b") };
222:
223: globalScope.createMember("useCompiler", 0).opAssign(
224: new OBuiltinFunction(OString
225: .makeString("useCompiler"), argNames) {
226: public Value callAsFunction(StackFrame sf,
227: MemberTable args) {
228: if ((args == null)
229: || (args.length() != argNames.length))
230: throw PackagedScriptObjectException
231: .makeExceptionWrapper(new OIllegalArgumentException(
232: "wrong number of args!"));
233:
234: OscriptInterpreter.useCompiler(args
235: .referenceAt(0).castToBoolean());
236: return null;
237: }
238: });
239: }
240:
241: // __runRegressionTests:
242: {
243: final OString argNames[] = {};
244:
245: globalScope
246: .createMember("__runRegressionTests", 0)
247: .opAssign(
248: new OBuiltinFunction(
249: OString
250: .makeString("__runRegressionTests"),
251: argNames) {
252: public Value callAsFunction(
253: StackFrame sf, MemberTable args) {
254: if ((args != null)
255: && (args.length() != argNames.length))
256: throw PackagedScriptObjectException
257: .makeExceptionWrapper(new OIllegalArgumentException(
258: "wrong number of args!"));
259:
260: return OExactNumber
261: .makeExactNumber(OscriptRegressionTestDriver
262: .runRegressionTests());
263: }
264: });
265: }
266:
267: // exit:
268: {
269: final OString argNames[] = { OString.makeString("result") };
270:
271: globalScope.createMember("exit", 0).opAssign(
272: new OBuiltinFunction(OString.makeString("exit"),
273: argNames) {
274: public Value callAsFunction(StackFrame sf,
275: MemberTable args) {
276: if ((args == null)
277: || (args.length() != argNames.length))
278: throw PackagedScriptObjectException
279: .makeExceptionWrapper(new OIllegalArgumentException(
280: "wrong number of args!"));
281:
282: exit((int) (args.referenceAt(0)
283: .castToExactNumber()));
284: return null; // never get here!
285: }
286: });
287: }
288:
289: // charToString:
290: {
291: final OString argNames[] = { OString.makeString("c") };
292:
293: globalScope.createMember("charToString", 0).opAssign(
294: new OBuiltinFunction(OString
295: .makeString("charToString"), argNames) {
296: public Value callAsFunction(StackFrame sf,
297: MemberTable args) {
298: if ((args == null)
299: || (args.length() != argNames.length))
300: throw PackagedScriptObjectException
301: .makeExceptionWrapper(new OIllegalArgumentException(
302: "wrong number of args!"));
303:
304: int c = (int) (args.referenceAt(0)
305: .castToExactNumber());
306:
307: return new OString("" + ((char) c)); // don't bother intern'ing (ie OString.makeString())
308: }
309: });
310: }
311:
312: // stringToChar:
313: {
314: final OString argNames[] = { OString.makeString("str") };
315:
316: globalScope.createMember("stringToChar", 0).opAssign(
317: new OBuiltinFunction(OString
318: .makeString("stringToChar"), argNames) {
319: public Value callAsFunction(StackFrame sf,
320: MemberTable args) {
321: if ((args == null)
322: || (args.length() != argNames.length))
323: throw PackagedScriptObjectException
324: .makeExceptionWrapper(new OIllegalArgumentException(
325: "wrong number of args!"));
326:
327: return OExactNumber
328: .makeExactNumber((int) (args
329: .referenceAt(0)
330: .castToString().charAt(0)));
331: }
332: });
333: }
334:
335: // __getPreviousScope:
336: {
337: final OString argNames[] = { OString.makeString("scope") };
338:
339: globalScope.createMember("__getPreviousScope", 0)
340: .opAssign(
341: new OBuiltinFunction(OString
342: .makeString("__getPreviousScope"),
343: argNames) {
344: public Value callAsFunction(
345: StackFrame sf, MemberTable args) {
346: if ((args == null)
347: || (args.length() != argNames.length))
348: throw PackagedScriptObjectException
349: .makeExceptionWrapper(new OIllegalArgumentException(
350: "wrong number of args!"));
351:
352: Value result = ((Scope) (args
353: .referenceAt(0).unhand()))
354: .getPreviousScope();
355:
356: if (result == null)
357: result = Value.NULL;
358:
359: return result;
360: }
361: });
362: }
363: }
364:
365: /*=======================================================================*/
366: /**
367: * Set the input stream.
368: *
369: * @param in the stream to use for input
370: */
371: public static void setIn(InputStream in) {
372: OscriptBuiltins.in = in;
373: }
374:
375: public static InputStream getIn() {
376: return in;
377: }
378:
379: /*=======================================================================*/
380: /**
381: * Set the output stream.
382: *
383: * @param out the stream to use for output
384: */
385: public static void setOut(PrintStream out) {
386: OscriptBuiltins.out = out;
387: }
388:
389: public static PrintStream getOut() {
390: return out;
391: }
392:
393: /*=======================================================================*/
394: /**
395: * Set the error stream.
396: *
397: * @param err the stream to use for error output
398: */
399: public static void setErr(PrintStream err) {
400: OscriptBuiltins.err = err;
401: }
402:
403: public static PrintStream getErr() {
404: return err;
405: }
406:
407: /*=======================================================================*/
408: /**
409: * Exit... this is a bit safer than calling System.exit() directly,
410: * because it will run the at-exit runnables *before* calling exit.
411: * They should still be run *in theory* if you call System.exit()
412: * directly, but it seems that is not always reliable
413: */
414: public static void exit(int status) {
415: runAtExitRunnables();
416: System.exit(status);
417: }
418:
419: /*=======================================================================*/
420: /**
421: * Register a hook to be called at system exit. The runnables are
422: * prioritized, and the ones with higher priority (lower numerical
423: * <code>priority</code> value) will be invoked first.
424: *
425: * @param r runnable to call
426: * @param priority lower numerical value is higher priority
427: */
428: public static synchronized void atExit(Runnable r,
429: final int priority) {
430: if (atExitRunnableMap == null)
431: atExitRunnableMap = new TreeMap();
432:
433: Integer p = new Integer(priority);
434: LinkedList runnableList = (LinkedList) (atExitRunnableMap
435: .get(p));
436: if (runnableList == null) {
437: runnableList = new LinkedList() {
438: public String toString() {
439: return "[pri=" + priority + ", list="
440: + super .toString() + "]";
441: }
442: };
443: atExitRunnableMap.put(p, runnableList);
444: }
445:
446: runnableList.add(r);
447: }
448:
449: public static void atExit(Runnable r) {
450: atExit(r, Integer.MAX_VALUE / 2);
451: }
452:
453: public static final long runStringTest(int cnt) {
454: String str = "0123456789";
455: String res = "";
456: long t = System.currentTimeMillis();
457: for (int i = 0; i < cnt; i++)
458: res += str;
459: return System.currentTimeMillis() - t;
460: }
461: }
462:
463: /**
464: * Here for now... for convenience of built-in functions/constructors/etc.
465: */
466: class OBuiltinFunction extends Value {
467: private OString[] argNames;
468: private OString name;
469:
470: OBuiltinFunction(OString name, OString[] argNames) {
471: super ();
472:
473: this .name = name;
474: this .argNames = argNames;
475: }
476:
477: protected Value getTypeImpl() {
478: return Function.TYPE;
479: }
480:
481: public String toString() {
482: String str = "<OBuiltinFunction: " + name + "( ";
483:
484: if (argNames == null) {
485: str += "...";
486: } else {
487: if (argNames.length > 0) {
488: str += argNames[0];
489:
490: for (int i = 1; i < argNames.length; i++) {
491: str += argNames[i];
492: }
493: }
494: }
495:
496: str += " )>";
497:
498: return str;
499: }
500:
501: public String castToString() {
502: return toString();
503: }
504: }
505:
506: /*
507: * Local Variables:
508: * tab-width: 2
509: * indent-tabs-mode: nil
510: * mode: java
511: * c-indentation-style: java
512: * c-basic-offset: 2
513: * eval: (c-set-offset 'substatement-open '0)
514: * eval: (c-set-offset 'case-label '+)
515: * eval: (c-set-offset 'inclass '+)
516: * eval: (c-set-offset 'inline-open '0)
517: * End:
518: */
|