KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > gnu > expr > Language


1 // Copyright (c) 2002, 2003, 2004, 2005 Per M.A. Bothner.
2
// This is free software; for terms and warranty disclaimer see ./COPYING.
3

4 package gnu.expr;
5 import gnu.mapping.*;
6 import gnu.bytecode.*;
7 import gnu.mapping.Location;
8 import gnu.lists.*;
9 import gnu.text.Lexer;
10 import gnu.text.SourceMessages;
11 import gnu.kawa.reflect.*;
12 import java.io.*;
13 import java.lang.reflect.InvocationTargetException JavaDoc;
14 import gnu.kawa.lispexpr.ClassNamespace; // FIXME
15

16 /**
17  * Contains various language-dependent methods.
18  * Also contains "global" state about the executation environment,
19  * such as the global Environment. There can be multiple Languages
20  * associated with different threads, representing mutiple top-levels.
21  * (However, this functionality is incomplete.)
22  */

23
24 public abstract class Language
25 {
26    protected static final ThreadLocation current
27      = new ThreadLocation("language");
28
29   public static Language getDefaultLanguage()
30   { return (Language) current.get(null); }
31
32   static { Environment.setGlobal(BuiltinEnvironment.getInstance()); }
33
34   public static void setDefaultLanguage(Language language)
35   {
36     current.set(language);
37   }
38
39   /**
40    * List of known languages and their Language classes.
41    * Each element is one or more language names, or filename extensions,
42    * followed by the name of the Language sub-class.
43    * The table is searched from the beginning.
44    */

45
46   static String JavaDoc[][] languages =
47   {
48     { "scheme", ".scm", ".sc", "kawa.standard.Scheme" },
49     { "krl", ".krl", "gnu.kawa.brl.BRL" },
50     { "brl", ".brl", "gnu.kawa.brl.BRL" },
51     { "emacs", "elisp", "emacs-lisp", ".el", "gnu.jemacs.lang.ELisp" },
52     { "xquery", ".xquery", ".xq", ".xql", "gnu.xquery.lang.XQuery" },
53     { "q2", ".q2", "gnu.q2.lang.Q2" },
54     { "xslt", "xsl", ".xsl", "gnu.kawa.xslt.XSLT" },
55     { "commonlisp", "common-lisp", "clisp", "lisp",
56       ".lisp", ".lsp", ".cl",
57       "gnu.commonlisp.lang.CommonLisp" }
58   };
59
60   /** Get a list of all available languages */
61
62   public static String JavaDoc[][] getLanguages()
63   {
64     return languages;
65   }
66
67   /** Add a language to the list.
68    *
69    * @param langMapping is a language definition, the first index
70    * is the language name, subsequent indexes are file types that
71    * might cause the language to be used and the final index is the
72    * name of the class that implements the language.
73    */

74   public static void registerLanguage(String JavaDoc[] langMapping)
75   {
76     String JavaDoc[][] newLangs = new String JavaDoc[languages.length + 1][];
77     System.arraycopy(languages, 0, newLangs, 0, languages.length);
78     newLangs[newLangs.length - 1] = langMapping;
79     languages = newLangs;
80   }
81
82   /** Detect the programming language of a file based on its first line.
83    * @return a suitable Language or null if we didn't recognize one.
84    */

85   public static Language detect (InputStream in)
86     throws IOException
87   {
88     if (! in.markSupported())
89       return null;
90     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
91     in.mark(200);
92     for (;;)
93       {
94         if (sbuf.length() >= 200)
95           break;
96         int c = in.read();
97         if (c < 0 || c == '\n' || c == '\r')
98           break;
99         sbuf.append((char) c);
100       }
101     in.reset();
102     return detect(sbuf.toString());
103   }
104
105   /** Detect the programming language of a file based on its first line.
106    * @return a suitable Language or null if we didn't recognize one.
107    */

108   public static Language detect (InPort port)
109     throws IOException
110   {
111     StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
112     port.mark(300);
113     port.readLine(sbuf, 'P');
114     port.reset();
115     return detect(sbuf.toString());
116   }
117
118   /** Detect the programming language of a file based on its first line.
119    * @param line the first input line
120    * @return a suitable Language or null if we didn't recognize one.
121    */

122   public static Language detect (String JavaDoc line)
123   {
124     String JavaDoc str = line.trim();
125     // Does the line contain the string "kawa:LANGAUGE" for a valid LANGUAGE?
126
int k = str.indexOf("kawa:");
127     if (k >= 0)
128       {
129         int i = k+5;
130         int j = i;
131         while (j < str.length()
132                && Character.isJavaIdentifierPart(str.charAt(j)))
133           j++;
134         if (j > i)
135           {
136             String JavaDoc w = str.substring(i, j);
137             Language lang = getInstance(w);
138             if (lang != null)
139               return lang;
140           }
141       }
142     // Check for various Emacs language/mode patterns.
143
if (str.indexOf("-*- scheme -*-") >= 0)
144       return getInstance("scheme");
145     if (str.indexOf("-*- xquery -*-") >= 0)
146       return getInstance("xquery");
147     if (str.indexOf("-*- emacs-lisp -*-") >= 0)
148       return getInstance("elisp");
149     if (str.indexOf("-*- common-lisp -*-") >= 0
150         || str.indexOf("-*- lisp -*-") >= 0)
151       return getInstance("common-lisp");
152     // Does it start with an XQuery comment or XQuery version statement?
153
if ((str.charAt(0) == '(' && str.charAt(1) == ':')
154         || (str.length() >= 7 && str.substring(0, 7).equals("xquery ")))
155       return getInstance("xquery");
156     if (str.charAt(0) == ';' && str.charAt(1) == ';')
157       return getInstance("scheme");
158     return null;
159   }
160
161   public static Language getInstanceFromFilenameExtension(String JavaDoc filename)
162   {
163     int dot = filename.lastIndexOf('.');
164     if (dot > 0)
165       {
166     Language lang = Language.getInstance(filename.substring(dot));
167     if (lang != null)
168       return lang;
169       }
170     return null;
171   }
172
173   /** Look for a language with the given name or extension.
174    * If name is null, look for the first language available. */

175   public static Language getInstance (String JavaDoc name)
176   {
177     int langCount = languages.length;
178     for (int i = 0; i < langCount; i++)
179       {
180     String JavaDoc[] names = languages[i];
181     int nameCount = names.length - 1;
182     for (int j = nameCount; --j >= 0; )
183       {
184         if (name == null || names[j].equalsIgnoreCase(name))
185           {
186         Class JavaDoc langClass;
187         try
188           {
189             langClass = Class.forName(names[nameCount]);
190           }
191         catch (ClassNotFoundException JavaDoc ex)
192           {
193             // In the future, we may support languages names that
194
// can be implemented by more than one Language,
195
// so don't give up yet.
196
break;
197           }
198         return getInstance(names[0], langClass);
199           }
200       }
201       }
202     return null;
203   }
204
205   protected Language ()
206   {
207     gnu.lists.Convert.setInstance(KawaConvert.getInstance());
208   }
209
210   public static Language getInstance (String JavaDoc langName, Class JavaDoc langClass)
211   {
212     try
213       {
214     java.lang.reflect.Method JavaDoc method;
215     Class JavaDoc[] args = { };
216     try
217       {
218         String JavaDoc capitalizedName
219           = (Character.toTitleCase(langName.charAt(0))
220          + langName.substring(1).toLowerCase());
221         String JavaDoc methodName = "get" + capitalizedName + "Instance";
222         method = langClass.getDeclaredMethod(methodName, args);
223       }
224     catch (Exception JavaDoc ex)
225       {
226         method
227           = langClass.getDeclaredMethod("getInstance", args);
228       }
229     return (Language) method.invoke(null, Values.noArgs);
230       }
231     catch (Exception JavaDoc ex)
232       {
233     langName = langClass.getName();
234     Throwable JavaDoc th;
235     if (ex instanceof InvocationTargetException JavaDoc)
236       th = ((InvocationTargetException JavaDoc) ex).getTargetException();
237     else
238       th = ex;
239     // th.printStackTrace();
240
throw new WrappedException("getInstance for '" + langName + "' failed",
241                    th);
242       }
243   }
244
245   /** Test if a value is considered "true" in this language. */
246   public boolean isTrue(Object JavaDoc value)
247   {
248     return value != Boolean.FALSE;
249   }
250
251   public Object JavaDoc booleanObject(boolean b)
252   {
253     return b ? Boolean.TRUE : Boolean.FALSE;
254   }
255
256   /** The value to return for a "void" result. */
257   public Object JavaDoc noValue()
258   {
259     return Values.empty;
260   }
261
262   /** True if functions are in a separate anme space from variable.
263    * Is true for e.g. Common Lisp, Emacs Lisp; false for Scheme. */

264   public boolean hasSeparateFunctionNamespace()
265   {
266     return false;
267   }
268
269   /** The environment for language built-ins and predefined bindings. */
270   protected Environment environ;
271
272   /** If non-null, the user environment.
273    * This allows "bunding" an Environment with a Language. This is partly to
274    * match existing documentation, and partly for convenience from Java code.
275    * Normally, userEnv is null, in which case the user environment is
276    * extracted from the current thread. */

277   protected Environment userEnv;
278
279   /** Get current user environment. */
280   public final Environment getEnvironment()
281   {
282     return userEnv != null ? userEnv : Environment.getCurrent();
283   }
284
285   static int envCounter;
286
287   public final Environment getNewEnvironment ()
288   {
289     return Environment.make("environment-"+(++envCounter), environ);
290   }
291
292   public Environment getLangEnvironment() { return environ; }
293
294   public NamedLocation lookupBuiltin (Symbol name, Object JavaDoc property, int hash)
295   {
296     return environ == null ? null : environ.lookup(name, property, hash);
297   }
298
299   /** Enter a value into the current environment. */
300   public void define(String JavaDoc sym, Object JavaDoc p)
301   {
302     Symbol s = getSymbol(sym);
303     environ.define(s, null, p);
304   }
305
306   /** Declare in the current Environment a variable aliased to a static field.
307    */

308   protected void defAliasStFld(String JavaDoc name, String JavaDoc cname, String JavaDoc fname)
309   {
310     StaticFieldLocation.define(environ, getSymbol(name), null, cname, fname);
311   }
312
313   /** Declare in the current Environment a procedure bound to a static field.
314    * @param name the procedure's source-level name.
315    * @param cname the name of the class containing the field.
316    * @param fname the name of the field, which should be a static
317    * final field whose type extends gnu.mapping.Procedure.
318    */

319   protected void defProcStFld(String JavaDoc name, String JavaDoc cname, String JavaDoc fname)
320   {
321     Object JavaDoc property = (hasSeparateFunctionNamespace() ? EnvironmentKey.FUNCTION
322                : null);
323     Symbol sym = getSymbol(name);
324     StaticFieldLocation loc
325       = StaticFieldLocation.define(environ, sym, property, cname, fname);
326     loc.setProcedure();
327   }
328
329   /** Declare in the current Environment a procedure bound to a static field.
330    * @param name the procedure's source-level name.
331    * @param cname the name of the class containing the field.
332    * The name of the field is the mangling of <code>name</code>.
333    */

334   protected void defProcStFld(String JavaDoc name, String JavaDoc cname)
335   {
336     defProcStFld(name, cname, Compilation.mangleNameIfNeeded(name));
337   }
338
339   /** Enter a named function into the current environment. */
340   public final void defineFunction(Named proc)
341   {
342     Object JavaDoc name = proc.getSymbol();
343     Symbol sym = (name instanceof Symbol ? (Symbol) name
344           : getSymbol(name.toString()));
345     Object JavaDoc property = (hasSeparateFunctionNamespace() ? EnvironmentKey.FUNCTION
346                : null);
347     environ.define(sym, property, proc);
348   }
349
350   /** Enter a function into the current environment.
351    * Same as define(name,proc) for Scheme, but not for (say) Common Lisp.
352    **/

353   public void defineFunction(String JavaDoc name, Object JavaDoc proc)
354   {
355     Object JavaDoc property = (hasSeparateFunctionNamespace() ? EnvironmentKey.FUNCTION
356                : null);
357     environ.define(getSymbol(name), property, proc);
358   }
359
360   /** Import all the public fields of an object. */
361   private void defineAll(Object JavaDoc object)
362   {
363     Class JavaDoc clas = object.getClass();
364     java.lang.reflect.Field JavaDoc[] fields = clas.getFields();
365     for (int i = fields.length; --i >= 0; )
366       {
367     java.lang.reflect.Field JavaDoc field = fields[i];
368     String JavaDoc name = field.getName();
369     if (name.startsWith(Declaration.PRIVATE_PREFIX)
370         || name.endsWith("$instance"))
371       continue;
372     if ((field.getModifiers() & java.lang.reflect.Modifier.FINAL) != 0)
373       {
374         try
375           {
376         defineFromFieldValue(field, field.get(object));
377           }
378         catch (Throwable JavaDoc ex)
379           {
380         throw new WrappedException("error accessing field "+field, ex);
381           }
382       }
383     else
384       {
385         System.err.println("INTERNAL ERROR in defineAll for "
386                    + name + " in " + clas);
387       }
388       }
389   }
390
391   private void defineFromFieldValue(java.lang.reflect.Field JavaDoc fld, Object JavaDoc value)
392     throws Throwable JavaDoc
393   {
394     if (value instanceof Location)
395       {
396     Location loc = (Location) value;
397     Symbol sym = loc.getKeySymbol();
398     if (sym != null)
399       {
400         environ.addLocation(sym, loc.getKeyProperty(), loc);
401         return;
402       }
403       }
404     else
405       {
406     Object JavaDoc vname;
407     if (value instanceof Named)
408       vname = ((Named) value).getSymbol();
409     else
410       vname = null;
411     if (vname == null)
412       vname = Compilation.demangleName(fld.getName(), true).intern();
413     Symbol symbol = vname instanceof Symbol ? (Symbol) vname
414       : environ.getSymbol(vname.toString());
415     Object JavaDoc prop = getEnvPropertyFor(fld, value);
416     environ.define(symbol, prop, value);
417       }
418   }
419
420   public Object JavaDoc getEnvPropertyFor (java.lang.reflect.Field JavaDoc fld, Object JavaDoc value)
421   {
422     if (! hasSeparateFunctionNamespace())
423       return null;
424     if (Compilation.typeProcedure.getReflectClass()
425     .isAssignableFrom(fld.getType()))
426       return EnvironmentKey.FUNCTION;
427     return null;
428   }
429
430   public Object JavaDoc getEnvPropertyFor (Declaration decl)
431   {
432     if (hasSeparateFunctionNamespace() && decl.isProcedureDecl())
433       return EnvironmentKey.FUNCTION;
434     return null;
435   }
436
437   public void loadClass(String JavaDoc name)
438     throws java.lang.ClassNotFoundException JavaDoc
439   {
440     try
441       {
442     Class JavaDoc clas = Class.forName(name);
443     Object JavaDoc inst = clas.newInstance ();
444     defineAll(inst);
445     if (inst instanceof ModuleBody)
446       ((ModuleBody)inst).run();
447       }
448     catch (java.lang.ClassNotFoundException JavaDoc ex)
449       {
450     throw ex;
451       }
452     catch (Exception JavaDoc ex)
453       {
454     throw new WrappedException("cannot load "+name, ex);
455       }
456   }
457
458   public Symbol getSymbol (String JavaDoc name)
459   {
460     return environ.getSymbol(name);
461   }
462
463   public Object JavaDoc lookup(String JavaDoc name)
464   {
465     return environ.get (name);
466   }
467
468   public AbstractFormat getFormat(boolean readable)
469   {
470     return null;
471   }
472
473   public Consumer getOutputConsumer(Writer out)
474   {
475     OutPort oport = out instanceof OutPort ? (OutPort) out
476       : new OutPort(out);
477     oport.objectFormat = getFormat(false);
478     return oport;
479   }
480
481   public String JavaDoc getName()
482   {
483     String JavaDoc name = getClass().getName();
484     int dot = name.lastIndexOf('.');
485     if (dot >= 0)
486       name = name.substring(dot+1);
487     return name;
488   }
489
490   public abstract Lexer getLexer(InPort inp, SourceMessages messages);
491
492   public Compilation getCompilation (Lexer lexer, SourceMessages messages)
493   {
494     return new Compilation(this, messages);
495   }
496
497   /** Flag to tell parse that expression will be evaluated immediately.
498    * I.e. we're not creating class files for future execution. */

499   public static final int PARSE_IMMEDIATE = 1;
500   /** Flag to tell parse to only read a single line if possible.
501    * Multiple lines may be read if syntactically required. */

502   public static final int PARSE_ONE_LINE = 2;
503   /** Flag to tell parser to continue until we have the module name.
504    * The parser is allowed to continue further, but must stop before
505    * any module import. */

506   public static final int PARSE_PROLOG = 4;
507
508   public static boolean requirePedantic;
509
510   /** Parse one or more expressions.
511    * @param port the InPort to read the expressions from.
512    * @param messages where to send error messages and warnings
513    * @param options various flags, includding PARSE_IMMEDIATE
514    * and PARSE_ONE_LINE
515    * @return a new Compilation.
516    * May return null if PARSE_ONE_LINE on end-of-file.
517    */

518   public final Compilation parse(InPort port,
519                                  gnu.text.SourceMessages messages,
520                                  int options)
521     throws java.io.IOException JavaDoc, gnu.text.SyntaxException
522   {
523     return parse(getLexer(port, messages), options, null);
524   }
525
526   public final Compilation parse(InPort port,
527                                  gnu.text.SourceMessages messages,
528                                  ModuleInfo info)
529     throws java.io.IOException JavaDoc, gnu.text.SyntaxException
530   {
531     return parse(getLexer(port, messages), Language.PARSE_PROLOG, info);
532   }
533
534   public final Compilation parse(Lexer lexer, int options, ModuleInfo info)
535     throws java.io.IOException JavaDoc, gnu.text.SyntaxException
536   {
537     SourceMessages messages = lexer.getMessages();
538     Compilation tr = getCompilation(lexer, messages);
539     if (requirePedantic)
540       tr.pedantic = true;
541     tr.immediate = (options & PARSE_IMMEDIATE) != 0;
542     if ((options & PARSE_PROLOG) != 0)
543       tr.setState(Compilation.PROLOG_PARSING);
544     tr.pushNewModule(lexer);
545     if (info != null)
546       info.setCompilation(tr);
547     if (! parse(tr, options))
548       return null;
549     if (tr.getState() == Compilation.PROLOG_PARSING)
550       tr.setState(Compilation.PROLOG_PARSED);
551     return tr;
552   }
553
554   public abstract boolean parse (Compilation comp, int options)
555     throws java.io.IOException JavaDoc, gnu.text.SyntaxException;
556
557   /** Perform any need post-processing after we've read all the modules
558    * to be compiled.
559    * Using a separate pass allows compiling mutually recursive modules. */

560   public void resolve (Compilation comp)
561   {
562   }
563
564   public Type getTypeFor(Class JavaDoc clas)
565   {
566     return Type.make(clas);
567   }
568
569   public final Type getLangTypeFor (Type type)
570   {
571     if (! (type instanceof ObjectType) || ((ObjectType) type).isExisting())
572       {
573         Class JavaDoc clas = type.getReflectClass();
574         if (clas != null)
575           return getTypeFor(clas);
576       }
577     return type;
578   }
579
580   public static Type string2Type (String JavaDoc name)
581   {
582     Type t;
583     if (name.endsWith("[]"))
584       {
585     t = string2Type(name.substring(0, name.length()-2));
586     if (t == null)
587       return null;
588     t = gnu.bytecode.ArrayType.make(t);
589       }
590     else if (gnu.bytecode.Type.isValidJavaTypeName(name))
591       t = gnu.bytecode.Type.getType(name);
592     else
593       return null;
594     return t;
595   }
596
597   public Type getTypeFor (String JavaDoc name)
598   {
599     return string2Type(name);
600   }
601
602   public final Type getTypeFor (Object JavaDoc spec, boolean lenient)
603   {
604     if (spec instanceof Type)
605       return (Type) spec;
606     if (spec instanceof Class JavaDoc)
607       return getTypeFor((Class JavaDoc) spec);
608     if (lenient
609         && (spec instanceof FString
610             || spec instanceof String JavaDoc
611             || (spec instanceof Symbol && ((Symbol) spec).hasEmptyNamespace())
612             || spec instanceof CharSeq))
613       return getTypeFor(spec.toString());
614     if (spec instanceof Namespace)
615       {
616         String JavaDoc uri = ((Namespace) spec).getName();
617         if (uri != null && uri.startsWith("class:"))
618           return getLangTypeFor(string2Type(uri.substring(6)));
619       }
620     return null;
621   }
622
623   /** "Coerce" a language-specific "type specifier" object to a Type. */
624   public final Type asType(Object JavaDoc spec)
625   {
626     Type type = getTypeFor(spec, true);
627     return type == null ? (Type) spec : type;
628   }
629
630   public final Type getTypeFor (Expression exp)
631   {
632     return getTypeFor(exp, true);
633   }
634
635   public Type getTypeFor (Expression exp, boolean lenient)
636   {
637     if (exp instanceof QuoteExp)
638       {
639         return getTypeFor(((QuoteExp) exp).getValue(), lenient);
640       }
641     else if (exp instanceof ReferenceExp)
642       {
643         ReferenceExp rexp = (ReferenceExp) exp;
644         Declaration decl = Declaration.followAliases(rexp.getBinding());
645         String JavaDoc name = rexp.getName();
646         if (decl != null)
647       {
648         name = decl.getName();
649         exp = decl.getValue();
650         if (decl.isAlias()
651         && exp instanceof QuoteExp)
652           {
653         Object JavaDoc val = ((QuoteExp) exp).getValue();
654         if (val instanceof Location)
655           {
656             Location loc = (Location) val;
657             if (loc.isBound())
658               return asType(loc.get());
659             if (! (loc instanceof Named))
660               return null;
661             name = ((Named) loc).getName();
662           }
663           }
664         else if (! decl.getFlag(Declaration.IS_UNKNOWN))
665           return getTypeFor(exp, lenient);
666       }
667     Object JavaDoc val = getEnvironment().get(name);
668     if (val instanceof Type)
669       return (Type) val;
670         if (val instanceof ClassNamespace)
671           return ((ClassNamespace) val).getClassType();
672         int len = name.length();
673         if (len > 2 && name.charAt(0) == '<'
674             && name.charAt(len-1) == '>')
675           return getTypeFor(name.substring(1, len-1));
676       }
677     else if (exp instanceof ClassExp || exp instanceof ModuleExp)
678       {
679     return ((LambdaExp) exp).getType();
680       }
681     return null;
682   }
683
684   public Declaration declFromField (ModuleExp mod, Object JavaDoc fvalue, Field fld)
685   {
686     String JavaDoc fname = fld.getName();
687     Type ftype = fld.getType();
688     boolean isAlias = ftype.isSubtype(Compilation.typeLocation);
689     Object JavaDoc fdname;
690     // FIXME if fvalue is FieldLocation, and field is final,
691
// get name from value of field.
692
boolean isImportedInstance;
693     boolean externalAccess = false;
694     if ((isImportedInstance = fname.endsWith("$instance")))
695       fdname = fname;
696     else if (fvalue instanceof Named) // && ! isAlias
697
fdname = ((Named) fvalue).getSymbol();
698     else
699       {
700     // FIXME move this to demangleName
701
if (fname.startsWith(Declaration.PRIVATE_PREFIX))
702           {
703             externalAccess = true;
704             fname = fname.substring(Declaration.PRIVATE_PREFIX.length());
705           }
706     fdname = Compilation.demangleName(fname, true).intern();
707       }
708     Type dtype = isAlias ? Type.pointer_type
709       : getTypeFor(ftype.getReflectClass());
710     Declaration fdecl = mod.addDeclaration(fdname, dtype);
711     boolean isStatic = (fld.getModifiers() & Access.STATIC) != 0;
712     boolean isFinal = (fld.getModifiers() & Access.FINAL) != 0;
713     if (isAlias)
714       fdecl.setIndirectBinding(true);
715     else if (isFinal && ftype.isSubtype(Compilation.typeProcedure))
716       fdecl.setProcedureDecl(true);
717     if (isStatic)
718       fdecl.setFlag(Declaration.STATIC_SPECIFIED);
719     fdecl.field = fld;
720     if (isFinal && ! isAlias) // FIXME? ok for location?
721
fdecl.setFlag(Declaration.IS_CONSTANT);
722     if (isImportedInstance)
723       fdecl.setFlag(Declaration.MODULE_REFERENCE);
724     fdecl.setSimple(false);
725     if (externalAccess)
726       fdecl.setFlag(Declaration.EXTERNAL_ACCESS|Declaration.PRIVATE);
727     return fdecl;
728   }
729
730   public static final int VALUE_NAMESPACE = 1<<0;
731   public static final int FUNCTION_NAMESPACE = 1<<1;
732   public static final int NAMESPACE_PREFIX_NAMESPACE = 1<<2;
733
734   /** Return the namespace (e.g value or function) of a Declaration.
735    * Return a bitmask of all the namespaces "covered" by the Declaration.
736    * Note this isn't a namespace in the XML sense; if a Declaration has
737    * a specific namespace URI, then that is part of its symbol.
738    * This namespace bitmap is a separate dimension, for the use of
739    * languages that have separate namespaces for different kinds of
740    * declarations, such as variables and functions.
741    */

742   public int getNamespaceOf(Declaration decl)
743   {
744     return VALUE_NAMESPACE;
745   }
746
747   /** True if a Declaration is in the specified namespace.
748    * @param namespace normally a bitmask as returned by getNamespaceOf. */

749   public boolean hasNamespace (Declaration decl, int namespace)
750   {
751     return (getNamespaceOf(decl) & namespace) != 0;
752   }
753
754   public void emitPushBoolean(boolean value, CodeAttr code)
755   {
756     code.emitGetStatic(value ? Compilation.trueConstant
757                : Compilation.falseConstant);
758   }
759
760   /** Generate code to test if an object is considered true.
761    * Assume the object has been pushed on the JVM stack.
762    * Generate code to push true or false as appropriate. */

763   public void emitCoerceToBoolean(CodeAttr code)
764   {
765     emitPushBoolean(false, code);
766     code.emitIfNEq();
767     code.emitPushInt(1);
768     code.emitElse();
769     code.emitPushInt(0);
770     code.emitFi();
771   }
772
773   public Object JavaDoc coerceFromObject(Class JavaDoc clas, Object JavaDoc obj)
774   {
775     return getTypeFor(clas).coerceFromObject(obj);
776   }
777
778   public Object JavaDoc coerceToObject(Class JavaDoc clas, Object JavaDoc obj)
779   {
780     return getTypeFor(clas).coerceToObject(obj);
781   }
782
783   public Object JavaDoc coerceToObject(int val)
784   {
785     return gnu.math.IntNum.make(val);
786   }
787
788   public static synchronized void setDefaults (Language lang)
789   {
790     Language.setDefaultLanguage(lang);
791     current.setGlobal(lang);
792     // Assuming this is the initial (main) thread, make it's Environment
793
// the default (global) one, so child threads can inherit from it.
794
// Thus command-line definitions etc get inherited.
795
if (Environment.getGlobal() == BuiltinEnvironment.getInstance())
796       Environment.setGlobal(Environment.getCurrent());
797   }
798
799   public Procedure getPrompter()
800   {
801     Object JavaDoc property = null;
802     if (hasSeparateFunctionNamespace())
803       property = EnvironmentKey.FUNCTION;
804     Procedure prompter = (Procedure) getEnvironment()
805       .get(getSymbol("default-prompter"), property, null);
806     if (prompter != null)
807       return prompter;
808     else
809       return new SimplePrompter();
810   }
811
812   /** Return the result of evaluating a string as a source expression. */
813   public final Object JavaDoc eval (String JavaDoc string) throws Throwable JavaDoc
814   {
815     return eval(new CharArrayInPort(string));
816   }
817
818   /** Evaluate expression(s) read from a Reader.
819    * This just calls eval(InPort).
820    */

821   public final Object JavaDoc eval (Reader in) throws Throwable JavaDoc
822   {
823     return eval(in instanceof InPort ? (InPort) in : new InPort(in));
824   }
825
826   /** Evaluate expression(s) read from an InPort. */
827   public final Object JavaDoc eval (InPort port) throws Throwable JavaDoc
828   {
829     CallContext ctx = CallContext.getInstance();
830     int oldIndex = ctx.startFromContext();
831     try
832       {
833     eval(port, ctx);
834     return ctx.getFromContext(oldIndex);
835       }
836     catch (Throwable JavaDoc ex)
837       {
838     ctx.cleanupFromContext(oldIndex);
839     throw ex;
840       }
841   }
842
843   /** Evaluate a string and write the result value(s) on a Writer. */
844   public final void eval (String JavaDoc string, Writer out) throws Throwable JavaDoc
845   {
846     eval(new CharArrayInPort(string), out);
847   }
848
849   /** Evaluate a string and write the result value(s) to a PrintConsumer.
850    * This is to disambiguate calls using OutPort or XMLPrinter,
851    * which are both Writer and Consumer. */

852   public final void eval (String JavaDoc string, PrintConsumer out) throws Throwable JavaDoc
853   {
854     eval(string, getOutputConsumer(out));
855   }
856
857   /** Evaluate a string and write the result value(s) to a Consumer. */
858   public final void eval (String JavaDoc string, Consumer out) throws Throwable JavaDoc
859   {
860     eval(new CharArrayInPort(string), out);
861   }
862
863   /** Read expressions from a Reader and write the result to a Writer. */
864   public final void eval (Reader in, Writer out) throws Throwable JavaDoc
865   {
866     eval(in, getOutputConsumer(out));
867   }
868
869   /** Read expressions from a Reader and write the result to a Consumer. */
870   public void eval (Reader in, Consumer out) throws Throwable JavaDoc
871   {
872     InPort port = in instanceof InPort ? (InPort) in : new InPort(in);
873     CallContext ctx = CallContext.getInstance();
874     Consumer save = ctx.consumer;
875     try
876       {
877     ctx.consumer = out;
878     eval(port, ctx);
879       }
880     finally
881       {
882     ctx.consumer = save;
883       }
884   }
885
886   public void eval (InPort port, CallContext ctx) throws Throwable JavaDoc
887   {
888     SourceMessages messages = new SourceMessages();
889     Language saveLang = getDefaultLanguage();
890     setDefaultLanguage(this);
891     try
892       {
893     Compilation comp = parse(port, messages, PARSE_IMMEDIATE);
894     ModuleExp.evalModule(getEnvironment(), ctx, comp, null, null);
895       }
896     finally
897       {
898     setDefaultLanguage(saveLang);
899       }
900     if (messages.seenErrors())
901       throw new RuntimeException JavaDoc("invalid syntax in eval form:\n"
902                  + messages.toString(20));
903   }
904
905   static protected int env_counter = 0;
906
907   public void runAsApplication (String JavaDoc[] args)
908   {
909     setDefaults(this);
910     kawa.repl.main(args);
911   }
912 }
913
914 class SimplePrompter extends Procedure1
915 {
916   public String JavaDoc prefix = "[";
917   public String JavaDoc suffix = "] ";
918
919   public Object JavaDoc apply1 (Object JavaDoc arg)
920   {
921     if (arg instanceof InPort)
922       {
923     InPort port = (InPort) arg;
924     int line = port.getLineNumber() + 1;
925     if (line >= 0)
926       return prefix + line + suffix;
927       }
928     return suffix;
929   }
930
931   // The compiler finds registerEnvironment by using reflection.
932
//
933
// public static void registerEnvironment()
934
// { Environment.setGlobal(new ...().getEnvironment()); }
935
}
936
Popular Tags