0001: package kawa.lang;
0002:
0003: import gnu.mapping.*;
0004: import gnu.expr.*;
0005: import gnu.kawa.reflect.*;
0006: import gnu.bytecode.Type;
0007: import gnu.bytecode.ClassType;
0008: import gnu.text.SourceMessages;
0009: import gnu.lists.*;
0010: import gnu.kawa.lispexpr.*;
0011: import java.util.*;
0012: import gnu.kawa.functions.GetNamedPart;
0013: import gnu.text.SourceLocator;
0014:
0015: /** Used to translate from source to Expression.
0016: * The result has macros expanded, lexical names bound, etc, and is
0017: * ready for code generation.
0018: * This is sometimes called a "compilation environment",
0019: * but we modify it as we go along - there is a single Translator for
0020: * each top-level form.
0021: */
0022:
0023: public class Translator extends Compilation {
0024: // Global environment used to look for syntax/macros.
0025: private Environment env;
0026:
0027: /** Set if we're processing (as opposed to expanding)
0028: * a <code>define-syntax</code> or <code>defmacro</code>. */
0029: public Macro currentMacroDefinition;
0030:
0031: /** Innermost current scope of pattern variable,
0032: * from a <code>syntax-case</code>. */
0033: public PatternScope patternScope;
0034:
0035: public Declaration templateScopeDecl;
0036:
0037: /** A variable to hold the matched values for syntax-case
0038: * pattern variables. */
0039: public Declaration matchArray;
0040:
0041: /** A stack of aliases pushed by <code>pushRenamedAlias</code>. */
0042: Stack renamedAliasStack;
0043:
0044: public Stack formStack = new Stack();
0045: public int firstForm;
0046: public Object pendingForm;
0047:
0048: public LambdaExp curMethodLambda;
0049:
0050: /** Return true if decl is lexical and not fluid. */
0051: public boolean isLexical(Declaration decl) {
0052: if (decl == null)
0053: return false;
0054: if (!decl.isFluid())
0055: return true;
0056: ScopeExp scope = currentScope();
0057: ScopeExp context = decl.getContext();
0058: for (;; scope = scope.outer) {
0059: if (scope == null)
0060: return false;
0061: if (scope == context)
0062: return true;
0063: if (scope instanceof LambdaExp
0064: && !((LambdaExp) scope).getInlineOnly())
0065: return false;
0066: }
0067: }
0068:
0069: private static Expression errorExp = new ErrorExp(
0070: "unknown syntax error");
0071:
0072: public Translator(Language language, SourceMessages messages) {
0073: super (language, messages);
0074: this .env = Environment.getCurrent();
0075: }
0076:
0077: public final Environment getGlobalEnvironment() {
0078: return env;
0079: }
0080:
0081: public Expression parse(Object input) {
0082: return rewrite(input);
0083: }
0084:
0085: public final Expression rewrite_car(Pair pair, SyntaxForm syntax) {
0086: if (syntax == null || syntax.scope == current_scope
0087: || pair.car instanceof SyntaxForm)
0088: return rewrite_car(pair, false);
0089: ScopeExp save_scope = current_scope;
0090: try {
0091: setCurrentScope(syntax.scope);
0092: return rewrite_car(pair, false);
0093: } finally {
0094: setCurrentScope(save_scope);
0095: }
0096: }
0097:
0098: public final Expression rewrite_car(Pair pair, boolean function) {
0099: Object car = pair.car;
0100: if (pair instanceof PairWithPosition)
0101: return rewrite_with_position(car, function,
0102: (PairWithPosition) pair);
0103: else
0104: return rewrite(car, function);
0105: }
0106:
0107: Syntax currentSyntax;
0108:
0109: public Syntax getCurrentSyntax() {
0110: return currentSyntax;
0111: }
0112:
0113: /** The module instance containing the current macro.
0114: * This is only used temporarily, set when resolving a Declaration
0115: * bound to a macro, and used to set the macroContext field of the
0116: * TemplateScope created when expanding the macro's template(s). */
0117: Declaration macroContext;
0118:
0119: /**
0120: * Apply a Syntax object.
0121: * @param syntax the Syntax object whose rewrite method we call
0122: * @param form the syntax form (including the macro name)
0123: * @return the re-written form as an Expression object
0124: */
0125: Expression apply_rewrite(Syntax syntax, Pair form) {
0126: Expression exp = errorExp;
0127: Syntax saveSyntax = currentSyntax;
0128: currentSyntax = syntax;
0129: try {
0130: exp = syntax.rewriteForm(form, this );
0131: } finally {
0132: currentSyntax = saveSyntax;
0133: }
0134: return exp;
0135: }
0136:
0137: /** Check if declaraton is an alias for some other name.
0138: * This is needed to chase identifiers renamed for hygienic macro
0139: * expansion - see SyntaxRules.expand. */
0140: static ReferenceExp getOriginalRef(Declaration decl) {
0141: if (decl != null && decl.isAlias() && !decl.isIndirectBinding()) {
0142: Expression value = decl.getValue();
0143: if (value instanceof ReferenceExp)
0144: return (ReferenceExp) value;
0145: }
0146: return null;
0147: }
0148:
0149: final boolean selfEvaluatingSymbol(Object obj) {
0150: return ((LispLanguage) getLanguage()).selfEvaluatingSymbol(obj);
0151: }
0152:
0153: /** True iff a form matches a literal symbol. */
0154: public final boolean matches(Object form, String literal) {
0155: return matches(form, null, literal);
0156: }
0157:
0158: public boolean matches(Object form, SyntaxForm syntax,
0159: String literal) {
0160: if (syntax != null) {
0161: // FIXME
0162: }
0163: if (form instanceof SyntaxForm) {
0164: // FIXME
0165: return literal == ((SyntaxForm) form).form;
0166: }
0167: if (form instanceof Symbol && !selfEvaluatingSymbol(form)) {
0168: ReferenceExp rexp = getOriginalRef(lexical.lookup(form, -1));
0169: if (rexp != null)
0170: form = rexp.getSymbol();
0171: }
0172: return form == literal;
0173: }
0174:
0175: public Declaration lookup(Object name, int namespace) {
0176: Declaration decl = lexical.lookup(name, namespace);
0177: if (decl != null && getLanguage().hasNamespace(decl, namespace))
0178: return decl;
0179: return currentModule().lookup(name, getLanguage(), namespace);
0180: }
0181:
0182: /** Find global Declaration, creating one if not found. */
0183: public Declaration lookupGlobal(Object name) {
0184: return lookupGlobal(name, -1);
0185: }
0186:
0187: /** Find global Declaration, creating one if not found. */
0188: public Declaration lookupGlobal(Object name, int namespace) {
0189: ModuleExp module = currentModule();
0190: Declaration decl = module
0191: .lookup(name, getLanguage(), namespace);
0192: if (decl == null) {
0193: decl = module.getNoDefine(name);
0194: decl.setIndirectBinding(true);
0195: }
0196: return decl;
0197: }
0198:
0199: /** Check if a Declaration is bound to a Syntax.
0200: * @param decl the Declaration to check
0201: * @return the Syntax bound to decl, or null.
0202: * In the former case, macroContext may be set as a side effect.
0203: */
0204: Syntax check_if_Syntax(Declaration decl) {
0205: Declaration d = Declaration.followAliases(decl);
0206:
0207: Expression dval = d.getValue();
0208: if (dval != null && d.getFlag(Declaration.IS_SYNTAX)) {
0209: try {
0210: if (decl.getValue() instanceof ReferenceExp) {
0211: Declaration context = ((ReferenceExp) decl
0212: .getValue()).contextDecl();
0213: if (context != null)
0214: macroContext = context;
0215: else if (current_scope instanceof TemplateScope)
0216: macroContext = ((TemplateScope) current_scope).macroContext;
0217: } else if (current_scope instanceof TemplateScope)
0218: macroContext = ((TemplateScope) current_scope).macroContext;
0219: Object obj = dval.eval(env);
0220: return obj instanceof Syntax ? (Syntax) obj : null;
0221: } catch (Throwable ex) {
0222: ex.printStackTrace();
0223: error('e', "unable to evaluate macro for "
0224: + decl.getSymbol());
0225: }
0226: }
0227: return null;
0228: }
0229:
0230: public Expression rewrite_pair(Pair p, boolean function) {
0231: if (p.car instanceof Syntax)
0232: return apply_rewrite((Syntax) p.car, p);
0233: Object cdr = p.cdr;
0234:
0235: Expression func = rewrite_car(p, true);
0236: Object proc = null;
0237: ReferenceExp ref = null;
0238: if (func instanceof ReferenceExp) {
0239: ref = (ReferenceExp) func;
0240: Declaration decl = ref.getBinding();
0241: if (decl == null) {
0242: Object sym = ref.getSymbol();
0243: Symbol symbol;
0244: String name;
0245: if (sym instanceof Symbol && !selfEvaluatingSymbol(sym)) {
0246: symbol = (Symbol) sym;
0247: name = symbol.getName();
0248: } else {
0249: name = sym.toString();
0250: symbol = env.getSymbol(name);
0251: }
0252: proc = env
0253: .get(
0254: symbol,
0255: getLanguage()
0256: .hasSeparateFunctionNamespace() ? EnvironmentKey.FUNCTION
0257: : null, null);
0258: if (proc instanceof Syntax)
0259: return apply_rewrite((Syntax) proc, p);
0260: if (proc instanceof AutoloadProcedure) {
0261: try {
0262: proc = ((AutoloadProcedure) proc).getLoaded();
0263: } catch (RuntimeException ex) {
0264: proc = null;
0265: }
0266: }
0267: } else {
0268: Declaration saveContext = macroContext;
0269: Syntax syntax = check_if_Syntax(decl);
0270: if (syntax != null) {
0271: Expression e = apply_rewrite(syntax, p);
0272: macroContext = saveContext;
0273: return e;
0274: }
0275: }
0276:
0277: ref.setProcedureName(true);
0278: if (getLanguage().hasSeparateFunctionNamespace())
0279: func.setFlag(ReferenceExp.PREFER_BINDING2);
0280: }
0281:
0282: int cdr_length = listLength(cdr);
0283:
0284: if (cdr_length == -1)
0285: return syntaxError("circular list is not allowed after "
0286: + p.car);
0287: if (cdr_length < 0)
0288: return syntaxError("dotted list [" + cdr
0289: + "] is not allowed after " + p.car);
0290:
0291: boolean mapKeywordsToAttributes = false;
0292: Stack vec = new Stack();
0293:
0294: ScopeExp save_scope = current_scope;
0295: for (int i = 0; i < cdr_length;) {
0296: if (cdr instanceof SyntaxForm) {
0297: SyntaxForm sf = (SyntaxForm) cdr;
0298: cdr = sf.form;
0299: setCurrentScope(sf.scope);
0300: }
0301: Pair cdr_pair = (Pair) cdr;
0302: Expression arg = rewrite_car(cdr_pair, false);
0303: i++;
0304:
0305: if (mapKeywordsToAttributes) {
0306: if ((i & 1) == 0) // Previous iteration was a keyword
0307: {
0308: Expression[] aargs = new Expression[2];
0309: aargs[0] = (Expression) vec.pop();
0310: aargs[1] = arg;
0311: arg = new ApplyExp(
0312: gnu.kawa.xml.MakeAttribute.makeAttribute,
0313: aargs);
0314: } else {
0315: Object value;
0316: if (arg instanceof QuoteExp
0317: && (value = ((QuoteExp) arg).getValue()) instanceof Keyword
0318: && i < cdr_length)
0319: arg = new QuoteExp(((Keyword) value).asSymbol());
0320: else
0321: mapKeywordsToAttributes = false;
0322: }
0323: }
0324:
0325: vec.addElement(arg);
0326: cdr = cdr_pair.cdr;
0327: }
0328: Expression[] args = new Expression[vec.size()];
0329: vec.copyInto(args);
0330:
0331: if (save_scope != current_scope)
0332: setCurrentScope(save_scope);
0333:
0334: return ((LispLanguage) getLanguage()).makeApply(func, args);
0335: }
0336:
0337: public Symbol namespaceResolve(Expression context, Expression member) {
0338: if (context instanceof ReferenceExp
0339: && member instanceof QuoteExp) {
0340: ReferenceExp rexp = (ReferenceExp) context;
0341: Declaration decl = rexp.getBinding();
0342: Object val;
0343: if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN)) {
0344: Object rsym = rexp.getSymbol();
0345: Symbol sym = rsym instanceof Symbol ? (Symbol) rsym
0346: : env.getSymbol(rsym.toString());
0347: val = env.get(sym, null);
0348: } else if (decl.isNamespaceDecl()) {
0349: val = decl.getConstantValue();
0350: } else
0351: val = null;
0352: if (val instanceof Namespace) {
0353: Namespace ns = (Namespace) val;
0354: String uri = ns.getName();
0355: if (uri != null && uri.startsWith("class:"))
0356: return null;
0357: String mem = ((QuoteExp) member).getValue().toString()
0358: .intern();
0359: return ns.getSymbol(mem);
0360: }
0361: }
0362: return null;
0363: }
0364:
0365: public static Object stripSyntax(Object obj) {
0366: while (obj instanceof SyntaxForm)
0367: obj = ((SyntaxForm) obj).form;
0368: return obj;
0369: }
0370:
0371: public static Object safeCar(Object obj) {
0372: while (obj instanceof SyntaxForm)
0373: obj = ((SyntaxForm) obj).form;
0374: if (!(obj instanceof Pair))
0375: return null;
0376: return stripSyntax(((Pair) obj).car);
0377: }
0378:
0379: public static Object safeCdr(Object obj) {
0380: while (obj instanceof SyntaxForm)
0381: obj = ((SyntaxForm) obj).form;
0382: if (!(obj instanceof Pair))
0383: return null;
0384: return stripSyntax(((Pair) obj).cdr);
0385: }
0386:
0387: /** Returns the length of a syntax list.
0388: * Returns Integer.MIN_VALUE for cyclic lists.
0389: * For impure lists returns the negative of one more than
0390: * the number of pairs before the "dot".
0391: * Similar to LList.listLength, but descends into SyntaxForm. */
0392: public static int listLength(Object obj) {
0393: // Based on list-length implementation in
0394: // Guy L Steele jr: "Common Lisp: The Language", 2nd edition, page 414
0395: int n = 0;
0396: Object slow = obj;
0397: Object fast = obj;
0398: for (;;) {
0399: // 'n' is number of previous Pairs before 'fast' cursor.
0400: while (fast instanceof SyntaxForm)
0401: fast = ((SyntaxForm) fast).form;
0402: while (slow instanceof SyntaxForm)
0403: slow = ((SyntaxForm) slow).form;
0404: if (fast == LList.Empty)
0405: return n;
0406: if (!(fast instanceof Pair))
0407: return -1 - n;
0408: n++;
0409: Object next = ((Pair) fast).cdr;
0410: while (next instanceof SyntaxForm)
0411: next = ((SyntaxForm) next).form;
0412: if (next == LList.Empty)
0413: return n;
0414: if (!(next instanceof Pair))
0415: return -1 - n;
0416: slow = ((Pair) slow).cdr;
0417: fast = ((Pair) next).cdr;
0418: n++;
0419: if (fast == slow)
0420: return Integer.MIN_VALUE;
0421: }
0422: }
0423:
0424: public void rewriteInBody(Object exp) {
0425: if (exp instanceof SyntaxForm) {
0426: SyntaxForm sf = (SyntaxForm) exp;
0427: ScopeExp save_scope = current_scope;
0428: try {
0429: setCurrentScope(sf.scope);
0430: rewriteInBody(sf.form);
0431: } finally {
0432: setCurrentScope(save_scope);
0433: }
0434: } else if (exp instanceof Values) {
0435: Object[] vals = ((Values) exp).getValues();
0436: for (int i = 0; i < vals.length; i++)
0437: rewriteInBody(vals[i]);
0438: } else
0439: formStack.add(rewrite(exp, false));
0440: }
0441:
0442: /**
0443: * Re-write a Scheme expression in S-expression format into internal form.
0444: */
0445: public Expression rewrite(Object exp) {
0446: return rewrite(exp, false);
0447: }
0448:
0449: public Object namespaceResolve(Object name) {
0450: if (!(name instanceof String)) {
0451: Pair p;
0452: if (name instanceof Pair
0453: && safeCar(p = (Pair) name) == LispLanguage.lookup_sym
0454: && p.cdr instanceof Pair
0455: && (p = (Pair) p.cdr).cdr instanceof Pair) {
0456: Expression part1 = rewrite(p.car);
0457: Expression part2 = rewrite(((Pair) p.cdr).car);
0458:
0459: Symbol sym = namespaceResolve(part1, part2);
0460: if (sym != null)
0461: return sym;
0462: String combinedName = GetNamedPart.combineName(part1,
0463: part2);
0464: if (combinedName != null)
0465: return combinedName;
0466: }
0467: }
0468: return name;
0469: }
0470:
0471: public void setCurrentScope(ScopeExp scope) {
0472: super .setCurrentScope(scope);
0473: while (scope != null && !(scope instanceof PatternScope))
0474: scope = scope.outer;
0475: patternScope = (PatternScope) scope;
0476: }
0477:
0478: /**
0479: * Re-write a Scheme expression in S-expression format into internal form.
0480: */
0481: public Expression rewrite(Object exp, boolean function) {
0482: if (exp instanceof SyntaxForm) {
0483: SyntaxForm sf = (SyntaxForm) exp;
0484: ScopeExp save_scope = current_scope;
0485: try {
0486: setCurrentScope(sf.scope);
0487: Expression s = rewrite(sf.form, function);
0488: return s;
0489: } finally {
0490: setCurrentScope(save_scope);
0491: }
0492: }
0493: if (exp instanceof PairWithPosition)
0494: return rewrite_with_position(exp, function,
0495: (PairWithPosition) exp);
0496: else if (exp instanceof Pair)
0497: return rewrite_pair((Pair) exp, function);
0498: else if (exp instanceof String
0499: || (exp instanceof Symbol && !selfEvaluatingSymbol(exp))) {
0500: Declaration decl = lexical.lookup(exp, function);
0501: Declaration cdecl = null;
0502:
0503: // If we're nested inside a class (in a ClassExp) then the field
0504: // and methods names of this class and super-classes/interfaces
0505: // need to be searched.
0506: ScopeExp scope = current_scope;
0507: int decl_nesting = decl == null ? -1 : ScopeExp
0508: .nesting(decl.context);
0509: String dname;
0510: if (exp instanceof String
0511: || (exp instanceof Symbol && ((Symbol) exp)
0512: .hasEmptyNamespace()))
0513: dname = exp.toString();
0514: else {
0515: dname = null;
0516: scope = null;
0517: }
0518: for (; scope != null; scope = scope.outer) {
0519: if (scope instanceof LambdaExp
0520: && scope.outer instanceof ClassExp // redundant? FIXME
0521: && ((LambdaExp) scope).isClassMethod()) {
0522: if (decl_nesting >= ScopeExp.nesting(scope.outer))
0523: break;
0524: LambdaExp caller = (LambdaExp) scope;
0525: ClassExp cexp = (ClassExp) scope.outer;
0526: ClassType ctype = (ClassType) cexp.getType();
0527: Object part = SlotGet.lookupMember(ctype, dname,
0528: ctype);
0529: boolean contextStatic = (caller == cexp.clinitMethod || (caller != cexp.initMethod && caller.nameDecl
0530: .isStatic()));
0531: if (part == null) {
0532: char mode = contextStatic ? 'S' : 'V';
0533: PrimProcedure[] methods = ClassMethods
0534: .getMethods(ctype, dname, mode, ctype,
0535: language);
0536: if (methods.length == 0)
0537: continue;
0538: }
0539: Expression part1;
0540: // FIXME We're throwing away 'part', which is wasteful.
0541: if (contextStatic)
0542: part1 = new ReferenceExp(
0543: ((ClassExp) caller.outer).nameDecl);
0544: else
0545: part1 = new ThisExp(caller.firstDecl());
0546: return GetNamedPart.makeExp(part1, QuoteExp
0547: .getInstance(dname));
0548: }
0549: }
0550:
0551: Object nameToLookup;
0552: Symbol symbol = null;
0553: if (decl != null) {
0554: nameToLookup = decl.getSymbol();
0555: exp = null;
0556: ReferenceExp rexp = getOriginalRef(decl);
0557: if (rexp != null) {
0558: decl = rexp.getBinding();
0559: if (decl == null) {
0560: exp = rexp.getSymbol();
0561: nameToLookup = exp;
0562: }
0563: }
0564: } else {
0565: nameToLookup = exp;
0566: }
0567: symbol = exp instanceof String ? env
0568: .getSymbol((String) exp) : (Symbol) exp;
0569: boolean separate = getLanguage()
0570: .hasSeparateFunctionNamespace();
0571: if (decl != null) {
0572: if (!isLexical(decl)
0573: || (separate && decl.isProcedureDecl()))
0574: decl = null;
0575: else if (current_scope instanceof TemplateScope
0576: && decl.needsContext())
0577: cdecl = ((TemplateScope) current_scope).macroContext;
0578: else if (decl.getFlag(Declaration.FIELD_OR_METHOD)
0579: && !decl.isStatic()) {
0580: scope = currentScope();
0581: for (;;) {
0582: if (scope == null)
0583: throw new Error("internal error: missing "
0584: + decl);
0585: if (scope.outer == decl.context) // I.e. same class.
0586: break;
0587: scope = scope.outer;
0588: }
0589: cdecl = scope.firstDecl();
0590: }
0591: } else {
0592: Location loc = env.lookup(symbol,
0593: function && separate ? EnvironmentKey.FUNCTION
0594: : null);
0595: if (loc != null)
0596: loc = loc.getBase();
0597: if (loc instanceof FieldLocation) {
0598: FieldLocation floc = (FieldLocation) loc;
0599: try {
0600: decl = floc.getDeclaration();
0601: if (!inlineOk(null)
0602: // A kludge - we get a bunch of testsuite failures
0603: // if we don't inline $lookup$. FIXME.
0604: && decl != kawa.standard.Scheme.getNamedPartDecl)
0605: decl = null;
0606: if (decl != null && !decl.isStatic()) {
0607: cdecl = new Declaration("(module-instance)");
0608: cdecl.setValue(new QuoteExp(floc
0609: .getInstance()));
0610: }
0611: } catch (Throwable ex) {
0612: error('e', "exception loading '" + exp + "' - "
0613: + ex.getMessage());
0614: decl = null;
0615: }
0616: }
0617: /*
0618: else if (Compilation.inlineOk && function)
0619: {
0620: // Questionable. fail with new set_b implementation,
0621: // which just call rewrite_car on the lhs,
0622: // if we don't require function to be true. FIXME.
0623: decl = Declaration.getDeclaration(proc);
0624: }
0625: */
0626: }
0627: if (decl != null
0628: && decl.getContext() instanceof PatternScope)
0629: return syntaxError("reference to pattern variable "
0630: + decl.getName() + " outside syntax template");
0631:
0632: ReferenceExp rexp = new ReferenceExp(nameToLookup, decl);
0633: rexp.setContextDecl(cdecl);
0634: rexp.setLine(this );
0635: if (function && separate)
0636: rexp.setFlag(ReferenceExp.PREFER_BINDING2);
0637: return rexp;
0638: } else if (exp instanceof LangExp)
0639: return rewrite(((LangExp) exp).getLangValue(), function);
0640: else if (exp instanceof Expression)
0641: return (Expression) exp;
0642: else
0643: return QuoteExp.getInstance(Quote.quote(exp, this ));
0644: }
0645:
0646: public static void setLine(Expression exp, Object location) {
0647: if (location instanceof SourceLocator)
0648: exp.setLocation((SourceLocator) location);
0649: }
0650:
0651: public static void setLine(Declaration decl, Object location) {
0652: if (location instanceof SourceLocator)
0653: decl.setLocation((SourceLocator) location);
0654: }
0655:
0656: PairWithPosition positionPair;
0657:
0658: /** Note current line number position from a PairWithPosition.
0659: * Return an object to pass to popPositionOf.
0660: */
0661: public Object pushPositionOf(Object pair) {
0662: if (pair instanceof SyntaxForm)
0663: pair = ((SyntaxForm) pair).form;
0664: if (!(pair instanceof PairWithPosition))
0665: return null;
0666: PairWithPosition ppair = (PairWithPosition) pair;
0667: Object saved;
0668: if (positionPair == null
0669: || positionPair.getFileName() != getFileName()
0670: || positionPair.getLineNumber() != getLineNumber()
0671: || positionPair.getColumnNumber() != getColumnNumber()) {
0672: saved = new PairWithPosition(this , Special.eof,
0673: positionPair);
0674: } else
0675: saved = positionPair;
0676: setLine(pair);
0677: positionPair = ppair;
0678: return saved;
0679: }
0680:
0681: /** Restore line number position from a previous pushPositionOf.
0682: * @param saved value returned by matching pushPositionOf.
0683: */
0684: public void popPositionOf(Object saved) {
0685: if (saved == null)
0686: return;
0687: setLine(saved);
0688: positionPair = (PairWithPosition) saved;
0689: if (positionPair.car == Special.eof)
0690: positionPair = (PairWithPosition) positionPair.cdr;
0691: }
0692:
0693: /** Set the line position of the argument to the current position. */
0694:
0695: public void setLineOf(Expression exp) {
0696: if (exp instanceof QuoteExp)
0697: return;
0698: exp.setLocation(this );
0699: }
0700:
0701: /** Extract a type from the car of a pair. */
0702: public Type exp2Type(Pair typeSpecPair) {
0703: Object saved = pushPositionOf(typeSpecPair);
0704: try {
0705: Expression texp = rewrite_car(typeSpecPair, false);
0706: texp = new InlineCalls(this ).walk(texp);
0707: if (texp instanceof ErrorExp)
0708: return null;
0709: texp = new InlineCalls(this ).walk(texp);
0710: Type type = getLanguage().getTypeFor(texp);
0711: if (type == null) {
0712: if (texp instanceof ReferenceExp)
0713: error('e', "unknown type name '"
0714: + ((ReferenceExp) texp).getName() + '\'');
0715: else
0716: error('e',
0717: "invalid type spec (must be \"type\" or 'type or <type>)");
0718: return Type.pointer_type;
0719: }
0720: return type;
0721: } finally {
0722: popPositionOf(saved);
0723: }
0724: }
0725:
0726: public Expression rewrite_with_position(Object exp,
0727: boolean function, PairWithPosition pair) {
0728: Object saved = pushPositionOf(pair);
0729: Expression result;
0730: try {
0731: if (exp == pair)
0732: result = rewrite_pair(pair, function); // To avoid a cycle
0733: else
0734: result = rewrite(exp, function);
0735: setLineOf(result);
0736: } finally {
0737: popPositionOf(saved);
0738: }
0739: return result;
0740: }
0741:
0742: public static Object wrapSyntax(Object form, SyntaxForm syntax) {
0743: if (syntax == null || form instanceof Expression)
0744: return form;
0745: else
0746: return syntax.fromDatumIfNeeded(form);
0747: }
0748:
0749: public Object popForms(int first) {
0750: int last = formStack.size();
0751: if (last == first)
0752: return Values.empty;
0753: Object r;
0754: if (last == first + 1)
0755: r = formStack.elementAt(first);
0756: else {
0757: Values vals = new Values();
0758: for (int i = first; i < last; i++)
0759: vals.writeObject(formStack.elementAt(i));
0760: r = vals;
0761: }
0762: formStack.setSize(first);
0763: return r;
0764: }
0765:
0766: public void scanForm(Object st, ScopeExp defs) {
0767: if (st instanceof SyntaxForm) {
0768: SyntaxForm sf = (SyntaxForm) st;
0769: ScopeExp save_scope = currentScope();
0770: try {
0771: setCurrentScope(sf.scope);
0772: int first = formStack.size();
0773: scanForm(sf.form, defs);
0774: formStack.add(wrapSyntax(popForms(first), sf));
0775: return;
0776: } finally {
0777: setCurrentScope(save_scope);
0778: }
0779: }
0780: if (st instanceof Values) {
0781: if (st == Values.empty)
0782: st = QuoteExp.voidExp; // From #!void
0783: else {
0784: Object[] vals = ((Values) st).getValues();
0785: for (int i = 0; i < vals.length; i++)
0786: scanForm(vals[i], defs);
0787: return;
0788: }
0789: }
0790: if (st instanceof Pair) {
0791: Pair st_pair = (Pair) st;
0792: Declaration saveContext = macroContext;
0793: Syntax syntax = null;
0794: ScopeExp save_scope = current_scope;
0795: try {
0796: Object obj = st_pair.car;
0797: if (obj instanceof SyntaxForm) {
0798: SyntaxForm sf = (SyntaxForm) st_pair.car;
0799: setCurrentScope(sf.scope);
0800: obj = sf.form;
0801: }
0802: Pair p;
0803: if (obj instanceof Pair
0804: && (p = (Pair) obj).car == LispLanguage.lookup_sym
0805: && p.cdr instanceof Pair
0806: && (p = (Pair) p.cdr).cdr instanceof Pair) {
0807: Expression part1 = rewrite(p.car);
0808: Expression part2 = rewrite(((Pair) p.cdr).car);
0809: obj = namespaceResolve(part1, part2);
0810: }
0811: if (obj instanceof String
0812: || (obj instanceof Symbol && !selfEvaluatingSymbol(obj))) {
0813: Expression func = rewrite(obj, true);
0814: if (func instanceof ReferenceExp) {
0815: Declaration decl = ((ReferenceExp) func)
0816: .getBinding();
0817: if (decl != null)
0818: syntax = check_if_Syntax(decl);
0819: else {
0820: obj = resolve(obj, true);
0821: if (obj instanceof Syntax)
0822: syntax = (Syntax) obj;
0823: }
0824: }
0825: }
0826: // Recognize deferred begin created in scanBody for pendingForms.
0827: // A seemingly-cleaned (obj instanceof Syntax) causes problems
0828: // with some Syntax forms, such as define.
0829: else if (obj == kawa.standard.begin.begin)
0830: syntax = (Syntax) obj;
0831: } finally {
0832: if (save_scope != current_scope)
0833: setCurrentScope(save_scope);
0834: }
0835: if (syntax != null) {
0836: String save_filename = getFileName();
0837: int save_line = getLineNumber();
0838: int save_column = getColumnNumber();
0839: try {
0840: setLine(st_pair);
0841: syntax.scanForm(st_pair, defs, this );
0842: return;
0843: } finally {
0844: macroContext = saveContext;
0845: setLine(save_filename, save_line, save_column);
0846: }
0847: }
0848: }
0849: formStack.add(st);
0850: }
0851:
0852: /** Recursive helper method for rewrite_body.
0853: * Scan body for definitions, adding partially macro-expanded
0854: * expressions into the <code>formStack</code>.
0855: * @param makeList if true, return a list representation of the scanned
0856: * forms (not including declarations); else forms are push on formStack
0857: * @return a list of forms if <code>makeList</code> (possibly wrapped
0858: * in a <code>SyntaxForm</code>); otherwise <code>null</code>.
0859: */
0860:
0861: public Object scanBody(Object body, ScopeExp defs, boolean makeList) {
0862: Object list = makeList ? LList.Empty : null;
0863: Pair lastPair = null;
0864: while (body != LList.Empty) {
0865: if (body instanceof SyntaxForm) {
0866: SyntaxForm sf = (SyntaxForm) body;
0867: ScopeExp save_scope = current_scope;
0868: try {
0869: setCurrentScope(sf.scope);
0870: int first = formStack.size();
0871: Object f = scanBody(sf.form, defs, makeList);
0872: if (makeList) {
0873: f = wrapSyntax(f, sf);
0874: if (lastPair == null)
0875: return f;
0876: lastPair.cdr = f;
0877: return list;
0878: }
0879: formStack.add(wrapSyntax(popForms(first), sf));
0880: return null;
0881: } finally {
0882: setCurrentScope(save_scope);
0883: }
0884: } else if (body instanceof Pair) {
0885: Pair pair = (Pair) body;
0886: int first = formStack.size();
0887: scanForm(pair.car, defs);
0888: if (getState() == Compilation.PROLOG_PARSED) {
0889: // We've seen a require form during the initial pass when
0890: // we're looking module names. Defer the require and any
0891: // following forms in this body.
0892: if (pair.car != pendingForm)
0893: pair = makePair(pair, pendingForm, pair.cdr);
0894: pendingForm = new Pair(kawa.standard.begin.begin,
0895: pair);
0896: return LList.Empty;
0897: }
0898: int fsize = formStack.size();
0899: if (makeList) {
0900: for (int i = first; i < fsize; i++) {
0901: Pair npair = makePair(pair, formStack
0902: .elementAt(i), LList.Empty);
0903: if (lastPair == null)
0904: list = npair;
0905: else
0906: lastPair.cdr = npair;
0907: lastPair = npair;
0908: }
0909: formStack.setSize(first);
0910: }
0911: body = pair.cdr;
0912: } else {
0913: formStack.add(syntaxError("body is not a proper list"));
0914: break;
0915: }
0916: }
0917: return list;
0918: }
0919:
0920: public static Pair makePair(Pair pair, Object car, Object cdr) {
0921: if (pair instanceof PairWithPosition)
0922: return new PairWithPosition((PairWithPosition) pair, car,
0923: cdr);
0924: return new Pair(car, cdr);
0925: }
0926:
0927: /**
0928: * Re-write a Scheme <body> in S-expression format into internal form.
0929: */
0930:
0931: public Expression rewrite_body(Object exp) {
0932: // NOTE we have both a rewrite_body and a rewriteBody.
0933: // This is confusing, at the least. FIXME.
0934: Object saved = pushPositionOf(exp);
0935: LetExp defs = new LetExp(null);
0936: int first = formStack.size();
0937: defs.outer = current_scope;
0938: current_scope = defs;
0939: try {
0940: scanBody(exp, defs, false);
0941: if (formStack.size() == first)
0942: formStack.add(syntaxError("body with no expressions"));
0943: int ndecls = defs.countDecls();
0944: if (ndecls != 0) {
0945: Expression[] inits = new Expression[ndecls];
0946: for (int i = ndecls; --i >= 0;)
0947: inits[i] = QuoteExp.undefined_exp;
0948: defs.inits = inits;
0949: }
0950: Expression body = makeBody(first, null);
0951: setLineOf(body);
0952: if (ndecls == 0)
0953: return body;
0954: defs.body = body;
0955: setLineOf(defs);
0956: return defs;
0957: } finally {
0958: pop(defs);
0959: popPositionOf(saved);
0960: }
0961: }
0962:
0963: /* Rewrite forms on formStack above first. */
0964: public void rewriteBody(int first) {
0965: int nforms = formStack.size() - first;
0966: if (nforms == 0)
0967: return;
0968: else if (nforms == 1) {
0969: Object f = formStack.pop();
0970: rewriteInBody(f);
0971: } else {
0972: Object[] forms = new Object[nforms];
0973: for (int i = 0; i < nforms; i++)
0974: forms[i] = formStack.elementAt(first + i);
0975: formStack.setSize(first);
0976: for (int i = 0; i < nforms; i++)
0977: rewriteInBody(forms[i]);
0978: }
0979: }
0980:
0981: /** Combine a list of zero or more expression forms into a "body". */
0982: public Expression makeBody(int first, ScopeExp scope) {
0983: rewriteBody(first);
0984: int nforms = formStack.size() - first;
0985: if (nforms == 0)
0986: return QuoteExp.voidExp;
0987: else if (nforms == 1) {
0988: return (Expression) formStack.pop();
0989: } else {
0990: Expression[] exps = new Expression[nforms];
0991: for (int i = 0; i < nforms; i++)
0992: exps[i] = (Expression) formStack.elementAt(first + i);
0993: formStack.setSize(first);
0994: if (scope instanceof ModuleExp)
0995: return new ApplyExp(
0996: gnu.kawa.functions.AppendValues.appendValues,
0997: exps);
0998: else
0999: return ((LispLanguage) getLanguage()).makeBody(exps);
1000: }
1001: }
1002:
1003: /** Storage used by noteAccess and processAccesses. */
1004: Vector notedAccess;
1005:
1006: /** Note that we reference name in a given scope.
1007: * This may be called when defining a macro, at scan-time,
1008: * and the name may be bound to a declaration we haven't seen yet. */
1009: public void noteAccess(Object name, ScopeExp scope) {
1010: if (notedAccess == null)
1011: notedAccess = new Vector();
1012: notedAccess.addElement(name);
1013: notedAccess.addElement(scope);
1014: }
1015:
1016: /** Check references recorded by noteAccess.
1017: * Resolve now to a Declaration, and note the access.
1018: * This is needed in case an exported macro references a private Declaration.
1019: */
1020: public void processAccesses() {
1021: if (notedAccess == null)
1022: return;
1023: int sz = notedAccess.size();
1024: ScopeExp saveScope = current_scope;
1025: for (int i = 0; i < sz; i += 2) {
1026: Object name = notedAccess.elementAt(i);
1027: ScopeExp scope = (ScopeExp) notedAccess.elementAt(i + 1);
1028: if (current_scope != scope)
1029: setCurrentScope(scope);
1030: Declaration decl = (Declaration) lexical.lookup(name, -1);
1031: if (decl != null && !decl.getFlag(Declaration.IS_UNKNOWN)) {
1032: decl.getContext().currentLambda().capture(decl);
1033: decl.setCanRead(true);
1034: decl.setSimple(false);
1035: decl.setFlag(Declaration.EXTERNAL_ACCESS);
1036: }
1037: }
1038: if (current_scope != saveScope)
1039: setCurrentScope(saveScope);
1040: }
1041:
1042: public void finishModule(ModuleExp mexp) {
1043: boolean moduleStatic = mexp.isStatic();
1044: for (Declaration decl = mexp.firstDecl(); decl != null; decl = decl
1045: .nextDecl()) {
1046: if (decl.getFlag(Declaration.NOT_DEFINING)) {
1047: String msg1 = "'";
1048: String msg2 = (decl
1049: .getFlag(Declaration.EXPORT_SPECIFIED) ? "' exported but never defined"
1050: : decl.getFlag(Declaration.STATIC_SPECIFIED) ? "' declared static but never defined"
1051: : "' declared but never defined");
1052: error('e', decl, msg1, msg2);
1053: }
1054: if (mexp.getFlag(ModuleExp.EXPORT_SPECIFIED)) {
1055: if (decl.getFlag(Declaration.EXPORT_SPECIFIED)) {
1056: if (decl.isPrivate()) {
1057: if (decl.getFlag(Declaration.PRIVATE_SPECIFIED))
1058: error('e', decl, "'",
1059: "' is declared both private and exported");
1060: decl.setPrivate(false);
1061: }
1062: } else
1063: decl.setPrivate(true);
1064: }
1065: if (moduleStatic)
1066: decl.setFlag(Declaration.STATIC_SPECIFIED);
1067: else if ((mexp.getFlag(ModuleExp.NONSTATIC_SPECIFIED) && !decl
1068: .getFlag(Declaration.STATIC_SPECIFIED))
1069: || gnu.expr.Compilation.moduleStatic < 0
1070: || mexp.getFlag(ModuleExp.SUPERTYPE_SPECIFIED))
1071: decl.setFlag(Declaration.NONSTATIC_SPECIFIED);
1072: }
1073: if (!moduleStatic)
1074: mexp.declareThis(null);
1075: }
1076:
1077: public void resolveModule(ModuleExp mexp) {
1078: int numPending = pendingImports == null ? 0 : pendingImports
1079: .size();
1080: for (int i = 0; i < numPending;) {
1081: ModuleInfo info = (ModuleInfo) pendingImports
1082: .elementAt(i++);
1083: ScopeExp defs = (ScopeExp) pendingImports.elementAt(i++);
1084: Expression posExp = (Expression) pendingImports
1085: .elementAt(i++);
1086: if (mexp == defs) {
1087: // process(BODY_PARSED);
1088: Expression savePos = new ReferenceExp((Object) null);
1089: savePos.setLine(this );
1090: setLine(posExp);
1091: kawa.standard.require.importDefinitions(null, info,
1092: null, formStack, defs, this );
1093: setLine(savePos);
1094: pendingImports.setElementAt(null, i - 3);
1095: pendingImports.setElementAt(null, i - 2);
1096: pendingImports.setElementAt(null, i - 1);
1097: }
1098: }
1099:
1100: processAccesses();
1101:
1102: setModule(mexp);
1103: Compilation save_comp = Compilation.getCurrent();
1104: try {
1105: Compilation.setCurrent(this );
1106: mexp.body = makeBody(firstForm, mexp);
1107: lexical.pop(mexp);
1108: } finally {
1109: Compilation.setCurrent(save_comp);
1110: }
1111:
1112: /* DEBUGGING:
1113: OutPort err = OutPort.errDefault ();
1114: err.print ("[Re-written expression for load/compile: ");
1115: mexp.print (err);
1116: //err.print ("\nbefore load<"+mod.getClass().getName()+">");
1117: err.println();
1118: err.flush();
1119: */
1120: }
1121:
1122: public Declaration makeRenamedAlias(Declaration decl,
1123: ScopeExp templateScope) {
1124: if (templateScope == null)
1125: return decl; // ???
1126: return makeRenamedAlias(decl.getSymbol(), decl, templateScope);
1127: }
1128:
1129: public Declaration makeRenamedAlias(Object name, Declaration decl,
1130: ScopeExp templateScope) {
1131: Declaration alias = new Declaration(name);
1132: alias.setAlias(true);
1133: alias.setPrivate(true);
1134: alias.context = templateScope;
1135: ReferenceExp ref = new ReferenceExp(decl);
1136: ref.setDontDereference(true);
1137: alias.noteValue(ref);
1138: return alias;
1139: }
1140:
1141: /** Push an alias for a declaration in a scope.
1142: * If the name of <code>decl</code> came from a syntax template
1143: * whose immediate scope is <code>templateScope</code>,
1144: * then the same syntax template may contain local variable references
1145: * that are also in the same <code>templateScope</code>.
1146: * Such variable references will <em>not</em> look in the current
1147: * "physical" scope, where we just created <code>decl</code>, but
1148: * will instead search the "lexical" <code>templateScope</scope>.
1149: * So that such references can resolve to <code>decl</code>, we
1150: * create an alias in <code>templateScope</code> that points
1151: * to <code>decl</code>. We record that we did this in the
1152: * <code> renamedLiasStack</code>, so we can remove the alias later.
1153: */
1154: public void pushRenamedAlias(Declaration alias) {
1155: Declaration decl = getOriginalRef(alias).getBinding();
1156: ScopeExp templateScope = alias.context;
1157: decl.setSymbol(null);
1158: Declaration old = templateScope.lookup(decl.getSymbol());
1159: if (old != null)
1160: templateScope.remove(old);
1161: templateScope.addDeclaration(alias);
1162: if (renamedAliasStack == null)
1163: renamedAliasStack = new Stack();
1164: renamedAliasStack.push(old);
1165: renamedAliasStack.push(alias);
1166: renamedAliasStack.push(templateScope);
1167: }
1168:
1169: /** Remove one or more aliases created by <code>pushRenamedAlias</code>. */
1170: public void popRenamedAlias(int count) {
1171: while (--count >= 0) {
1172: ScopeExp templateScope = (ScopeExp) renamedAliasStack.pop();
1173: Declaration alias = (Declaration) renamedAliasStack.pop();
1174: Declaration decl = getOriginalRef(alias).getBinding();
1175: decl.setSymbol(alias.getSymbol());
1176: templateScope.remove(alias);
1177: Object old = renamedAliasStack.pop();
1178: if (old != null)
1179: templateScope.addDeclaration((Declaration) old);
1180: }
1181: }
1182:
1183: public Declaration define(Object name, SyntaxForm nameSyntax,
1184: ScopeExp defs) {
1185: boolean aliasNeeded = nameSyntax != null
1186: && nameSyntax.scope != currentScope();
1187: Object declName = aliasNeeded ? new String(name.toString())
1188: : name;
1189: Declaration decl = defs.getDefine(declName, 'w', this );
1190: if (aliasNeeded) {
1191: Declaration alias = makeRenamedAlias(name, decl,
1192: nameSyntax.scope);
1193: nameSyntax.scope.addDeclaration(alias);
1194: }
1195: push(decl);
1196: return decl;
1197: }
1198: }
|