1 package kawa.lang; 2 import gnu.mapping.*; 3 import gnu.expr.*; 4 import gnu.kawa.reflect.*; 5 import gnu.bytecode.ArrayClassLoader; 6 import gnu.bytecode.ClassType; 7 import gnu.bytecode.Field; 8 import gnu.bytecode.Member; 9 import gnu.bytecode.Type; 10 import gnu.bytecode.ZipLoader; 11 import gnu.text.SourceMessages; 12 import gnu.lists.*; 13 import gnu.kawa.lispexpr.*; 14 import java.util.*; 15 import gnu.kawa.functions.GetNamedPart; 16 import gnu.kawa.functions.CompileNamedPart; 17 import gnu.kawa.functions.MakeSplice; 18 import gnu.kawa.functions.MultiplyOp; 19 import gnu.kawa.functions.Expt; 20 import gnu.kawa.xml.XmlNamespace; 21 import gnu.math.DFloNum; 22 import gnu.math.IntNum; 23 import gnu.math.Unit; 24 import gnu.text.Char; 25 import gnu.text.SourceLocator; 26 import gnu.text.StandardNamedChars; 27 /* #ifdef enable:XML */ 28 import gnu.xml.NamespaceBinding; 29 /* #endif */ 30 import kawa.standard.Scheme; 31 import kawa.standard.require.DeclSetMapper; 32 33 /** Used to translate from source to Expression. 34 * The result has macros expanded, lexical names bound, etc, and is 35 * ready for code generation. 36 * This is sometimes called a "compilation environment", 37 * but we modify it as we go along - there is a single Translator for 38 * each top-level form. 39 */ 40 41 public class Translator extends Compilation 42 { 43 // Global environment used to look for syntax/macros. 44 private Environment env; 45 46 /** Set if we're processing (as opposed to expanding) 47 * a <code>define-syntax</code> or <code>defmacro</code>. */ 48 public Macro currentMacroDefinition; 49 50 /** Innermost current scope of pattern variable, 51 * from a <code>syntax-case</code>. */ 52 public PatternScope patternScope; 53 54 public Declaration templateScopeDecl; 55 56 /** A "mark" created for the current macro application. 57 * This is (more-or-less) the mark specified by the syntax-case 58 * specification (in r6rs-lib), applied to the output of a transformer. 59 * However, instead of "applying" a mark to the transformer output, 60 * we remember in the TemplateScope an object unique to the application. 61 */ 62 Object currentMacroMark = null; 63 64 /** A variable to hold the matched values for syntax-case 65 * pattern variables. */ 66 public Declaration matchArray; 67 68 /** A stack of aliases pushed by <code>pushRenamedAlias</code>. */ 69 private Stack<Declaration> renamedAliasStack; 70 71 public Object pendingForm; 72 73 public LambdaExp curMethodLambda; 74 75 /* #ifdef enable:XML */ 76 public NamespaceBinding xmlElementNamespaces = NamespaceBinding.predefinedXML; 77 /* #endif */ 78 79 public static final Declaration getNamedPartDecl; 80 static { 81 // Declare the special symbol $lookup$ (from the reader) 82 // and bind it to getNamedPartDecl. 83 String cname = "gnu.kawa.functions.GetNamedPart"; 84 String fname = "getNamedPart"; 85 getNamedPartDecl = Declaration.getDeclarationFromStatic(cname, fname); 86 LispLanguage.getNamedPartLocation.setDeclaration(getNamedPartDecl); 87 } 88 89 private static Expression errorExp = new ErrorExp ("unknown syntax error"); 90 Translator(Language language, SourceMessages messages, NameLookup lexical, Environment env)91 public Translator(Language language, SourceMessages messages, 92 NameLookup lexical, Environment env) { 93 super(language, messages, lexical); 94 this.env = env; 95 } 96 Translator(Language language, SourceMessages messages, NameLookup lexical)97 public Translator(Language language, SourceMessages messages, 98 NameLookup lexical) { 99 super(language, messages, lexical); 100 this.env = Environment.getCurrent(); 101 } 102 103 @Override getGlobalEnvironment()104 public final Environment getGlobalEnvironment() { return env; } 105 parse(Object input)106 public Expression parse (Object input) 107 { 108 return rewrite(input); 109 } 110 rewrite_car(Pair pair, SyntaxForm syntax)111 public final Expression rewrite_car (Pair pair, SyntaxForm syntax) 112 { 113 return rewrite_car(pair, syntax == null ? current_scope : syntax.getScope()); 114 } 115 rewrite_car(Pair pair, ScopeExp templateScope)116 public final Expression rewrite_car (Pair pair, ScopeExp templateScope) 117 { 118 if (templateScope == current_scope 119 || pair.getCar() instanceof SyntaxForm) 120 return rewrite_car(pair, false); 121 ScopeExp save_scope = setPushCurrentScope(templateScope); 122 try 123 { 124 return rewrite_car(pair, false); 125 } 126 finally 127 { 128 setPopCurrentScope(save_scope); 129 } 130 } 131 rewrite_car(Pair pair, boolean function)132 public final Expression rewrite_car (Pair pair, boolean function) 133 { 134 Object car = pair.getCar(); 135 if (pair instanceof PairWithPosition) 136 return rewrite_with_position (car, function, (PairWithPosition) pair); 137 else 138 return rewrite (car, function); 139 } 140 141 /** Similar to rewrite_car. 142 * However, we check for (quasiquote exp) specially, and handle that 143 * directly. This is in case quasiquote isn't in scope. 144 */ rewrite_car_for_lookup(Pair pair)145 public final Expression rewrite_car_for_lookup(Pair pair) { 146 Object car = pair.getCar(); 147 if (car instanceof Pair) { 148 Pair pcar = (Pair) car; 149 if (pcar.getCar() == LispLanguage.quasiquote_sym) { 150 Object pos = pushPositionOf(pair); 151 Expression ret = Quote.quasiQuote.rewrite(pcar.getCdr(), this); 152 popPositionOf(pos); 153 return ret; 154 } 155 } 156 return rewrite_car(pair, false); 157 } 158 159 Syntax currentSyntax; getCurrentSyntax()160 public Syntax getCurrentSyntax() { return currentSyntax; } 161 162 /** The module instance containing the current macro. 163 * This is only used temporarily, set when resolving a Declaration 164 * bound to a macro, and used to set the macroContext field of the 165 * TemplateScope created when expanding the macro's template(s). */ 166 Declaration macroContext; 167 168 /** 169 * Apply a Syntax object. 170 * @param syntax the Syntax object whose rewrite method we call 171 * @param form the syntax form (including the macro name) 172 * @return the re-written form as an Expression object 173 */ apply_rewrite(Syntax syntax, Pair form)174 Expression apply_rewrite (Syntax syntax, Pair form) 175 { 176 Expression exp = errorExp; 177 Syntax saveSyntax = currentSyntax; 178 currentSyntax = syntax; 179 try 180 { 181 exp = syntax.rewriteForm(form, this); 182 } 183 finally 184 { 185 currentSyntax = saveSyntax; 186 } 187 return exp; 188 } 189 190 /** Check if declaraton is an alias for some other name. 191 * This is needed to chase identifiers renamed for hygienic macro 192 * expansion - see SyntaxRules.expand. */ getOriginalRef(Declaration decl)193 static ReferenceExp getOriginalRef(Declaration decl) 194 { 195 if (decl != null && decl.isAlias() && ! decl.isIndirectBinding()) 196 { 197 Expression value = decl.getValue(); 198 if (value instanceof ReferenceExp) 199 return (ReferenceExp) value; 200 } 201 return null; 202 } 203 keywordsAreSelfEvaluating()204 public final boolean keywordsAreSelfEvaluating() { 205 return ((LispLanguage) getLanguage()).keywordsAreSelfEvaluating(); 206 } 207 selfEvaluatingSymbol(Object obj)208 public final boolean selfEvaluatingSymbol (Object obj) 209 { 210 return ((LispLanguage) getLanguage()).selfEvaluatingSymbol(obj); 211 } 212 213 /** True iff a form matches a literal symbol. */ matches(Object form, String literal)214 public final boolean matches(Object form, String literal) 215 { 216 return matches(form, null, literal); 217 } 218 matches(Object form, SyntaxForm syntax, String literal)219 public boolean matches(Object form, SyntaxForm syntax, String literal) 220 { 221 if (syntax != null) 222 { 223 // FIXME 224 } 225 if (form instanceof SyntaxForm) 226 { 227 // FIXME 228 form = ((SyntaxForm) form).getDatum(); 229 } 230 if (form instanceof SimpleSymbol && ! selfEvaluatingSymbol(form)) 231 { 232 ReferenceExp rexp = getOriginalRef(lexical.lookup(form, -1)); 233 if (rexp != null) 234 form = rexp.getSymbol(); 235 } 236 return form instanceof SimpleSymbol 237 && ((Symbol) form).getLocalPart() == literal; 238 } 239 matches(Object form, SyntaxForm syntax, Symbol literal)240 public boolean matches(Object form, SyntaxForm syntax, Symbol literal) 241 { 242 if (syntax != null) 243 { 244 // FIXME 245 } 246 if (form instanceof SyntaxForm) 247 { 248 // FIXME 249 form = ((SyntaxForm) form).getDatum(); 250 } 251 if (form instanceof SimpleSymbol && ! selfEvaluatingSymbol(form)) 252 { 253 ReferenceExp rexp = getOriginalRef(lexical.lookup(form, -1)); 254 if (rexp != null) 255 form = rexp.getSymbol(); 256 } 257 return form == literal; 258 } 259 matchQuoted(Pair pair)260 public Object matchQuoted (Pair pair) 261 { 262 if (matches(pair.getCar(), LispLanguage.quote_str) 263 && pair.getCdr() instanceof Pair 264 && (pair = (Pair) pair.getCdr()).getCdr() == LList.Empty) 265 return pair.getCar(); 266 return null; 267 } 268 lookup(Object name, int namespace)269 public Declaration lookup(Object name, int namespace) 270 { 271 Declaration decl = lexical.lookup(name, namespace); 272 if (decl != null && getLanguage().hasNamespace(decl, namespace)) 273 return decl; 274 return currentModule().lookup(name, getLanguage(), namespace); 275 } 276 277 /** Find global Declaration, creating one if not found. */ lookupGlobal(Object name)278 public Declaration lookupGlobal(Object name) 279 { 280 return lookupGlobal(name, -1); 281 } 282 283 /** Find global Declaration, creating one if not found. */ lookupGlobal(Object name, int namespace)284 public Declaration lookupGlobal(Object name, int namespace) 285 { 286 ModuleExp module = currentModule(); 287 Declaration decl = module.lookup(name, getLanguage(), namespace); 288 if (decl == null) 289 { 290 decl = module.getNoDefine(name); 291 decl.setIndirectBinding(true); 292 } 293 return decl; 294 } 295 296 /** Check if a Declaration is bound to a Syntax. 297 * @param decl the Declaration to check 298 * @return the Syntax bound to decl, or null. 299 * In the former case, macroContext may be set as a side effect. 300 */ check_if_Syntax(Declaration decl)301 Syntax check_if_Syntax (Declaration decl) 302 { 303 Declaration d = Declaration.followAliases(decl); 304 Object obj = null; 305 Expression dval = d.getValue(); 306 if (dval != null && d.getFlag(Declaration.IS_SYNTAX)) 307 { 308 try 309 { 310 if (decl.getValue() instanceof ReferenceExp) 311 { 312 Declaration context 313 = ((ReferenceExp) decl.getValue()).contextDecl(); 314 if (context != null) 315 macroContext = context; 316 else if (current_scope instanceof TemplateScope) 317 macroContext = ((TemplateScope) current_scope).macroContext; 318 } 319 else if (current_scope instanceof TemplateScope) 320 macroContext = ((TemplateScope) current_scope).macroContext; 321 obj = dval.eval(env); 322 } 323 catch (Error ex) 324 { 325 ex.printStackTrace(); 326 throw ex; 327 } 328 catch (Throwable ex) 329 { 330 ex.printStackTrace(); 331 error('e', "unable to evaluate macro for "+decl.getSymbol()); 332 } 333 } 334 else if (decl.getFlag(Declaration.IS_SYNTAX) && ! decl.needsContext()) 335 { 336 StaticFieldLocation loc = StaticFieldLocation.make(decl); 337 obj = loc.get(null); 338 } 339 340 return obj instanceof Syntax ? (Syntax) obj : null; 341 } 342 rewrite_pair(Pair p, boolean function)343 public Expression rewrite_pair (Pair p, boolean function) 344 { 345 Object p_car = p.getCar(); 346 Expression func; 347 boolean useHelper = true; 348 if (p_car instanceof Pair 349 && ((Pair) p_car).getCar() == LispLanguage.splice_sym) { 350 func = gnu.kawa.reflect.MakeAnnotation.makeAnnotationMaker 351 (rewrite_car((Pair) ((Pair) p_car).getCdr(), false)); 352 useHelper = false; 353 } 354 else 355 func = rewrite_car (p, true); 356 Object proc = null; 357 if (func instanceof QuoteExp) 358 { 359 proc = func.valueIfConstant(); 360 if (proc instanceof Syntax) 361 return apply_rewrite((Syntax) proc, p); 362 } 363 ReferenceExp ref = null; 364 if (func instanceof ReferenceExp) 365 { 366 ref = (ReferenceExp) func; 367 Declaration decl = ref.getBinding(); 368 if (decl == null) 369 { 370 Object sym = ref.getSymbol(); 371 Symbol symbol; 372 String name; 373 if (sym instanceof Symbol && ! selfEvaluatingSymbol(sym)) 374 { 375 symbol = (Symbol) sym; 376 name = symbol.getName(); 377 } 378 else 379 { 380 name = sym.toString(); 381 symbol = env.getSymbol(name); 382 } 383 proc = env.get(symbol, 384 getLanguage().hasSeparateFunctionNamespace() 385 ? EnvironmentKey.FUNCTION 386 : null, 387 null); 388 if (proc instanceof Syntax) 389 return apply_rewrite ((Syntax) proc, p); 390 if (proc instanceof AutoloadProcedure) 391 { 392 try 393 { 394 proc = ((AutoloadProcedure) proc).getLoaded(); 395 } 396 catch (RuntimeException ex) 397 { 398 proc = null; 399 } 400 } 401 } 402 else 403 { 404 Declaration saveContext = macroContext; 405 Syntax syntax = check_if_Syntax (decl); 406 if (syntax != null) 407 { 408 Expression e = apply_rewrite (syntax, p); 409 macroContext = saveContext; 410 return e; 411 } 412 } 413 414 ref.setProcedureName(true); 415 if (getLanguage().hasSeparateFunctionNamespace()) 416 func.setFlag(ReferenceExp.PREFER_BINDING2); 417 } 418 419 boolean isNamedPartDecl = func instanceof ReferenceExp 420 && (((ReferenceExp) func).getBinding()==getNamedPartDecl); 421 if (isNamedPartDecl) 422 useHelper = false; 423 424 Object cdr = p.getCdr(); 425 int cdr_length = listLength(cdr); 426 427 if (cdr_length < 0) 428 return syntaxError 429 ("improper list (circular or dotted) is not allowed here"); 430 Expression applyFunction = useHelper ? applyFunction(func) : null; 431 432 Stack vec = new Stack(); 433 if (applyFunction != null) { 434 vec.add(func); 435 func = applyFunction; 436 } 437 438 ScopeExp save_scope = current_scope; 439 int first_keyword = -1; 440 int last_keyword = -1; 441 boolean bad_keyword_reported = false; 442 int firstSpliceArg = -1; 443 int i = 0; 444 while (cdr != LList.Empty) 445 { 446 if (cdr instanceof SyntaxForm) 447 { 448 SyntaxForm sf = (SyntaxForm) cdr; 449 cdr = sf.getDatum(); 450 // I.e. first time do equivalent of setPushCurrentScope 451 if (current_scope == save_scope) 452 lexical.pushSaveTopLevelRedefs(); 453 setCurrentScope(sf.getScope()); 454 } 455 Object save_pos = pushPositionOf(cdr); 456 Pair cdr_pair = (Pair) cdr; 457 Object cdr_car = cdr_pair.getCar(); 458 Object cdr_cdr = cdr_pair.getCdr(); 459 Expression arg; 460 if (cdr_car instanceof Keyword) { 461 if (first_keyword < 0) { 462 first_keyword = i; 463 last_keyword = i - 2; // To suppress incorrect warnings 464 } 465 if (bad_keyword_reported) 466 ; 467 else if (keywordsAreSelfEvaluating()) 468 last_keyword = i; 469 else if (i == last_keyword + 1 || i + 1 == cdr_length) { 470 bad_keyword_reported = true; 471 error('w', "missing value after unquoted keyword"); 472 } else if (i != last_keyword + 2) { 473 bad_keyword_reported = true; 474 error('w', "keyword separated from other keyword arguments"); 475 } else 476 last_keyword = i; 477 arg = QuoteExp.getInstance(cdr_car, this); 478 arg.setFlag(QuoteExp.IS_KEYWORD); 479 } else if (cdr_cdr instanceof Pair 480 // FIXME should check binding for ... is builtin ... 481 && ((Pair) cdr_cdr).getCar() == LispLanguage.dots3_sym) { 482 LambdaExp dotsLambda = new LambdaExp(); 483 pushScanContext(dotsLambda); 484 dotsLambda.body = rewrite_car(cdr_pair, false); 485 ScanContext scanContext = getScanContext(); 486 LinkedHashMap<Declaration,Declaration> sdecls 487 = scanContext.decls; 488 int nseqs = sdecls.size(); 489 ArrayList<Expression> scanExps = scanContext.scanExpressions; 490 int nexps = scanExps == null ? 0 : scanExps.size(); 491 Expression[] subargs = new Expression[nseqs + nexps + 1]; 492 subargs[0] = dotsLambda; 493 popScanContext(); 494 Iterator<Declaration> sit = sdecls.keySet().iterator(); 495 int j = 1; 496 while (sit.hasNext()) { 497 Declaration sdecl = sit.next(); 498 if (curScanNesting() > 0) { 499 sdecl = getScanContext().addSeqDecl(sdecl); 500 } 501 ReferenceExp rexp = new ReferenceExp(sdecl); 502 subargs[j++] = rexp; 503 } 504 for (int k = 0; k < nexps; k++) { 505 subargs[j++] = scanExps.get(k); 506 } 507 arg = new ApplyExp(Scheme.map, subargs); 508 arg = new ApplyExp(MakeSplice.quoteInstance, arg); 509 cdr_cdr = ((Pair) cdr_cdr).getCdr(); 510 if (firstSpliceArg < 0) 511 firstSpliceArg = i + (applyFunction != null ? 1 : 0); 512 } else { 513 Object cdr_car_car; 514 if (cdr_car instanceof Pair 515 && ((cdr_car_car = ((Pair) cdr_car).getCar()) == LispLanguage.splice_sym 516 || cdr_car_car == LispLanguage.splice_colon_sym)) { 517 arg = rewrite_car((Pair) ((Pair) cdr_car).getCdr(), false); 518 QuoteExp splicer = cdr_car_car == LispLanguage.splice_sym 519 ? MakeSplice.quoteInstance 520 : MakeSplice.quoteKeywordsAllowedInstance; 521 arg = new ApplyExp(splicer, arg); 522 if (firstSpliceArg < 0) 523 firstSpliceArg = i + (applyFunction != null ? 1 : 0); 524 } 525 else 526 arg = rewrite_car (cdr_pair, false); 527 } 528 i++; 529 530 vec.addElement(arg); 531 cdr = cdr_cdr; 532 popPositionOf(save_pos); 533 } 534 535 536 Expression[] args = new Expression[vec.size()]; 537 vec.copyInto(args); 538 539 if (save_scope != current_scope) 540 setPopCurrentScope(save_scope); 541 542 if (isNamedPartDecl) 543 return rewrite_lookup(args[0], args[1], function); 544 545 ApplyExp app = new ApplyExp(func, args); 546 app.firstSpliceArg = firstSpliceArg; 547 if (first_keyword >= 0) 548 { 549 app.numKeywordArgs = (last_keyword - first_keyword) / 2 + 1; 550 app.firstKeywordArgIndex = first_keyword + (applyFunction != null ? 2 : 1); 551 } 552 return app; 553 } 554 rewrite_lookup(Expression part1, Expression part2, boolean function)555 public Expression rewrite_lookup(Expression part1, Expression part2, boolean function) { 556 Symbol sym = namespaceResolve(part1, part2); 557 if (sym != null) 558 return rewrite(sym, function); 559 // FIXME don't copy the args array in makeExp ... 560 return CompileNamedPart.makeExp(part1, part2); 561 } 562 namespaceResolvePrefix(Expression context)563 public Namespace namespaceResolvePrefix (Expression context) 564 { 565 if (context instanceof ReferenceExp) 566 { 567 ReferenceExp rexp = (ReferenceExp) context; 568 Declaration decl = rexp.getBinding(); 569 Object val; 570 if (decl == null || decl.getFlag(Declaration.IS_UNKNOWN)) 571 { 572 Object rsym = rexp.getSymbol(); 573 Symbol sym = rsym instanceof Symbol ? (Symbol) rsym 574 : env.getSymbol(rsym.toString()); 575 val = env.get(sym, null); 576 } 577 else if (decl.isNamespaceDecl()) 578 { 579 val = decl.getConstantValue(); 580 } 581 else 582 val = null; 583 if (val instanceof Namespace) 584 { 585 Namespace ns = (Namespace) val; 586 String uri = ns.getName(); 587 if (uri != null && uri.startsWith("class:")) 588 return null; 589 return ns; 590 } 591 } 592 return null; 593 } 594 namespaceResolve(Namespace ns, Expression member)595 public Symbol namespaceResolve (Namespace ns, Expression member) 596 { 597 if (ns != null && member instanceof QuoteExp) 598 { 599 String mem = ((QuoteExp) member).getValue().toString().intern(); 600 return ns.getSymbol(mem); 601 } 602 return null; 603 } 604 namespaceResolve(Expression context, Expression member)605 public Symbol namespaceResolve (Expression context, Expression member) 606 { 607 return namespaceResolve(namespaceResolvePrefix(context), member); 608 } 609 stripSyntax(Object obj)610 public static Object stripSyntax (Object obj) 611 { 612 while (obj instanceof SyntaxForm) 613 obj = ((SyntaxForm) obj).getDatum(); 614 return obj; 615 } 616 safeCar(Object obj)617 public static Object safeCar (Object obj) 618 { 619 while (obj instanceof SyntaxForm) 620 obj = ((SyntaxForm) obj).getDatum(); 621 if (! (obj instanceof Pair)) 622 return null; 623 return stripSyntax(((Pair) obj).getCar()); 624 } 625 safeCdr(Object obj)626 public static Object safeCdr (Object obj) 627 { 628 while (obj instanceof SyntaxForm) 629 obj = ((SyntaxForm) obj).getDatum(); 630 if (! (obj instanceof Pair)) 631 return null; 632 return stripSyntax(((Pair) obj).getCdr()); 633 } 634 635 /** Returns the length of a syntax list. 636 * Returns Integer.MIN_VALUE for cyclic lists. 637 * For impure lists returns the negative of one more than 638 * the number of pairs before the "dot". 639 * Similar to LList.listLength, but handles SyntaxForm more efficiently. */ listLength(Object obj)640 public static int listLength(Object obj) 641 { 642 // Based on list-length implementation in 643 // Guy L Steele jr: "Common Lisp: The Language", 2nd edition, page 414 644 int n = 0; 645 Object slow = obj; 646 Object fast = obj; 647 for (;;) 648 { 649 // 'n' is number of previous Pairs before 'fast' cursor. 650 while (fast instanceof SyntaxForm) 651 fast = ((SyntaxForm) fast).getDatum(); 652 while (slow instanceof SyntaxForm) 653 slow = ((SyntaxForm) slow).getDatum(); 654 if (fast == LList.Empty) 655 return n; 656 if (! (fast instanceof Pair)) 657 return -1-n; 658 n++; 659 Object next = ((Pair) fast).getCdr(); 660 while (next instanceof SyntaxForm) 661 next = ((SyntaxForm) next).getDatum(); 662 if (next == LList.Empty) 663 return n; 664 if (! (next instanceof Pair)) 665 return -1-n; 666 slow = ((Pair)slow).getCdr(); 667 fast = ((Pair)next).getCdr(); 668 n++; 669 if (fast == slow) 670 return Integer.MIN_VALUE; 671 } 672 } 673 rewriteInBody(Object exp)674 public void rewriteInBody (Object exp) 675 { 676 if (exp instanceof SyntaxForm) 677 { 678 SyntaxForm sf = (SyntaxForm) exp; 679 ScopeExp save_scope = setPushCurrentScope(sf.getScope()); 680 try 681 { 682 rewriteInBody(sf.getDatum()); 683 } 684 finally 685 { 686 setPopCurrentScope(save_scope); 687 } 688 } 689 else if (exp instanceof ValuesFromLList) 690 { 691 // Optimization of following case. 692 // More importantly, we make use of the line number information. 693 for (Object vs = ((ValuesFromLList) exp).values; 694 vs != LList.Empty; ) 695 { 696 Pair p = (Pair) vs; 697 pushForm(rewrite_car(p, false)); 698 vs = p.getCdr(); 699 } 700 } 701 else if (exp instanceof Values) 702 { 703 Object[] vals = ((Values) exp).getValues(); 704 for (int i = 0; i < vals.length; i++) 705 rewriteInBody(vals[i]); 706 } 707 else { 708 Expression e = rewrite(exp, false); 709 setLineOf(e); 710 pushForm(e); 711 } 712 } 713 getCompletions(Environment env, String nameStart, Object property, String namespaceUri, List<? super String> matches)714 public int getCompletions(Environment env, 715 String nameStart, Object property, 716 String namespaceUri, 717 List<? super String> matches) { 718 LocationEnumeration e = env.enumerateAllLocations(); 719 int count = 0; 720 while (e.hasMoreElements()) { 721 Location loc = e.nextLocation(); 722 Symbol sym = loc.getKeySymbol(); 723 String local = sym == null ? null : sym.getLocalPart(); 724 if (local != null && local.startsWith(nameStart) 725 && property == loc.getKeyProperty() 726 && namespaceUri == sym.getNamespaceURI()) { 727 count++; 728 matches.add(local); 729 } 730 } 731 return count; 732 } 733 namespaceResolve(Object name)734 public Object namespaceResolve(Object name) { 735 Object prefix = null; 736 Expression part2 = null; 737 Pair p; 738 if (name instanceof Pair 739 && safeCar(p = (Pair) name) == LispLanguage.lookup_sym 740 && p.getCdr() instanceof Pair 741 && (p = (Pair) p.getCdr()).getCdr() instanceof Pair) { 742 prefix = namespaceResolve(p.getCar()); 743 if (! (stripSyntax(prefix) instanceof Symbol)) 744 return name; 745 part2 = rewrite_car_for_lookup((Pair) p.getCdr()); 746 } 747 else if (name instanceof Symbol) { 748 Symbol s = (Symbol) name; 749 if (s.hasUnknownNamespace()) { 750 String loc = s.getLocalPart(); 751 prefix = Symbol.valueOf(s.getPrefix()); 752 part2 = QuoteExp.getInstance(Symbol.valueOf(s.getLocalPart())); 753 } 754 } 755 if (part2 != null) { 756 Expression part1 = rewrite(prefix); 757 Symbol sym = namespaceResolve(part1, part2); 758 if (sym != null) 759 return sym; 760 String combinedName = CompileNamedPart.combineName(part1, part2); 761 if (combinedName != null) 762 return Namespace.EmptyNamespace.getSymbol(combinedName); 763 } 764 return name; 765 } 766 767 /** 768 * Re-write a Scheme expression in S-expression format into internal form. 769 */ rewrite(Object exp)770 public Expression rewrite(Object exp) { 771 return rewrite(exp, 'N'); 772 } 773 774 /** 775 * Re-write a Scheme expression in S-expression format into internal form. 776 */ rewrite(Object exp, boolean function)777 public Expression rewrite(Object exp, boolean function) { 778 return rewrite(exp, function ? 'F' : 'N'); 779 } 780 781 /** Re-write a Scheme expression in S-expression format into internal form. 782 * @param mode either 'N' (normal), 'F' (function application context), 783 * 'M' (macro-checking) or 'Q' (colon-form in quote). 784 */ rewrite(Object exp, char mode)785 public Expression rewrite(Object exp, char mode) { 786 if (exp instanceof SyntaxForm) { 787 SyntaxForm sf = (SyntaxForm) exp; 788 ScopeExp save_scope = setPushCurrentScope(sf.getScope()); 789 try { 790 Expression s = rewrite(sf.getDatum(), mode); 791 return s; 792 } finally { 793 setPopCurrentScope(save_scope); 794 } 795 } 796 boolean function = mode != 'N'; 797 if (exp instanceof Pair && mode != 'Q') { 798 Expression e = rewrite_pair((Pair) exp, function); 799 setLineOf(e); 800 return e; 801 } else if (exp instanceof Symbol && ! selfEvaluatingSymbol(exp)) { 802 Symbol s = (Symbol) exp; 803 804 // Check if we're handling a completion request. 805 int complete = s.getLocalName() 806 .indexOf(CommandCompleter.COMPLETE_REQUEST); 807 boolean separate = getLanguage().hasSeparateFunctionNamespace(); 808 if (complete >= 0) { 809 List<String> candidates = new ArrayList<String>(); 810 String prefix = s.toString().substring(0, complete); 811 Object property = function && separate ? EnvironmentKey.FUNCTION 812 : null; 813 int symspace = function ? Language.FUNCTION_NAMESPACE 814 : Language.VALUE_NAMESPACE; 815 getCompletions(env, prefix, property, s.getNamespaceURI(), 816 candidates); 817 lexical.getCompletingSymbols(prefix, symspace, 818 candidates); 819 throw new CommandCompleter(complete, candidates, 820 prefix, prefix.length(), this); 821 } 822 823 if (s.hasUnknownNamespace()) { 824 String loc = s.getLocalPart(); 825 return rewrite_lookup(rewrite(Symbol.valueOf(s.getPrefix()), false), 826 QuoteExp.getInstance(Symbol.valueOf(s.getLocalPart())), 827 function); 828 } 829 Declaration decl = lexical.lookup(exp, function); 830 Declaration cdecl = null; 831 832 // If we're nested inside a class (in a ClassExp) then the field 833 // and methods names of this class and super-classes/interfaces 834 // need to be searched. 835 ScopeExp scope = current_scope; 836 int decl_nesting = decl == null ? -1 : ScopeExp.nesting(decl.context); 837 String dname; 838 if (exp instanceof SimpleSymbol) 839 dname = exp.toString(); 840 else { 841 dname = null; 842 scope = null; 843 } 844 for (;scope != null; scope = scope.getOuter()) { 845 if (scope instanceof LambdaExp 846 && scope.getOuter() instanceof ClassExp // redundant? FIXME 847 && ((LambdaExp) scope).isClassMethod() 848 && mode != 'M') { 849 if (decl_nesting >= ScopeExp.nesting(scope.getOuter())) 850 break; 851 LambdaExp caller = (LambdaExp) scope; 852 ClassExp cexp = (ClassExp) scope.getOuter(); 853 ClassType ctype = (ClassType) cexp.getClassType(); 854 // If ctype is a class that hasn't been compiled yet (and 855 // ClassExp#declareParts hasn't been called yet) 856 // then we may may get a tentative Field created 857 // by ClassExp#createFields. 858 // BUG: This doesn't work for not-yet compiled methods. 859 Member part = SlotGet.lookupMember(ctype, dname, ctype); 860 boolean contextStatic 861 = (caller == cexp.clinitMethod 862 || (caller != cexp.initMethod 863 && caller.nameDecl.isStatic())); 864 if (part == null) { 865 PrimProcedure[] methods 866 = ClassMethods.getMethods(ctype, dname, 867 contextStatic ? 'S' : 'V', 868 ctype, language); 869 if (methods.length == 0) 870 continue; 871 } else { 872 gnu.expr.SourceName snameAnn = 873 part.getAnnotation(gnu.expr.SourceName.class); 874 String pname = snameAnn == null ? part.getName() 875 : snameAnn.name(); 876 if (! dname.equals(pname)) 877 continue; 878 } 879 Expression part1; 880 // FIXME We're throwing away 'part', which is wasteful. 881 if (contextStatic) 882 part1 = new ReferenceExp(((ClassExp) caller.getOuter()).nameDecl); 883 else 884 part1 = new ThisExp(caller.firstDecl()); 885 return CompileNamedPart.makeExp(part1, 886 QuoteExp.getInstance(dname)); 887 } 888 } 889 890 Object nameToLookup; 891 if (decl != null) { 892 nameToLookup = decl.getSymbol(); 893 exp = null; 894 ReferenceExp rexp = getOriginalRef(decl); 895 if (rexp != null) { 896 decl = rexp.getBinding(); 897 if (decl == null) { 898 exp = rexp.getSymbol(); 899 nameToLookup = exp; 900 } 901 } 902 } else { 903 nameToLookup = exp; 904 } 905 Symbol symbol = (Symbol) exp; 906 if (decl != null) { 907 if (current_scope instanceof TemplateScope && decl.needsContext()) 908 cdecl = ((TemplateScope) current_scope).macroContext; 909 else if (decl.getFlag(Declaration.FIELD_OR_METHOD) 910 && ! decl.isStatic()) { 911 scope = currentScope(); 912 for (;;) { 913 if (scope == null) 914 throw new Error("internal error: missing "+decl); 915 if (scope.getOuter() == decl.context) // I.e. same class. 916 break; 917 scope = scope.getOuter(); 918 } 919 cdecl = scope.firstDecl(); 920 } 921 } else { 922 Location loc 923 = env.lookup(symbol, 924 function && separate ? EnvironmentKey.FUNCTION 925 : null); 926 if (loc != null) 927 loc = loc.getBase(); 928 if (loc instanceof FieldLocation) { 929 FieldLocation floc = (FieldLocation) loc; 930 try { 931 decl = floc.getDeclaration(); 932 if (! inlineOk(null) 933 // A kludge - we get a bunch of testsuite failures 934 // if we don't inline $lookup$. FIXME. 935 && (decl != getNamedPartDecl 936 // Another kludge to support "object" as a 937 // type specifier. 938 && ! isObjectSyntax(floc.getDeclaringClass(), 939 floc.getMemberName()))) 940 decl = null; 941 else if (immediate) { 942 if (! decl.isStatic()) { 943 cdecl = new Declaration("(module-instance)"); 944 cdecl.setValue(new QuoteExp(floc.getInstance())); 945 } 946 } else if (decl.isStatic()) { 947 // If the class has been loaded through ZipLoader 948 // or ArrayClassLoader then it might not be visible 949 // if loaded through some other ClassLoader. 950 Class fclass = floc.getRClass(); 951 ClassLoader floader; 952 if (fclass == null 953 || ((floader = fclass.getClassLoader()) 954 instanceof ZipLoader) 955 || floader instanceof ArrayClassLoader) 956 decl = null; 957 } else 958 decl = null; 959 } catch (Exception ex) { 960 error('e', 961 "exception loading '" + exp 962 + "' - " + ex.getMessage()); 963 decl = null; 964 } 965 } 966 else if (mode != 'M' && (loc == null || ! loc.isBound())) 967 { 968 Expression e = checkDefaultBinding(symbol, this); 969 if (e != null) 970 return e; 971 } 972 /* 973 else if (Compilation.inlineOk && function) { 974 // Questionable. fail with new set_b implementation, 975 // which just call rewrite_car on the lhs, 976 // if we don't require function to be true. FIXME. 977 decl = Declaration.getDeclaration(proc); 978 } 979 */ 980 } 981 if (decl != null) { 982 // A special kludge to deal with the overloading between the 983 // object macro and object as being equivalent to java.lang.Object. 984 // A cleaner solution would be to use an identifier macro. 985 Field dfield = decl.getField(); 986 if (! function && dfield != null 987 && isObjectSyntax(dfield.getDeclaringClass(), 988 dfield.getName())) 989 return QuoteExp.getInstance(Object.class); 990 991 if (decl.getContext() instanceof PatternScope) 992 return syntaxError("reference to pattern variable "+decl.getName()+" outside syntax template"); 993 } 994 995 if (decl == null && function 996 && nameToLookup==LispLanguage.lookup_sym) { 997 decl = getNamedPartDecl; 998 } 999 int scanNesting = decl == null ? 0 1000 : Declaration.followAliases(decl).getScanNesting(); 1001 if (scanNesting > 0) { 1002 if (scanNesting > curScanNesting()) 1003 error('e', "using repeat variable '"+decl.getName()+"' while not in repeat context"); 1004 else { 1005 return new ReferenceExp 1006 (scanContextStack.get(scanNesting-1).addSeqDecl(decl)); 1007 } 1008 } 1009 ReferenceExp rexp = new ReferenceExp (nameToLookup, decl); 1010 rexp.setContextDecl(cdecl); 1011 rexp.setLine(this); 1012 if (function && separate) 1013 rexp.setFlag(ReferenceExp.PREFER_BINDING2); 1014 return rexp; 1015 } else if (exp instanceof LangExp) 1016 return rewrite(((LangExp) exp).getLangValue(), function); 1017 else if (exp instanceof Expression) 1018 return (Expression) exp; 1019 else if (exp == Special.abstractSpecial) 1020 return QuoteExp.abstractExp; 1021 else if (exp == Boolean.TRUE) 1022 return QuoteExp.trueExp; 1023 else if (exp == Boolean.FALSE) 1024 return QuoteExp.falseExp; 1025 else if (exp == Special.nativeSpecial) 1026 return QuoteExp.nativeExp; 1027 else { 1028 if (exp instanceof Keyword && ! keywordsAreSelfEvaluating()) 1029 error('w', "keyword should be quoted if not in argument position"); 1030 if (exp instanceof String) 1031 exp = new IString((String) exp); 1032 return QuoteExp.getInstance(Quote.quote(exp, this), this); 1033 } 1034 } 1035 1036 /** 1037 * If a symbol is lexically unbound, look for a default binding. 1038 * The default implementation does the following: 1039 * 1040 * If the symbol is the name of an existing Java class, return that class. 1041 * Handles both with and without (semi-deprecated) angle-brackets: 1042 * {@code <java.lang.Integer>} and {@code java.lang.Integer}. 1043 * Also handles arrays, such as {@code java.lang.String[]}. 1044 * 1045 * If the symbol starts with {@code '@'} parse as an annotation class. 1046 * 1047 * Recognizes quanties with units, such as {@code 2m} and {@code 3m/s^2}. 1048 * 1049 * Handles the xml and unit namespaces. 1050 * 1051 * @return null if no binding, otherwise an Expression. 1052 * 1053 * FIXME: This method should be refactored. The quantities parsing should 1054 * be moved to its own method at least. 1055 */ checkDefaultBinding(Symbol symbol, Translator tr)1056 public Expression checkDefaultBinding(Symbol symbol, Translator tr) { 1057 Namespace namespace = symbol.getNamespace(); 1058 String local = symbol.getLocalPart(); 1059 String name = symbol.toString(); 1060 int len = name.length(); 1061 1062 if (namespace instanceof XmlNamespace) 1063 return makeQuoteExp(((XmlNamespace) namespace).get(local)); 1064 String namespaceName = namespace.getName(); 1065 if (namespaceName == LispLanguage.unitNamespace.getName()) { 1066 Object val = Unit.lookup(local); 1067 if (val != null) 1068 return makeQuoteExp(val); 1069 } 1070 if (namespaceName == LispLanguage.entityNamespace.getName()) { 1071 Object val = lookupStandardEntity(local); 1072 if (val == null) { 1073 tr.error('e', "unknown entity name "+local); 1074 val = "{"+namespace.getPrefix()+":"+local+"}"; 1075 } 1076 return makeQuoteExp(val); 1077 } 1078 1079 char ch0 = name.charAt(0); 1080 1081 if (ch0 == '@') { // Deprecated - reader now returns ($splice$ ATYPE). 1082 String rest = name.substring(1); 1083 Expression classRef = tr.rewrite(Symbol.valueOf(rest)); 1084 return MakeAnnotation.makeAnnotationMaker(classRef); 1085 } 1086 1087 // Look for quantities. 1088 if (ch0 == '-' || ch0 == '+' || Character.digit(ch0, 10) >= 0) { 1089 // 1: initial + or -1 seen. 1090 // 2: digits seen 1091 // 3: '.' seen 1092 // 4: fraction seen 1093 // 5: [eE][=+]?[0-9]+ seen 1094 int state = 0; 1095 int i = 0; 1096 1097 for (; i < len; i++) { 1098 char ch = name.charAt(i); 1099 if (Character.digit(ch, 10) >= 0) 1100 state = state < 3 ? 2 : state < 5 ? 4 : 5; 1101 else if ((ch == '+' || ch == '-') && state == 0) 1102 state = 1; 1103 else if (ch == '.' && state < 3) 1104 state = 3; 1105 else if ((ch == 'e' || ch == 'E') && (state == 2 || state == 4) 1106 && i + 1 < len) { 1107 int j = i + 1; 1108 char next = name.charAt(j); 1109 if ((next == '-' || next == '+') && ++j < len) 1110 next = name.charAt(j); 1111 if (Character.digit(next, 10) < 0) 1112 break; 1113 state = 5; 1114 i = j + 1; 1115 } 1116 else 1117 break; 1118 } 1119 tryQuantity: 1120 if (i < len && state > 1) { 1121 DFloNum num = new DFloNum(name.substring(0, i)); 1122 boolean div = false; 1123 ArrayList vec = new ArrayList(); 1124 for (; i < len;) { 1125 char ch = name.charAt(i++); 1126 if (ch == '*') { 1127 if (i == len) 1128 break tryQuantity; 1129 ch = name.charAt(i++); 1130 } else if (ch == '/') { 1131 if (i == len || div) 1132 break tryQuantity; 1133 div = true; 1134 ch = name.charAt(i++); 1135 } 1136 int unitStart = i - 1; 1137 int unitEnd; 1138 for (;;) { 1139 if (!Character.isLetter(ch)) { 1140 unitEnd = i - 1; 1141 if (unitEnd == unitStart) 1142 break tryQuantity; 1143 break; 1144 } 1145 if (i == len) { 1146 unitEnd = i; 1147 ch = '1'; 1148 break; 1149 } 1150 ch = name.charAt(i++); 1151 } 1152 vec.add(name.substring(unitStart, unitEnd)); 1153 boolean expRequired = false; 1154 if (ch == '^') { 1155 expRequired = true; 1156 if (i == len) 1157 break tryQuantity; 1158 ch = name.charAt(i++); 1159 } 1160 boolean neg = div; 1161 if (ch == '+') { 1162 expRequired = true; 1163 if (i == len) 1164 break tryQuantity; 1165 ch = name.charAt(i++); 1166 } else if (ch == '-') { 1167 expRequired = true; 1168 if (i == len) 1169 break tryQuantity; 1170 ch = name.charAt(i++); 1171 neg = !neg; 1172 } 1173 int nexp = 0; 1174 int exp = 0; 1175 for (;;) { 1176 int dig = Character.digit(ch, 10); 1177 if (dig <= 0) { 1178 i--; 1179 break; 1180 } 1181 exp = 10 * exp + dig; 1182 nexp++; 1183 if (i == len) 1184 break; 1185 ch = name.charAt(i++); 1186 } 1187 if (nexp == 0) { 1188 exp = 1; 1189 if (expRequired) 1190 break tryQuantity; 1191 } 1192 if (neg) 1193 exp = -exp; 1194 vec.add(IntNum.make(exp)); 1195 } 1196 if (i == len) { 1197 int nunits = vec.size() >> 1; 1198 Expression[] units = new Expression[nunits]; 1199 for (i = 0; i < nunits; i++) { 1200 String uname = (String) vec.get(2 * i); 1201 Symbol usym = LispLanguage.unitNamespace.getSymbol(uname.intern()); 1202 Expression uref = tr.rewrite(usym); 1203 IntNum uexp = (IntNum) vec.get(2 * i + 1); 1204 if (uexp.longValue() != 1) 1205 uref = new ApplyExp(Expt.expt, 1206 new Expression[] { 1207 uref, makeQuoteExp(uexp) 1208 }); 1209 units[i] = uref; 1210 } 1211 Expression unit; 1212 if (nunits == 1) 1213 unit = units[0]; 1214 else 1215 unit = new ApplyExp(MultiplyOp.TIMES, units); 1216 return new ApplyExp(MultiplyOp.TIMES, 1217 new Expression[] { 1218 makeQuoteExp(num), 1219 unit 1220 }); 1221 } 1222 } 1223 } 1224 1225 boolean sawAngle; 1226 if (len > 2 && ch0 == '<' && name.charAt(len - 1) == '>') { 1227 name = name.substring(1, len - 1); 1228 len -= 2; 1229 sawAngle = true; 1230 } else 1231 sawAngle = false; 1232 int rank = 0; 1233 while (len > 2 && name.charAt(len - 2) == '[' 1234 && name.charAt(len - 1) == ']') { 1235 len -= 2; 1236 rank++; 1237 } 1238 //(future) String cname = (namespace == LispPackage.ClassNamespace) ? local : name; 1239 String cname = name; 1240 if (rank != 0) 1241 cname = name.substring(0, len); 1242 try { 1243 Type type = getLanguage().getNamedType(cname); 1244 if (rank > 0 && (!sawAngle || type == null)) { 1245 Symbol tsymbol = namespace.getSymbol(cname.intern()); 1246 Expression texp = tr.rewrite(tsymbol, false); 1247 texp = InlineCalls.inlineCalls(texp, tr); 1248 if (!(texp instanceof ErrorExp)) 1249 type = tr.getLanguage().getTypeFor(texp); 1250 } 1251 if (type != null) { 1252 // Somewhat inconsistent: Types named by getNamedType are Type, 1253 // while standard type/classes are Class. FIXME. 1254 while (--rank >= 0) { 1255 type = gnu.bytecode.ArrayType.make(type); 1256 } 1257 return makeQuoteExp(type); 1258 } 1259 Class clas; 1260 type = Type.lookupType(cname); 1261 if (type instanceof gnu.bytecode.PrimType) 1262 clas = type.getReflectClass(); 1263 else { 1264 if (cname.indexOf('.') < 0) 1265 cname = (tr.classPrefix 1266 + Mangling.mangleNameIfNeeded(cname)); 1267 if (rank == 0) { 1268 ModuleManager mmanager = ModuleManager.getInstance(); 1269 ModuleInfo typeInfo = mmanager.searchWithClassName(cname); 1270 if (typeInfo != null) { 1271 Compilation tcomp = typeInfo.getCompilation(); 1272 if (tcomp != null && tcomp.mainClass != null) { 1273 QuoteExp qexp = new QuoteExp(tcomp.mainClass, 1274 Type.javalangClassType); 1275 qexp.setLocation(this); 1276 return qexp; 1277 } 1278 } 1279 } 1280 1281 clas = ClassType.getContextClass(cname); 1282 } 1283 if (clas != null) { 1284 if (rank > 0) { 1285 type = Type.make(clas); 1286 while (--rank >= 0) { 1287 type = gnu.bytecode.ArrayType.make(type); 1288 } 1289 clas = type.getReflectClass(); 1290 } 1291 return makeQuoteExp(clas); 1292 } 1293 } catch (ClassNotFoundException ex) { 1294 Package pack = gnu.bytecode.ArrayClassLoader.getContextPackage(name); 1295 if (pack != null) 1296 return makeQuoteExp(pack); 1297 } catch (NoClassDefFoundError ex) { 1298 tr.error('w', "error loading class " + cname + " - " + ex.getMessage() + " not found"); 1299 } catch (Exception ex) { 1300 } 1301 if (name.startsWith("array")) { 1302 Type atype = LispLanguage.decodeArrayType(name); 1303 if (atype != null) 1304 return makeQuoteExp(atype); 1305 } 1306 1307 return null; 1308 } 1309 1310 static Map<String,String> standardEntities; 1311 public static synchronized String lookupStandardEntity(String key) { 1312 if (standardEntities == null) { 1313 standardEntities = new HashMap<String,String>(); 1314 Char.addNamedChars(standardEntities); 1315 } 1316 String val = standardEntities.get(key); 1317 if (val != null) 1318 return val; 1319 return val = StandardNamedChars.instance.get(key); 1320 } 1321 1322 public static void setLine(Expression exp, Object location) 1323 { 1324 if (location instanceof SourceLocator) 1325 exp.setLocation((SourceLocator) location); 1326 } 1327 1328 public static void setLine(Declaration decl, Object location) 1329 { 1330 if (location instanceof SourceLocator) 1331 decl.setLocation((SourceLocator) location); 1332 } 1333 1334 PairWithPosition positionPair; 1335 1336 /* 1337 public Object pushPositionOfCar(Object pair) 1338 { 1339 if (pair instanceof Pair) 1340 { 1341 Object car = ((Pair) pair).getCar(); 1342 if (car instanceof PairWithPosition) 1343 pair = car; 1344 } 1345 return pushPositionOf(pair); 1346 }*/ 1347 1348 /** Note current line number position from a PairWithPosition. 1349 * Return an object to pass to popPositionOf. 1350 */ 1351 public Object pushPositionOf(Object pos) 1352 { 1353 if (pos instanceof SyntaxForm) 1354 pos = ((SyntaxForm) pos).getDatum(); 1355 PairWithPosition pair; 1356 if (pos instanceof PairWithPosition) 1357 pair = (PairWithPosition) pos; 1358 else if (pos instanceof SourceLocator) 1359 pair = new PairWithPosition((SourceLocator) pos, null, null); 1360 else 1361 return null; 1362 Object saved; 1363 if (positionPair == null 1364 || positionPair.getFileName() != getFileName() 1365 || positionPair.getLineNumber() != getLineNumber() 1366 || positionPair.getColumnNumber() != getColumnNumber()) 1367 { 1368 saved = new PairWithPosition(this, this, positionPair); 1369 } 1370 else 1371 saved = positionPair; 1372 setLine(pos); 1373 positionPair = pair; 1374 return saved; 1375 } 1376 1377 /** Restore line number position from a previous pushPositionOf. 1378 * @param saved value returned by matching pushPositionOf. 1379 */ 1380 public void popPositionOf(Object saved) 1381 { 1382 if (saved == null) 1383 return; 1384 setLine(saved); 1385 positionPair = (PairWithPosition) saved; 1386 if (positionPair.getCar() == this) 1387 positionPair = (PairWithPosition) positionPair.getCdr(); 1388 } 1389 1390 public void errorWithPosition(String message, Object form) { 1391 Object save = pushPositionOf(form); 1392 error('e', message); 1393 popPositionOf(save); 1394 } 1395 1396 public void errorIfNonEmpty(Object form) { 1397 if (form != LList.Empty) 1398 error('e', "invalid improper (dotted) list"); 1399 } 1400 1401 /** Set the line position of the argument to the current position. */ 1402 1403 public void setLineOf (Expression exp) 1404 { 1405 // "Special" QuoteExps may be shared, but the position gets set (in the 1406 // call to QuoteExp.getInstance at end of re-write) for normal ones. 1407 if (exp instanceof QuoteExp) 1408 return; 1409 if (exp.getLineNumber() <= 0) 1410 exp.setLocation(this); 1411 } 1412 1413 /** Extract a type from the car of a pair. */ 1414 public Type exp2Type(Pair typeSpecPair) 1415 { 1416 return exp2Type(typeSpecPair, null, null); 1417 } 1418 1419 public Type exp2Type(Pair typeSpecPair, Declaration decl, SyntaxForm syntax) 1420 { 1421 Object saved = pushPositionOf(typeSpecPair); 1422 try 1423 { 1424 Expression texp = rewrite_car(typeSpecPair, syntax); 1425 if (texp instanceof ErrorExp) 1426 return null; 1427 Type type = getLanguage().getTypeFor(texp); 1428 if (type == null) 1429 { 1430 try 1431 { 1432 Object t = texp.eval(env); 1433 if (t instanceof Class) 1434 type = Type.make((Class) t); 1435 else if (t instanceof Type) 1436 type = (Type) t; 1437 } 1438 catch (Error ex) 1439 { 1440 throw ex; 1441 } 1442 catch (Throwable ex) 1443 { 1444 } 1445 } 1446 if (type == null) 1447 { 1448 if (texp instanceof ReferenceExp) 1449 error('e', "unknown type name '" 1450 + ((ReferenceExp) texp).getName() + '\''); 1451 else 1452 error('e', "invalid type spec"); 1453 type = Type.errorType; 1454 } 1455 if (decl != null) 1456 decl.setType(texp, type); 1457 return type; 1458 } 1459 finally 1460 { 1461 popPositionOf(saved); 1462 } 1463 } 1464 1465 public Expression rewrite_with_position (Object exp, boolean function, 1466 PairWithPosition pair) 1467 { 1468 Object saved = pushPositionOf(pair); 1469 Expression result; 1470 try 1471 { 1472 if (exp == pair) 1473 result = rewrite_pair(pair, function); // To avoid a cycle 1474 else 1475 result = rewrite (exp, function); 1476 setLineOf(result); 1477 } 1478 finally 1479 { 1480 popPositionOf(saved); 1481 } 1482 return result; 1483 } 1484 1485 public static Object wrapSyntax (Object form, SyntaxForm syntax) 1486 { 1487 if (syntax == null || form instanceof Expression) 1488 return form; 1489 else 1490 return SyntaxForms.fromDatumIfNeeded(form, syntax); 1491 } 1492 1493 /** Pop from formStack all forms that come after beforeFirst. 1494 */ 1495 public Values popForms(Pair beforeFirst) 1496 { 1497 Object tail = formStack.popTail(beforeFirst); 1498 if (tail == LList.Empty) 1499 return Values.empty; 1500 return new ValuesFromLList((LList) tail); 1501 } 1502 1503 public void scanForm (Object st, ScopeExp defs) 1504 { 1505 if (st instanceof SyntaxForm) 1506 { 1507 SyntaxForm sf = (SyntaxForm) st; 1508 ScopeExp save_scope = setPushCurrentScope(sf.getScope()); 1509 try 1510 { 1511 Pair beforeFirst = formStack.last; 1512 scanForm(sf.getDatum(), defs); 1513 pushForm(wrapSyntax(popForms(beforeFirst), sf)); 1514 return; 1515 } 1516 finally 1517 { 1518 setPopCurrentScope(save_scope); 1519 } 1520 } 1521 if (st instanceof Values) 1522 { 1523 if (st == Values.empty) 1524 st = QuoteExp.voidExp; // From #!void 1525 else if (st instanceof ValuesFromLList) 1526 { 1527 for (Object vs = ((ValuesFromLList) st).values; 1528 vs != LList.Empty; ) 1529 { 1530 Pair p = (Pair) vs; 1531 Object save = pushPositionOf(p); 1532 scanForm(p.getCar(), defs); 1533 popPositionOf(save); 1534 vs = p.getCdr(); 1535 } 1536 } 1537 else 1538 { 1539 Object[] vals = ((Values) st).getValues(); 1540 for (int i = 0; i < vals.length; i++) 1541 scanForm(vals[i], defs); 1542 return; 1543 } 1544 } 1545 if (st instanceof Pair) 1546 { 1547 Pair st_pair = (Pair) st; 1548 Declaration saveContext = macroContext; 1549 Syntax syntax = null; 1550 ScopeExp savedScope = current_scope; 1551 Object savedPosition = pushPositionOf(st); 1552 if (st instanceof SourceLocator && defs.getLineNumber() < 0) 1553 defs.setLocation((SourceLocator) st); 1554 try 1555 { 1556 Object obj = st_pair.getCar(); 1557 if (obj instanceof SyntaxForm) 1558 { 1559 SyntaxForm sf = (SyntaxForm) st_pair.getCar(); 1560 savedScope = setPushCurrentScope(sf.getScope()); 1561 obj = sf.getDatum(); 1562 } 1563 Pair p; 1564 if (obj instanceof Pair 1565 && (p = (Pair) obj).getCar() == LispLanguage.lookup_sym 1566 && p.getCdr() instanceof Pair 1567 && (p = (Pair) p.getCdr()).getCdr() instanceof Pair) 1568 { 1569 Expression part1 = rewrite(p.getCar()); 1570 Expression part2 = rewrite_car_for_lookup((Pair) p.getCdr()); 1571 Object value1 = part1.valueIfConstant(); 1572 Object value2 = part2.valueIfConstant(); 1573 if (value1 instanceof Class && value2 instanceof Symbol) 1574 { 1575 try 1576 { 1577 obj = GetNamedPart.getNamedPart(value1, (Symbol)value2); 1578 if (obj instanceof Syntax) 1579 syntax = (Syntax) obj; 1580 } 1581 catch (Exception ex) 1582 { 1583 obj = null; 1584 } 1585 } 1586 else 1587 obj = namespaceResolve(part1, part2); 1588 } 1589 if (obj instanceof Symbol && ! selfEvaluatingSymbol(obj)) 1590 { 1591 Expression func = rewrite(obj, 'M'); 1592 if (func instanceof ReferenceExp) 1593 { 1594 Declaration decl = ((ReferenceExp) func).getBinding(); 1595 if (decl != null) 1596 syntax = check_if_Syntax(decl); 1597 else 1598 { 1599 obj = resolve(obj, true); 1600 if (obj instanceof Syntax) 1601 syntax = (Syntax) obj; 1602 } 1603 } 1604 } 1605 // Recognize deferred begin created in scanBody for pendingForms. 1606 // A seemingly-cleaner (obj instanceof Syntax) causes problems 1607 // with some Syntax forms, such as define. 1608 else if (obj == kawa.standard.begin.begin 1609 || obj == kawa.standard.define_library.define_library_scan) 1610 syntax = (Syntax) obj; 1611 } 1612 finally 1613 { 1614 if (savedScope != current_scope) 1615 setPopCurrentScope(savedScope); 1616 popPositionOf(savedPosition); 1617 } 1618 if (syntax != null) 1619 { 1620 String save_filename = getFileName(); 1621 try 1622 { 1623 syntax.scanForm(st_pair, defs, this); 1624 return; 1625 } 1626 finally 1627 { 1628 macroContext = saveContext; 1629 } 1630 } 1631 } 1632 pushForm(st); 1633 } 1634 1635 /** Recursive helper method for rewrite_body. 1636 * Scan body for definitions, adding partially macro-expanded 1637 * expressions into the <code>formStack</code>. 1638 * @param makeList if true, return a list representation of the scanned 1639 * forms (not including declarations); else forms are push on formStack 1640 * @return a list of forms if <code>makeList</code> (possibly wrapped 1641 * in a <code>SyntaxForm</code>); otherwise <code>null</code>. 1642 */ 1643 1644 public LList scanBody (Object body, ScopeExp defs, boolean makeList) 1645 { 1646 LList list = makeList ? LList.Empty : null; 1647 Pair lastPair = null; 1648 while (body != LList.Empty) 1649 { 1650 if (body instanceof SyntaxForm) 1651 { 1652 SyntaxForm sf = (SyntaxForm) body; 1653 ScopeExp save_scope = setPushCurrentScope(sf.getScope()); 1654 try 1655 { 1656 Pair first = formStack.last; 1657 1658 LList f = scanBody(sf.getDatum(), defs, makeList); 1659 if (makeList) 1660 { 1661 f = (LList) SyntaxForms.fromDatumIfNeeded(f, sf); 1662 if (lastPair == null) 1663 return f; 1664 lastPair.setCdrBackdoor(f); 1665 return list; 1666 } 1667 pushForm(wrapSyntax(popForms(first), sf)); 1668 return null; 1669 } 1670 finally 1671 { 1672 setPopCurrentScope(save_scope); 1673 } 1674 } 1675 else if (body instanceof Pair) 1676 { 1677 Pair pair = (Pair) body; 1678 Pair first = formStack.last; 1679 Object savePos = pushPositionOf(pair); 1680 scanForm(pair.getCar(), defs); 1681 popPositionOf(savePos); 1682 if (getState() == Compilation.PROLOG_PARSED && pendingForm != null) 1683 { 1684 // We've seen a require form during the initial pass when 1685 // we're looking module names. Defer the require and any 1686 // following forms in this body. 1687 if (pair.getCar() != pendingForm) 1688 pair = makePair(pair, pendingForm, pair.getCdr()); 1689 pendingForm = new Pair(kawa.standard.begin.begin, pair); 1690 if (makeList) 1691 formStack.pushAll(list); 1692 return LList.Empty; 1693 } 1694 if (makeList) 1695 { 1696 Pair last = formStack.lastPair(); 1697 LList nlist = (LList) formStack.popTail(first); 1698 if (lastPair == null) 1699 list = nlist; 1700 else 1701 lastPair.setCdrBackdoor(nlist); 1702 if (last != first) 1703 lastPair = last; 1704 } 1705 body = pair.getCdr(); 1706 } 1707 else 1708 { 1709 pushForm(syntaxError("body is not a proper list")); 1710 break; 1711 } 1712 } 1713 return list; 1714 } 1715 1716 public static Pair makePair(Pair pair, Object car, Object cdr) 1717 { 1718 if (pair instanceof PairWithPosition) 1719 return new PairWithPosition((PairWithPosition) pair, car, cdr); 1720 return new Pair(car, cdr); 1721 } 1722 1723 /** 1724 * Re-write a Scheme 'body' in S-expression format into internal form. 1725 */ 1726 1727 public Expression rewrite_body (Object exp) 1728 { 1729 // NOTE we have both a rewrite_body and a rewriteBody. 1730 // This is confusing, at the least. FIXME. 1731 Object saved = pushPositionOf(exp); 1732 LetExp defs = new LetExp(); 1733 defs.setFlag(LetExp.IS_BODY_SCOPE); 1734 int renamedAliasOldSize = renamedAliasCount(); 1735 Pair first = formStack.last; 1736 defs.setOuter(current_scope); 1737 current_scope = defs; 1738 try 1739 { 1740 LList list = scanBody(exp, defs, true); 1741 if (list.isEmpty()) 1742 pushForm(syntaxError("body with no expressions")); 1743 int ndecls = 0; 1744 for (Declaration decl = defs.firstDecl(); decl != null; decl = decl.nextDecl()) 1745 { 1746 if (! decl.getFlag(Declaration.IS_DYNAMIC)) 1747 { 1748 ndecls++; 1749 decl.setInitValue(QuoteExp.undefined_exp); 1750 } 1751 } 1752 rewriteBody(list); 1753 int renamedAliasNewSize = renamedAliasCount(); 1754 popRenamedAlias(renamedAliasNewSize - renamedAliasOldSize); 1755 Expression body = makeBody(first, null); 1756 setLineOf(body); 1757 if (ndecls == 0) 1758 return body; 1759 defs.setBody(body); 1760 setLineOf(defs); 1761 return defs; 1762 } 1763 finally 1764 { 1765 pop(defs); 1766 popPositionOf(saved); 1767 } 1768 } 1769 1770 protected void rewriteBody (LList forms) 1771 { 1772 while (forms != LList.Empty) 1773 { 1774 Pair pair = (Pair) forms; 1775 Object saved = pushPositionOf(pair); 1776 try 1777 { 1778 rewriteInBody(pair.getCar()); 1779 } 1780 finally 1781 { 1782 popPositionOf(saved); 1783 } 1784 forms = (LList) pair.getCdr(); 1785 } 1786 } 1787 1788 /** Combine a list of zero or more expression forms into a "body". */ 1789 protected Expression makeBody(Pair head, ScopeExp scope) 1790 { 1791 Object tail = formStack.popTail(head); 1792 int nforms = LList.length(tail); 1793 if (nforms == 0) 1794 return QuoteExp.voidExp; 1795 Pair first = (Pair) tail; 1796 if (nforms == 1) 1797 { 1798 return (Expression) first.getCar(); 1799 } 1800 else 1801 { 1802 Expression[] exps = new Expression[nforms]; 1803 first.toArray(exps); 1804 if (scope instanceof ModuleExp) 1805 return new ApplyExp(gnu.kawa.functions.AppendValues.appendValues, 1806 exps); 1807 else 1808 return makeBody(exps); 1809 } 1810 } 1811 1812 public boolean appendBodyValues () { return false; } 1813 1814 /** Combine a 'body' consisting of a list of expression. */ 1815 public Expression makeBody(Expression[] exps) 1816 { 1817 if (appendBodyValues()) 1818 return new ApplyExp(gnu.kawa.functions.AppendValues.appendValues, exps); 1819 else 1820 return new BeginExp (exps); 1821 } 1822 1823 /** Storage used by noteAccess and processAccesses. */ 1824 ArrayList notedAccess; 1825 1826 /** Note that we reference name in a given scope. 1827 * This may be called when defining a macro, at scan-time, 1828 * and the name may be bound to a declaration we haven't seen yet. */ 1829 public void noteAccess (Object name, ScopeExp scope) 1830 { 1831 if (notedAccess == null) 1832 notedAccess = new ArrayList(); 1833 notedAccess.add(name); 1834 notedAccess.add(scope); 1835 } 1836 1837 /** Check references recorded by noteAccess. 1838 * Resolve now to a Declaration, and note the access. 1839 * This is needed in case an exported macro references a private Declaration. 1840 */ 1841 public void processAccesses () 1842 { 1843 if (notedAccess == null) 1844 return; 1845 int sz = notedAccess.size(); 1846 ScopeExp saveScope = current_scope; 1847 for (int i = 0; i < sz; i += 2) 1848 { 1849 Object name = notedAccess.get(i); 1850 ScopeExp scope = (ScopeExp) notedAccess.get(i+1); 1851 if (current_scope != scope) 1852 { 1853 // I.e. first time do equivalent of setPushCurrentScope 1854 if (current_scope == saveScope) 1855 lexical.pushSaveTopLevelRedefs(); 1856 setCurrentScope(scope); 1857 } 1858 Declaration decl = (Declaration) lexical.lookup(name, -1); 1859 if (decl != null && ! decl.getFlag(Declaration.IS_UNKNOWN)) 1860 { 1861 decl.getContext().currentLambda().capture(decl); 1862 decl.setCanRead(true); 1863 decl.setSimple(false); 1864 decl.setFlag(Declaration.EXTERNAL_ACCESS); 1865 } 1866 } 1867 if (current_scope != saveScope) 1868 setPopCurrentScope(saveScope); 1869 } 1870 1871 public void finishModule(ModuleExp mexp) 1872 { 1873 boolean moduleStatic = mexp.isStatic(); 1874 for (Declaration decl = mexp.firstDecl(); 1875 decl != null; decl = decl.nextDecl()) 1876 { 1877 if (decl.getFlag(Declaration.NOT_DEFINING)) 1878 { 1879 String msg1 = "'"; 1880 String msg2 1881 = (decl.getFlag(Declaration.EXPORT_SPECIFIED) 1882 ? "' exported but never defined" 1883 : decl.getFlag(Declaration.STATIC_SPECIFIED) 1884 ? "' declared static but never defined" 1885 : "' declared but never defined"); 1886 error('e', decl, msg1, msg2); 1887 } 1888 if (mexp.getFlag(ModuleExp.EXPORT_SPECIFIED) 1889 || (generateMainMethod() && ! immediate)) 1890 { 1891 if (decl.getFlag(Declaration.EXPORT_SPECIFIED)) 1892 { 1893 if (decl.isPrivate()) 1894 { 1895 if (decl.getFlag(Declaration.PRIVATE_SPECIFIED)) 1896 error('e', decl, 1897 "'", "' is declared both private and exported"); 1898 decl.setPrivate(false); 1899 } 1900 } 1901 else if (! kawa.standard.IfFeature.isProvide(decl)) 1902 decl.setPrivate(true); 1903 } 1904 if (moduleStatic) 1905 decl.setFlag(Declaration.STATIC_SPECIFIED); 1906 else if ((mexp.getFlag(ModuleExp.NONSTATIC_SPECIFIED) 1907 && ! decl.getFlag(Declaration.STATIC_SPECIFIED)) 1908 || gnu.expr.Compilation.moduleStatic < 0 1909 || mexp.getFlag(ModuleExp.SUPERTYPE_SPECIFIED)) 1910 decl.setFlag(Declaration.NONSTATIC_SPECIFIED); 1911 } 1912 if (mexp.getFlag(ModuleExp.SUPERTYPE_SPECIFIED)) 1913 mexp.setFlag(false, ModuleExp.USE_DEFINED_CLASS); 1914 } 1915 1916 public void resolveModule(ModuleExp mexp) 1917 { 1918 Expression savePos = new ReferenceExp((Object) null); 1919 int numPending = pendingImports == null ? 0 : pendingImports.size(); 1920 for (int i = 0; i < numPending; ) 1921 { 1922 ModuleInfo info = (ModuleInfo) pendingImports.elementAt(i++); 1923 ScopeExp defs = (ScopeExp) pendingImports.elementAt(i++); 1924 Expression posExp = (Expression) pendingImports.elementAt(i++); 1925 Pair beforeGoal = (Pair) pendingImports.elementAt(i++); 1926 DeclSetMapper mapper = (DeclSetMapper) pendingImports.elementAt(i++); 1927 if (mexp == defs) 1928 { 1929 // process(BODY_PARSED); 1930 savePos.setLine(this); 1931 setLine(posExp); 1932 Pair beforeImports = formStack.last; 1933 kawa.standard.require.importDefinitions(null, info, mapper, 1934 formStack, defs, this); 1935 if (beforeGoal != beforeImports 1936 && beforeImports != formStack.last) 1937 { 1938 // Move forms derived from the import forwards in the list, 1939 // just following beforeGoal. 1940 Object firstGoal = beforeGoal.getCdr(); 1941 Object firstImports = beforeImports.getCdr(); 1942 beforeGoal.setCdrBackdoor(firstImports); 1943 formStack.last.setCdrBackdoor(firstGoal); 1944 beforeImports.setCdrBackdoor(LList.Empty); 1945 formStack.last = beforeImports; 1946 } 1947 setLine(savePos); 1948 } 1949 } 1950 pendingImports = null; 1951 setModule(mexp); 1952 1953 savePos.setLine(this); 1954 setLine(null, -1, -1); 1955 Compilation save_comp = Compilation.setSaveCurrent(this); 1956 try 1957 { 1958 Pair firstForm = formStack.getHead(); 1959 rewriteBody((LList) formStack.popTail(firstForm)); 1960 mexp.body = makeBody(firstForm, mexp); 1961 1962 processAccesses(); 1963 1964 // In immediate mode need to preserve Declaration for current "session". 1965 if (! immediate) 1966 lexical.pop(mexp); 1967 1968 // Patch up renamed exports - see export. 1969 for (Declaration decl = mexp.firstDecl(); decl != null; 1970 decl = decl.nextDecl()) { 1971 if (decl.getSymbol() == null 1972 && decl.getFlag(Declaration.EXPORT_SPECIFIED)) { 1973 decl.patchSymbolFromSet(); 1974 } 1975 } 1976 } 1977 finally 1978 { 1979 Compilation.restoreCurrent(save_comp); 1980 setLine(savePos); 1981 } 1982 1983 /* DEBUGGING: 1984 OutPort err = OutPort.errDefault (); 1985 err.print ("[Re-written expression for load/compile: "); 1986 mexp.print (err); 1987 //err.print ("\nbefore load<"+mod.getClass().getName()+">"); 1988 err.println(); 1989 err.flush(); 1990 */ 1991 } 1992 1993 public Declaration makeRenamedAlias (Declaration decl, 1994 ScopeExp templateScope) 1995 { 1996 if (templateScope == null) 1997 return decl; // ??? 1998 return makeRenamedAlias(decl.getSymbol(), decl, templateScope); 1999 } 2000 2001 public Declaration makeRenamedAlias (Object name, 2002 Declaration decl, 2003 ScopeExp templateScope) 2004 { 2005 Declaration alias = new Declaration(name); 2006 alias.setAlias(true); 2007 alias.setPrivate(true); 2008 alias.context = templateScope; 2009 ReferenceExp ref = new ReferenceExp(decl); 2010 ref.setDontDereference(true); 2011 alias.noteValue(ref); 2012 return alias; 2013 } 2014 2015 /** Push an alias for a declaration in a scope. 2016 * If the name of {@code decl} came from a syntax template 2017 * whose immediate scope is {@code templateScope}, 2018 * then the same syntax template may contain local variable references 2019 * that are also in the same {@code templateScope}. 2020 * Such variable references will <em>not</em> look in the current 2021 * "physical" scope, where we just created {@code decl}, but 2022 * will instead search the "lexical" {@code templateScope}. 2023 * So that such references can resolve to {@code decl}, we 2024 * create an alias in {@code templateScope} that points 2025 * to {@code decl}. We record that we did this in the 2026 * {@code renamedAliasStack}, so we can remove the alias later. 2027 */ 2028 public void pushRenamedAlias (Declaration alias) 2029 { 2030 Declaration decl = getOriginalRef(alias).getBinding(); 2031 ScopeExp templateScope = alias.context; 2032 decl.setSymbol(null); 2033 Declaration old = templateScope.lookup(alias.getSymbol()); 2034 if (old != null) 2035 templateScope.remove(old); 2036 templateScope.addDeclaration(alias); 2037 if (renamedAliasStack == null) 2038 renamedAliasStack = new Stack<Declaration>(); 2039 renamedAliasStack.push(old); 2040 renamedAliasStack.push(alias); 2041 } 2042 2043 public int renamedAliasCount() { 2044 return renamedAliasStack == null ? 0 : renamedAliasStack.size() >> 1; 2045 } 2046 2047 /** Remove one or more aliases created by <code>pushRenamedAlias</code>. */ 2048 public void popRenamedAlias (int count) 2049 { 2050 while (--count >= 0) 2051 { 2052 Declaration alias = (Declaration) renamedAliasStack.pop(); 2053 ScopeExp templateScope = alias.getContext(); 2054 Declaration decl = getOriginalRef(alias).getBinding(); 2055 decl.setSymbol(alias.getSymbol()); 2056 templateScope.remove(alias); 2057 Declaration old = renamedAliasStack.pop(); 2058 if (old != null) 2059 templateScope.addDeclaration(old); 2060 } 2061 } 2062 2063 public Declaration define(Object name, ScopeExp defs) { 2064 return define(name, (TemplateScope) null, defs); 2065 } 2066 2067 public Declaration define(Object name, SyntaxForm nameSyntax, 2068 ScopeExp defs) { 2069 return define(name, nameSyntax == null ? null : nameSyntax.getScope(), 2070 defs); 2071 } 2072 2073 public Declaration define(Object name, TemplateScope templateScope, 2074 ScopeExp defs) { 2075 ScopeExp scope = templateScope != null ? templateScope 2076 : currentScope(); 2077 boolean aliasNeeded = scope != defs; 2078 Object declName = aliasNeeded 2079 ? Symbol.makeUninterned(name.toString()) 2080 : name; 2081 Declaration decl = defs.getDefine(declName, this); 2082 if (aliasNeeded) { 2083 Declaration alias = makeRenamedAlias(name, decl, scope); 2084 if (defs instanceof LetExp) 2085 pushRenamedAlias(alias); 2086 else 2087 scope.addDeclaration(alias); 2088 } 2089 push(decl); 2090 return decl; 2091 } 2092 2093 static boolean isObjectSyntax (ClassType declaringClass, String fieldName) 2094 { 2095 return "objectSyntax".equals(fieldName) 2096 && "kawa.standard.object".equals(declaringClass.getName()); 2097 } 2098 2099 public FormStack formStack = new FormStack(this); 2100 public void pushForm(Object value) { formStack.push(value); } 2101 2102 /** A list of "forms" to be further processed. 2103 * It is implemented as an LList so we can save position information. 2104 */ 2105 public static class FormStack extends Pair { 2106 private Pair last = this; 2107 SourceLocator sloc; 2108 2109 public FormStack(SourceLocator sloc) { 2110 this.sloc = sloc; 2111 this.cdr = LList.Empty; 2112 } 2113 2114 /** Return the "head" of the list. 2115 * The cdr of the head is the first element. 2116 */ 2117 public Pair getHead() { return this; } 2118 public Object getFirst() { return cdr; } 2119 /** The Pair whose car is the last form in the list. 2120 * If the list is empty, this returns the list head. 2121 */ 2122 @Override 2123 public Pair lastPair() { return last; } 2124 2125 /* DEBUGGING: 2126 public void dump() { 2127 int i=0; 2128 System.err.println("formStack len:"+LList.length(getFirst())); 2129 for(Object x = getFirst(); x instanceof Pair; i++) { 2130 Pair p = (Pair) x; 2131 //if (! (p.getCar() instanceof SetExp)) 2132 System.err.println("- #"+i+": "+p.getCar()); 2133 x = p.getCdr(); 2134 } 2135 } 2136 */ 2137 2138 public Object popTail(Pair oldTail) { 2139 Object r = oldTail.getCdr(); 2140 oldTail.setCdrBackdoor(LList.Empty); 2141 last = oldTail; 2142 return r; 2143 } 2144 2145 public void push(Object value) { 2146 PairWithPosition pair = new PairWithPosition(sloc, value, LList.Empty); 2147 last.setCdrBackdoor(pair); 2148 last = pair; 2149 } 2150 2151 public void pushAll(LList values) { 2152 if (values == LList.Empty) 2153 return; 2154 last.setCdrBackdoor(values); 2155 last = ((Pair) values).lastPair(); 2156 } 2157 2158 public void pushAll(LList values, Pair valuesLast) { 2159 if (values == LList.Empty) 2160 return; 2161 last.setCdrBackdoor(values); 2162 last = valuesLast; 2163 } 2164 2165 public void pushAfter(Object value, Pair position) { 2166 Pair pair = new PairWithPosition(sloc, value, position.getCdr()); 2167 position.setCdrBackdoor(pair); 2168 if (last == position) 2169 last = pair; 2170 } 2171 } 2172 2173 /** An implementationof Values using a linked list. 2174 */ 2175 public static class ValuesFromLList extends Values.FromList<Object> { 2176 public LList values; 2177 2178 public ValuesFromLList(LList values) { 2179 super(values); 2180 this.values = values; 2181 } 2182 } 2183 2184 Stack<ScanContext> scanContextStack = new Stack<ScanContext>(); 2185 2186 public ScanContext getScanContext() { return scanContextStack.peek(); } 2187 public int curScanNesting() { return scanContextStack.size(); } 2188 public Stack<ScanContext> getScanContextStack() { return scanContextStack; } 2189 2190 public void pushScanContext (LambdaExp lambda) { 2191 ScanContext newContext = new ScanContext(); 2192 newContext.lambda = lambda; 2193 scanContextStack.push(newContext); 2194 } 2195 public void popScanContext() { 2196 scanContextStack.pop(); 2197 } 2198 public static class ScanContext { 2199 LinkedHashMap<Declaration,Declaration> decls 2200 = new LinkedHashMap<Declaration,Declaration>(); 2201 ArrayList<Expression> scanExpressions = null; 2202 LambdaExp lambda; 2203 2204 public LambdaExp getLambda() { return lambda; } 2205 2206 public Declaration addSeqDecl(Declaration scanVar) { 2207 Declaration param = decls.get(scanVar); 2208 if (param == null) { 2209 param = lambda.addParameter(null); 2210 decls.put(scanVar, param); 2211 } 2212 return param; 2213 } 2214 public void addSeqExpression(Expression scanExp) { 2215 if (scanExpressions == null) 2216 scanExpressions = new ArrayList<Expression>(); 2217 scanExpressions.add(scanExp); 2218 } 2219 } 2220 } 2221