001: // Copyright (c) 2001, 2004, 2005 Per M.A. Bothner
002: // This is free software; for terms and warranty disclaimer see ./COPYING.
003:
004: package gnu.kawa.lispexpr;
005:
006: import gnu.expr.*;
007: import gnu.mapping.*;
008: import gnu.text.*;
009: import gnu.lists.*;
010: import gnu.bytecode.Access;
011: import gnu.bytecode.Field;
012: import gnu.mapping.EnvironmentKey;
013: import gnu.kawa.reflect.StaticFieldLocation;
014: import kawa.lang.Translator; // FIXME
015: import kawa.lang.Syntax; // FIXME
016:
017: /** Language sub-class for Lisp-like languages (including Scheme). */
018:
019: public abstract class LispLanguage extends Language {
020: static public final String quote_sym = "quote";
021: static public final String unquote_sym = "unquote";
022: static public final String unquotesplicing_sym = "unquote-splicing";
023: static public final String quasiquote_sym = "quasiquote";
024: /** Used for Kawa infix ':' operator. */
025: static public final String lookup_sym = "$lookup$";
026:
027: /** The default <code>ReadTable</code> for this language. */
028: public ReadTable defaultReadTable = createReadTable();
029:
030: /** Create a fresh <code>ReadTable</code> appropriate for this language. */
031: public abstract ReadTable createReadTable();
032:
033: public Lexer getLexer(InPort inp, SourceMessages messages) {
034: return new LispReader(inp, messages);
035: }
036:
037: public Compilation getCompilation(Lexer lexer,
038: SourceMessages messages) {
039: return new Translator(this , messages);
040: }
041:
042: public boolean parse(Compilation comp, int options)
043: throws java.io.IOException, gnu.text.SyntaxException {
044: kawa.lang.Translator tr = (kawa.lang.Translator) comp;
045: Lexer lexer = tr.lexer;
046: ModuleExp mexp = tr.mainLambda;
047: Values forms = new Values();
048: LispReader reader = (LispReader) lexer;
049: Compilation save_comp = Compilation.getCurrent();
050: try {
051: Compilation.setCurrent(tr);
052: if (tr.pendingForm != null) {
053: tr.scanForm(tr.pendingForm, mexp);
054: tr.pendingForm = null;
055: }
056: for (;;) {
057: Object sexp = reader.readCommand();
058: if (sexp == Sequence.eofValue) {
059: if ((options & PARSE_ONE_LINE) != 0)
060: return false; // FIXME
061: break;
062: }
063: tr.scanForm(sexp, mexp);
064: if ((options & PARSE_ONE_LINE) != 0)
065: break;
066: if ((options & PARSE_PROLOG) != 0
067: && tr.getState() >= Compilation.PROLOG_PARSED) {
068: return true;
069: }
070: }
071: if (lexer.peek() == ')')
072: lexer.fatal("An unexpected close paren was read.");
073:
074: // Must be done before any other module imports this module.
075: tr.finishModule(mexp);
076:
077: if ((options & PARSE_PROLOG) == 0) {
078: tr.firstForm = 0;
079: }
080: tr.setState(Compilation.BODY_PARSED);
081: } finally {
082: Compilation.setCurrent(save_comp);
083: }
084: return true;
085: }
086:
087: /** Resolve names and other post-parsing processing. */
088: public void resolve(Compilation comp) {
089: Translator tr = (Translator) comp;
090: tr.resolveModule(tr.getModule());
091: }
092:
093: public Declaration declFromField(ModuleExp mod, Object fvalue,
094: Field fld) {
095: Declaration fdecl = super .declFromField(mod, fvalue, fld);
096: boolean isFinal = (fld.getModifiers() & Access.FINAL) != 0;
097: if (isFinal && fvalue instanceof Syntax) // FIXME - should check type? not value?
098: fdecl.setSyntax();
099: return fdecl;
100: }
101:
102: /** Declare in the current Environment a Syntax bound to a static field.
103: * @param name the procedure's source-level name.
104: * @param cname the name of the class containing the field.
105: * @param fname the name of the field, which should be a static
106: * final field whose type extends kawa.lang.Syntax.
107: */
108: protected void defSntxStFld(String name, String cname, String fname) {
109: Object property = hasSeparateFunctionNamespace() ? EnvironmentKey.FUNCTION
110: : null;
111: StaticFieldLocation loc = StaticFieldLocation.define(environ,
112: environ.getSymbol(name), property, cname, fname);
113: loc.setSyntax();
114: }
115:
116: protected void defSntxStFld(String name, String cname) {
117: defSntxStFld(name, cname, Compilation.mangleNameIfNeeded(name));
118: }
119:
120: /** Combine a <body> consisting of a list of expression. */
121: public Expression makeBody(Expression[] exps) {
122: return new BeginExp(exps);
123: }
124:
125: public Expression makeApply(Expression func, Expression[] args) {
126: return new ApplyExp(func, args);
127: }
128:
129: public boolean selfEvaluatingSymbol(Object obj) {
130: return obj instanceof Keyword;
131: }
132:
133: /** Convert the Language's idea of a symbol to a gnu.mapping.Symbol. */
134: public static Symbol langSymbolToSymbol(Object sym) {
135: return ((LispLanguage) Language.getDefaultLanguage())
136: .fromLangSymbol(sym);
137: }
138:
139: protected Symbol fromLangSymbol(Object sym) {
140: if (sym instanceof String)
141: return getSymbol((String) sym);
142: return (Symbol) sym;
143: }
144: }
|