1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 import java.util.*; 8 import java.io.*; 9 import kawa.Shell; 10 import gnu.text.*; 11 import java.util.zip.*; 12 import java.util.Stack ; 13 14 18 19 public class Compilation implements SourceLocator 20 { 21 25 public boolean mustCompile; 26 27 28 int maxSelectorValue; 29 30 public ClassType curClass; 31 public ClassType mainClass; 32 33 public ClassType moduleClass; 34 35 public LambdaExp curLambda; 36 public ModuleExp mainLambda; 37 public Variable thisDecl; 38 39 40 Variable moduleInstanceVar; 41 42 46 private int state; 47 49 public int getState () { return state; } 50 public void setState (int state) { this.state = state; } 51 52 public static final int PROLOG_PARSING = 1; 53 54 public static final int PROLOG_PARSED = 2; 55 56 public static final int BODY_PARSED = 4; 57 58 public static final int RESOLVED = 6; 59 60 public static final int WALKED = 8; 61 62 public static final int COMPILE_SETUP = 10; 63 64 public static final int COMPILED = 12; 65 66 public static final int CLASS_WRITTEN = 14; 67 public static final int ERROR_SEEN = 100; 68 69 public ModuleInfo minfo; 70 public Lexer lexer; 71 72 boolean pedantic; 73 public boolean isPedantic() { return pedantic; } 74 75 88 Field moduleInstanceMainField; 89 90 public java.util.Stack pendingImports; 91 92 public void pushPendingImport (ModuleInfo info, ScopeExp defs) 93 { 94 if (pendingImports == null) 95 pendingImports = new java.util.Stack (); 96 pendingImports.push(info); 97 pendingImports.push(defs); 98 Expression posExp = new ReferenceExp((Object ) null); 99 posExp.setLine(this); 100 pendingImports.push(posExp); 101 } 102 103 105 public static boolean fewerClasses; 106 107 108 public static boolean debugPrintExpr = false; 109 110 111 public static boolean debugPrintFinalExpr; 112 113 public static Options options = new Options(); 114 public Options currentOptions = new Options(options); 115 static { 116 options.add("warn-undefined-variable", Options.BOOLEAN_OPTION, 117 "warn if no compiler-visible binding for a variable"); 118 options.add("warn-invoke-unknown-method", Options.BOOLEAN_OPTION, 119 "warn if invoke calls an unknown method"); 120 options.add("warn-as-error", Options.BOOLEAN_OPTION, 121 "Make all warnings into errors"); 122 } 123 124 125 public final boolean getBooleanOption (String key, boolean defaultValue) 126 { 127 return currentOptions.getBoolean(key, defaultValue); 128 } 129 130 131 public final boolean getBooleanOption (String key) 132 { 133 return currentOptions.getBoolean(key); 134 } 135 136 138 public static int defaultCallConvention; 139 public static final int CALL_WITH_UNSPECIFIED = 0; 140 141 public static final int CALL_WITH_RETURN = 1; 142 143 public static final int CALL_WITH_CONSUMER = 2; 144 145 public static final int CALL_WITH_TAILCALLS = 3; 146 147 public static final int CALL_WITH_CONTINUATIONS = 4; 148 149 public boolean usingCPStyle() 150 { return defaultCallConvention == CALL_WITH_CONTINUATIONS; } 151 public boolean usingTailCalls() 152 { return defaultCallConvention >= CALL_WITH_TAILCALLS; } 153 154 157 public static int moduleStatic = 0; 158 159 ClassType[] classes; 160 int numClasses; 161 162 164 ArrayClassLoader loader; 165 166 167 public boolean immediate; 168 169 170 public Method method; 171 172 Method clinitMethod; 173 174 public final CodeAttr getCode() { return method.getCode(); } 175 176 int method_counter; 177 178 180 SwitchState fswitch; 181 182 Field fswitchIndex; 183 184 static public ClassType typeObject = Type.pointer_type; 186 static public ClassType scmBooleanType = ClassType.make("java.lang.Boolean"); 187 static public ClassType typeString = ClassType.make("java.lang.String"); 188 static public ClassType javaStringType = typeString; 189 static public ClassType scmKeywordType = ClassType.make("gnu.expr.Keyword"); 190 static public ClassType scmSequenceType = ClassType.make("gnu.lists.Sequence"); 191 static public ClassType javaIntegerType = ClassType.make("java.lang.Integer"); 192 static public ClassType scmListType = ClassType.make("gnu.lists.LList"); 193 static public ClassType typePair = ClassType.make("gnu.lists.Pair"); 194 static public ClassType scmPairType = typePair; 195 public static final ArrayType objArrayType = ArrayType.make(typeObject); 196 static public ClassType scmNamedType = ClassType.make("gnu.mapping.Named"); 197 static public ClassType typeRunnable = ClassType.make("java.lang.Runnable"); 198 public static ClassType typeType = ClassType.make("gnu.bytecode.Type"); 199 public static ClassType typeObjectType 200 = ClassType.make("gnu.bytecode.ObjectType", typeType); 201 public static ClassType typeClass = Type.java_lang_Class_type; 202 static public ClassType typeClassType = ClassType.make("gnu.bytecode.ClassType", typeObjectType); 203 static public ClassType typeProcedure 204 = ClassType.make("gnu.mapping.Procedure"); 205 static public ClassType typeLanguage 206 = ClassType.make("gnu.expr.Language"); 207 static public ClassType typeEnvironment 208 = ClassType.make("gnu.mapping.Environment"); 209 static public ClassType typeLocation 210 = ClassType.make("gnu.mapping.Location"); 211 static public ClassType typeSymbol 212 = ClassType.make("gnu.mapping.Symbol"); 213 static public final Method getSymbolValueMethod 214 = typeLanguage.getDeclaredMethod("getSymbolValue", 1); 215 static public final Method getSymbolProcedureMethod 216 = typeLanguage.getDeclaredMethod("getSymbolProcedure", 1); 217 static public final Method getLocationMethod 218 = typeLocation.addMethod("get", Type.typeArray0, 219 Type.pointer_type, Access.PUBLIC); 220 static public final Method getProcedureBindingMethod 221 = typeSymbol.addMethod("getProcedure", Type.typeArray0, 222 typeProcedure, Access.PUBLIC); 223 static public final Field trueConstant 224 = scmBooleanType.getDeclaredField("TRUE"); 225 static public final Field falseConstant 226 = scmBooleanType.getDeclaredField("FALSE"); 227 228 static final Method setNameMethod 229 = typeProcedure.getDeclaredMethod("setName", 1); 230 static Method makeListMethod; 231 232 public static final Type[] int1Args = { Type.int_type }; 233 public static final Type[] string1Arg = { javaStringType }; 234 public static final Type[] sym1Arg = string1Arg; 235 236 static public final Method getLocation1EnvironmentMethod 237 = typeEnvironment.getDeclaredMethod("getLocation", 1); 238 static public final Method getLocation2EnvironmentMethod; 239 static { 240 Type[] args = { typeSymbol, Type.pointer_type }; 241 getLocation2EnvironmentMethod 242 = typeEnvironment.addMethod("getLocation", args, 243 typeLocation, Access.PUBLIC|Access.FINAL); 244 } 245 246 static { 247 Type[] makeListArgs = { objArrayType, Type.int_type }; 248 makeListMethod = scmListType.addMethod ("makeList", 249 makeListArgs, scmListType, 250 Access.PUBLIC|Access.STATIC); 251 } 252 253 public static Method getCurrentEnvironmentMethod 254 = typeEnvironment.addMethod("getCurrent", Type.typeArray0, 255 typeEnvironment,Access.PUBLIC|Access.STATIC); 256 257 public static Type[] apply0args = Type.typeArray0; 258 public static Type[] apply1args = { typeObject }; 259 public static Type[] apply2args = { typeObject, typeObject }; 260 public static Type[] applyNargs = { objArrayType }; 261 262 static Method checkArgCountMethod; 263 264 public static Method apply0method = typeProcedure.addMethod 265 ("apply0", apply0args, typeObject, Access.PUBLIC|Access.FINAL); 266 267 public static Method apply1method; 268 public static Method apply2method; 269 public static Method apply3method; 270 public static Method apply4method; 271 public static Method applyNmethod; 272 273 static 274 { 275 apply1method = typeProcedure.addMethod ("apply1", apply1args, 276 typeObject, Access.PUBLIC); 277 apply2method = typeProcedure.addMethod ("apply2", apply2args, 278 typeObject, Access.PUBLIC); 279 Type[] apply3args = { typeObject, typeObject, typeObject }; 280 apply3method = typeProcedure.addMethod ("apply3", apply3args, 281 typeObject, Access.PUBLIC); 282 Type[] apply4args = { typeObject , typeObject, typeObject, typeObject}; 283 apply4method = typeProcedure.addMethod ("apply4", apply4args, 284 typeObject, Access.PUBLIC); 285 applyNmethod = typeProcedure.addMethod ("applyN", applyNargs, 286 typeObject, Access.PUBLIC); 287 Type[] args = new Type[2]; 288 args[0] = typeProcedure; 289 args[1] = Type.int_type; 290 checkArgCountMethod 291 = typeProcedure.addMethod("checkArgCount", args, Type.void_type, 292 Access.PUBLIC|Access.STATIC); 293 } 294 295 public static Method[] applymethods = { 296 apply0method, apply1method, apply2method, apply3method, 297 apply4method, applyNmethod }; 298 299 public static ClassType typeProcedure0 300 = ClassType.make("gnu.mapping.Procedure0", typeProcedure); 301 public static ClassType typeProcedure1 302 = ClassType.make("gnu.mapping.Procedure1", typeProcedure); 303 public static ClassType typeProcedure2 304 = ClassType.make("gnu.mapping.Procedure2", typeProcedure); 305 public static ClassType typeProcedure3 306 = ClassType.make("gnu.mapping.Procedure3", typeProcedure); 307 public static ClassType typeProcedure4 308 = ClassType.make("gnu.mapping.Procedure4", typeProcedure); 309 public static ClassType typeProcedureN 310 = ClassType.make("gnu.mapping.ProcedureN", typeProcedure); 311 public static ClassType typeModuleBody 312 = ClassType.make("gnu.expr.ModuleBody", typeProcedure0); 313 public static ClassType typeModuleWithContext 314 = ClassType.make("gnu.expr.ModuleWithContext", typeModuleBody); 315 public static ClassType typeApplet = ClassType.make("java.applet.Applet"); 316 public static ClassType typeServlet = ClassType.make("gnu.kawa.servlet.KawaServlet"); 317 318 319 public static ClassType typeCallContext 320 = ClassType.make("gnu.mapping.CallContext"); 321 public static final ClassType typeConsumer 322 = ClassType.make("gnu.lists.Consumer"); 323 public static Method getCallContextInstanceMethod 324 = typeCallContext.getDeclaredMethod("getInstance", 0); 325 public static ClassType typeValues 326 = ClassType.make("gnu.mapping.Values"); 327 public static Field noArgsField 328 = typeValues.getDeclaredField("noArgs"); 329 public static Field pcCallContextField 330 = typeCallContext.getDeclaredField("pc"); 331 public static ClassType typeMethodProc 332 = ClassType.make("gnu.mapping.MethodProc", typeProcedureN); 333 public static ClassType typeModuleMethod 334 = ClassType.make("gnu.expr.ModuleMethod", typeMethodProc); 335 public static Field argsCallContextField 337 = typeCallContext.getDeclaredField("values"); 338 public static Field procCallContextField 339 = typeCallContext.getDeclaredField("proc"); 340 private static Type[] applyCpsArgs = { typeCallContext}; 341 public static Method applyCpsMethod 342 = typeProcedure.addMethod("apply", applyCpsArgs, Type.void_type, 343 Access.PUBLIC); 344 345 public static ClassType[] typeProcedureArray = { 346 typeProcedure0, typeProcedure1, typeProcedure2, typeProcedure3, 347 typeProcedure4 }; 348 349 350 Initializer clinitChain; 351 352 public static boolean generateMainDefault = false; 353 354 public boolean generateMain = generateMainDefault; 355 356 LitTable litTable; 357 358 public static boolean generateAppletDefault = false; 359 360 public boolean generateApplet = generateAppletDefault; 361 362 public static boolean generateServletDefault = false; 363 364 public boolean generateServlet = generateServletDefault; 365 366 public final ClassType getModuleType() 367 { 368 return (defaultCallConvention >= Compilation.CALL_WITH_CONSUMER 369 ? typeModuleWithContext 370 : typeModuleBody); 371 } 372 373 377 public void compileConstant (Object value) 378 { 379 gnu.bytecode.CodeAttr code = getCode(); 380 if (value == null) 381 code.emitPushNull(); 382 else if (value instanceof String && ! immediate) 383 code.emitPushString((String ) value); 384 else 385 code.emitGetStatic(compileConstantToField(value)); 386 } 387 388 public Field compileConstantToField (Object value) 389 { 390 Literal literal = litTable.findLiteral(value); 391 if (literal.field == null) 392 literal.assign(litTable); 393 return literal.field; 394 } 395 396 public static boolean inlineOk = true; 397 398 public boolean inlineOk (Expression proc) 399 { 400 if (proc instanceof LambdaExp) 401 { 402 if (! (((LambdaExp) proc).currentLambda() instanceof ModuleExp)) 405 return true; 406 } 407 return inlineOk; 408 } 409 410 public boolean inlineOk (Procedure proc) 411 { 412 return inlineOk; 413 } 414 415 public void compileConstant (Object value, Target target) 416 { 417 if (target instanceof IgnoreTarget) 418 return; 419 if (value instanceof Values) 420 { 421 Object [] values = ((Values) value).getValues(); 422 int len = values.length; 423 if (target instanceof ConsumerTarget) 424 { 425 for (int i = 0; i < len; i++) 426 { 427 compileConstant(values[i], target); 428 } 429 return; 430 } 431 else if (target instanceof SeriesTarget) 432 { 433 SeriesTarget starget = (SeriesTarget) target; 434 Label saveDone = starget.done; 435 if (len > 0) 436 { 437 starget.done = null; 438 for (int i = 0; i < len; i++) 439 { 440 if (i+1 == len) 441 starget.done = saveDone; 442 compileConstant(values[i], target); 443 } 444 } 445 else if (saveDone != null && getCode().reachableHere()) 446 getCode().emitGoto(saveDone); 447 return; 448 } 449 } 450 if (target instanceof ConditionalTarget) 451 { 452 ConditionalTarget ctarg = (ConditionalTarget) target; 453 getCode().emitGoto(getLanguage().isTrue(value) ? ctarg.ifTrue 454 : ctarg.ifFalse); 455 return; 456 } 457 if (target instanceof StackTarget) 458 { 459 Type type = ((StackTarget) target).getType(); 460 if (type instanceof PrimType) 461 { 462 try 463 { 464 String signature = type.getSignature(); 465 CodeAttr code = getCode(); 466 char sig1 = (signature == null || signature.length() != 1) ? ' ' 467 : signature.charAt(0); 468 if (value instanceof Number ) 469 { 470 Number num = (Number ) value; 471 switch (sig1) 472 { 473 case 'I': 474 code.emitPushInt(num.intValue()); 475 return; 476 case 'S': 477 code.emitPushInt(num.shortValue()); 478 return; 479 case 'B': 480 code.emitPushInt(num.byteValue()); 481 return; 482 case 'J': 483 code.emitPushLong(num.longValue()); 484 return; 485 case 'F': 486 code.emitPushFloat(num.floatValue()); 487 return; 488 case 'D': 489 code.emitPushDouble(num.doubleValue()); 490 return; 491 } 492 } 493 if (sig1 == 'C') 494 { 495 code.emitPushInt((int) ((PrimType) type).charValue(value)); 496 return; 497 } 498 if (sig1 == 'Z') 499 { 500 boolean val = PrimType.booleanValue(value); 501 code.emitPushInt(val ? 1 : 0); 502 return; 503 } 504 } 505 catch (ClassCastException ex) 506 { 507 } 509 } 510 try 511 { 512 value = type.coerceFromObject(value); 513 } 514 catch (Exception ex) 515 { 516 StringBuffer sbuf = new StringBuffer (); 517 if (value == Values.empty) 518 sbuf.append("cannot convert void to "); 519 else 520 { 521 sbuf.append("cannot convert literal (of type "); 522 sbuf.append(value.getClass().getName()); 523 sbuf.append(") to "); 524 } 525 sbuf.append(type.getName()); 526 error('w', sbuf.toString()); 527 } 528 } 529 compileConstant(value); 530 target.compileFromStack(this, 531 value == null ? target.getType() 532 : Type.make(value.getClass())); 533 } 534 535 536 private void dumpInitializers (Initializer inits) 537 { 538 for (Initializer init = Initializer.reverse(inits); 539 init != null; init = init.next) 540 init.emit(this); 541 } 542 543 546 public ClassType findNamedClass (String name) 547 { 548 for (int i = 0; i < numClasses; i++) 549 { 550 if (name.equals (classes[i].getName ())) 551 return classes[i]; 552 } 553 return null; 554 } 555 556 public static String classPrefixDefault = ""; 557 558 public String classPrefix = classPrefixDefault; 559 560 561 private static void putURLWords(String name, StringBuffer sbuf) 562 { 563 int dot = name.indexOf('.'); 564 if (dot > 0) 565 { 566 putURLWords(name.substring(dot+1), sbuf); 567 sbuf.append('.'); 568 name = name.substring(0, dot); 569 } 570 sbuf.append(name); 571 } 572 573 576 public static String mangleURI (String name) 577 { 578 boolean hasSlash = name.indexOf('/') >= 0; 579 int len = name.length(); 580 if (len > 6 && name.startsWith("class:")) 581 return name.substring(6); 582 if (len > 5 && name.charAt(4) == ':' 584 && name.substring(0, 4).equalsIgnoreCase("http")) 585 { 586 name = name.substring(5); 587 len -= 5; 588 hasSlash = true; 589 } 590 else if (len > 4 && name.charAt(3) == ':' 591 && name.substring(0, 3).equalsIgnoreCase("uri")) 592 { 593 name = name.substring(4); 594 len -= 4; 595 } 596 int start = 0; 597 StringBuffer sbuf = new StringBuffer (); 598 for (;;) 599 { 600 int slash = name.indexOf('/', start); 601 int end = slash < 0 ? len : slash; 602 boolean first = sbuf.length() == 0; 603 if (first && hasSlash) 604 { 605 String host = name.substring(start, end); 607 if (end - start > 4 && host.startsWith("www.")) 608 host = host.substring(4); 609 putURLWords(host, sbuf); 611 } 612 else if (start != end) 613 { 614 if (! first) 615 sbuf.append('.'); 616 if (end == len) 617 { 618 int dot = name.lastIndexOf('.', len); 619 if (dot > start + 1 && ! first) 620 { 621 int extLen = len - dot; 623 if (extLen <= 4 624 || (extLen == 5 && name.endsWith("html"))) 625 { 626 len -= extLen; 627 end = len; 628 name = name.substring(0, len); 629 } 630 } 631 } 632 sbuf.append(name.substring(start, end)); 633 } 634 if (slash < 0) 635 break; 636 start = slash + 1; 637 } 638 return sbuf.toString(); 639 } 640 641 public static String mangleName (String name) 642 { 643 return mangleName(name, -1); 644 } 645 646 public static String mangleNameIfNeeded (String name) 647 { 648 if (isValidJavaName(name)) 649 return name; 650 else 651 return mangleName(name, 0); 652 } 653 654 public static boolean isValidJavaName(String name) 655 { 656 int len = name.length(); 657 if (len == 0 || ! Character.isJavaIdentifierStart(name.charAt(0))) 658 return false; 659 for (int i = len; --i > 0; ) 660 if (! Character.isJavaIdentifierPart(name.charAt(i))) 661 return false; 662 return true; 663 } 664 665 668 public static String mangleName (String name, boolean reversible) 669 { 670 return mangleName(name, reversible ? 1 : -1); 671 } 672 673 678 public static String mangleName (String name, int kind) 679 { 680 boolean reversible = kind >= 0; 681 int len = name.length (); 682 if (len == 6 && name.equals("*init*")) return "<init>"; 684 StringBuffer mangled = new StringBuffer (len); 685 boolean upcaseNext = false; 686 for (int i = 0; i < len; i++) 687 { 688 char ch = name.charAt(i); 689 if (upcaseNext) 690 { 691 ch = Character.toTitleCase(ch); 692 upcaseNext = false; 693 } 694 if (Character.isDigit(ch)) 695 { 696 if (i == 0) 697 mangled.append("$N"); 698 mangled.append(ch); 699 } 700 else if (Character.isLetter(ch) || ch == '_') 701 mangled.append(ch); 702 else if (ch == '$') 703 mangled.append(kind > 1 ? "$$" : "$"); 704 else 705 { 706 switch (ch) 707 { 708 case '+': mangled.append("$Pl"); break; 709 case '-': 710 if (reversible) 711 mangled.append("$Mn"); 712 else 713 { 714 char next = i + 1 < len ? name.charAt(i+1) : '\0'; 715 if (next == '>') 716 { 717 mangled.append("$To$"); 718 i++; 719 } 720 else if (! Character.isLowerCase(next)) 721 mangled.append("$Mn"); 722 } 723 break; 724 case '*': mangled.append("$St"); break; 725 case '/': mangled.append("$Sl"); break; 726 case '=': mangled.append("$Eq"); break; 727 case '<': mangled.append("$Ls"); break; 728 case '>': mangled.append("$Gr"); break; 729 case '@': mangled.append("$At"); break; 730 case '~': mangled.append("$Tl"); break; 731 case '%': mangled.append("$Pc"); break; 732 case '.': mangled.append("$Dt"); break; 733 case ',': mangled.append("$Cm"); break; 734 case '(': mangled.append("$LP"); break; 735 case ')': mangled.append("$RP"); break; 736 case '[': mangled.append("$LB"); break; 737 case ']': mangled.append("$RB"); break; 738 case '{': mangled.append("$LC"); break; 739 case '}': mangled.append("$RC"); break; 740 case '\'': mangled.append("$Sq"); break; 741 case '"': mangled.append("$Dq"); break; 742 case '&': mangled.append("$Am"); break; 743 case '#': mangled.append("$Nm"); break; 744 case '?': 745 char first = mangled.length() > 0 ? mangled.charAt(0) : '\0'; 746 if (! reversible 747 && i + 1 == len && Character.isLowerCase(first)) 748 { 749 mangled.setCharAt(0, Character.toTitleCase(first)); 750 mangled.insert(0, "is"); 751 } 752 else 753 mangled.append("$Qu"); 754 break; 755 case '!': mangled.append("$Ex"); break; 756 case ':': mangled.append("$Cl"); break; 757 case ';': mangled.append("$SC"); break; 758 case '^': mangled.append("$Up"); break; 759 case '|': mangled.append("$VB"); break; 760 default: 761 mangled.append('$'); 762 mangled.append(Character.forDigit ((ch >> 12) & 15, 16)); 763 mangled.append(Character.forDigit ((ch >> 8) & 15, 16)); 764 mangled.append(Character.forDigit ((ch >> 4) & 15, 16)); 765 mangled.append(Character.forDigit ((ch ) & 15, 16)); 766 } 767 if (! reversible) 768 upcaseNext = true; 769 } 770 } 771 String mname = mangled.toString (); 772 return mname.equals(name) ? name : mname; 773 } 774 775 778 public static char demangle2(char char1, char char2) 779 { 780 switch (char1 << 16 | char2) 781 { 782 case 'A' << 16 | 'm': return '&'; 783 case 'A' << 16 | 't': return '@'; 784 case 'C' << 16 | 'l': return ':'; 785 case 'C' << 16 | 'm': return ','; 786 case 'D' << 16 | 'q': return '\"'; 787 case 'D' << 16 | 't': return '.'; 788 case 'E' << 16 | 'q': return '='; 789 case 'E' << 16 | 'x': return '!'; 790 case 'G' << 16 | 'r': return '>'; 791 case 'L' << 16 | 'B': return '['; 792 case 'L' << 16 | 'C': return '{'; 793 case 'L' << 16 | 'P': return '('; 794 case 'L' << 16 | 's': return '<'; 795 case 'M' << 16 | 'c': return '%'; 796 case 'M' << 16 | 'n': return '-'; 797 case 'N' << 16 | 'm': return '#'; 798 case 'P' << 16 | 'c': return '%'; 799 case 'P' << 16 | 'l': return '+'; 800 case 'Q' << 16 | 'u': return '?'; 801 case 'R' << 16 | 'B': return ']'; 802 case 'R' << 16 | 'C': return '}'; 803 case 'R' << 16 | 'P': return ')'; 804 case 'S' << 16 | 'C': return ';'; 805 case 'S' << 16 | 'l': return '/'; 806 case 'S' << 16 | 'q': return '\\'; 807 case 'S' << 16 | 't': return '*'; 808 case 'T' << 16 | 'l': return '~'; 809 case 'U' << 16 | 'p': return '^'; 810 case 'V' << 16 | 'B': return '|'; 811 } 812 return (char) (-1); 813 } 814 815 public static String demangleName(String name) 816 { 817 return demangleName(name, false); 818 } 819 820 public static String demangleName(String name, boolean reversible) 821 { 822 StringBuffer sbuf = new StringBuffer (); 823 int len = name.length(); 824 boolean mangled = false; 825 boolean predicate = false; 826 boolean downCaseNext = false; 827 for (int i = 0; i < len; i++) 828 { 829 char ch = name.charAt(i); 830 if (downCaseNext && ! reversible) 831 { 832 ch = Character.toLowerCase(ch); 833 downCaseNext = false; 834 } 835 char d; 836 if (!reversible 837 && ch == 'i' && i == 0 && len > 2 && name.charAt(i+1) == 's' 838 && ! Character.isLowerCase(d = name.charAt(i+2))) 839 { 840 mangled = true; 841 predicate = true; 842 i++; 843 if (Character.isUpperCase(d) || Character.isTitleCase(d)) 844 { 845 sbuf.append(Character.toLowerCase(d)); 846 i++; 847 continue; 848 } 849 continue; 850 } 851 else if (ch == '$' && i + 2 < len) 852 { 853 char c1 = name.charAt(i+1); 854 char c2 = name.charAt(i+2); 855 d = Compilation.demangle2(c1, c2); 856 if (d != (char)(-1)) 857 { 858 sbuf.append(d); 859 i += 2; 860 mangled = true; 861 downCaseNext = true; 862 continue; 863 } 864 else if (c1 == 'T' && c2 == 'o' && i + 3 < len 865 && name.charAt(i+3) == '$') 866 { 867 sbuf.append("->"); 868 i += 3; 869 mangled = true; 870 downCaseNext = true; 871 continue; 872 } 873 } 874 else if (! reversible && i > 1 875 && (Character.isUpperCase(ch) || Character.isTitleCase(ch)) 876 && (Character.isLowerCase(name.charAt(i-1)))) 877 { 878 sbuf.append('-'); 879 mangled = true; 880 ch = Character.toLowerCase(ch); 881 } 882 sbuf.append(ch); 883 } 884 if (predicate) 885 sbuf.append('?'); 886 return mangled ? sbuf.toString() : name; 887 } 888 889 893 public String generateClassName (String hint) 894 { 895 hint = mangleName(hint, true); 896 if (mainClass != null) 897 hint = mainClass.getName() + '$' + hint; 898 else if (classPrefix != null) 899 hint = classPrefix + hint; 900 if (findNamedClass (hint) == null) 901 return hint; 902 for (int i = 0; ; i++) 903 { 904 String new_hint = hint + i; 905 if (findNamedClass (new_hint) == null) 906 return new_hint; 907 } 908 } 909 910 public Compilation (boolean immediate, SourceMessages messages) 911 { 912 this(messages); 913 this.immediate = immediate; 914 } 915 916 public Compilation (SourceMessages messages) 917 { 918 this.messages = messages; 919 lexical = new NameLookup(getLanguage()); 920 } 921 922 public Compilation (Language language, SourceMessages messages) 923 { 924 this(language, messages, new NameLookup(language)); 925 } 926 927 public Compilation (Language language, SourceMessages messages, 928 NameLookup lexical) 929 { 930 this.language = language; 931 this.messages = messages; 932 this.lexical = lexical; 933 } 934 935 936 public void walkModule (ModuleExp mexp) 937 { 938 if (debugPrintExpr) 939 { 940 OutPort dout = OutPort.errDefault(); 941 dout.println("[Module:" + mexp.getName()); 942 mexp.print(dout); 943 dout.println(']'); 944 dout.flush(); 945 } 946 947 InlineCalls.inlineCalls(mexp, this); 948 PushApply.pushApply(mexp); 949 ChainLambdas.chainLambdas(mexp, this); 950 FindTailCalls.findTailCalls(mexp, this); 951 } 952 953 public void outputClass (String directory) throws IOException 954 { 955 char dirSep = File.separatorChar; 956 for (int iClass = 0; iClass < numClasses; iClass++) 957 { 958 ClassType clas = classes[iClass]; 959 String out_name 960 = (directory + clas.getName().replace('.', dirSep) 961 + ".class"); 962 String parent = new File(out_name).getParent(); 963 if (parent != null) 964 new File(parent).mkdirs(); 965 clas.writeToFile(out_name); 966 967 clas.cleanupAfterCompilation(); 968 } 969 970 minfo.comp = null; 971 mainLambda.body = null; 972 mainLambda = null; 973 litTable = null; 974 } 975 976 public void compileToArchive (ModuleExp mexp, String fname) 977 throws java.io.IOException 978 { 979 boolean makeJar = false; 980 if (fname.endsWith(".zip")) 981 makeJar = false; 982 else if (fname.endsWith(".jar")) 983 makeJar = true; 984 else 985 { 986 fname = fname + ".zip"; 987 makeJar = false; 988 } 989 990 process(COMPILED); 991 992 File zar_file = new File (fname); 993 if (zar_file.exists ()) 994 zar_file.delete (); 995 ZipOutputStream zout; 996 997 if (makeJar) 998 zout = new java.util.jar.JarOutputStream (new FileOutputStream(zar_file)); 999 else 1000 1001 { 1002 zout = new ZipOutputStream (new FileOutputStream (zar_file)); 1003 zout.setMethod(ZipOutputStream.STORED); } 1005 1006 byte[][] classBytes = new byte[numClasses][]; 1007 CRC32 zcrc = new CRC32(); 1008 for (int iClass = 0; iClass < numClasses; iClass++) 1009 { 1010 ClassType clas = classes[iClass]; 1011 classBytes[iClass] = clas.writeToArray (); 1012 ZipEntry zent = new ZipEntry(clas.getName ().replace ('.', '/') 1013 + ".class"); 1014 1015 zent.setSize(classBytes[iClass].length); 1016 zcrc.reset(); 1017 zcrc.update(classBytes[iClass], 0, classBytes[iClass].length); 1018 zent.setCrc(zcrc.getValue()); 1019 1020 zout.putNextEntry (zent); 1021 zout.write (classBytes[iClass]); 1022 } 1023 zout.close (); 1024 } 1025 1026 public static boolean emitSourceDebugExtAttr = true; 1028 1029 private void registerClass (ClassType new_class) 1030 { 1031 if (classes == null) 1032 classes = new ClassType[20]; 1033 else if (numClasses >= classes.length) 1034 { 1035 ClassType[] new_classes = new ClassType[2 * classes.length]; 1036 System.arraycopy (classes, 0, new_classes, 0, numClasses); 1037 classes = new_classes; 1038 } 1039 new_class.access_flags |= new_class.isInterface() ? Access.PUBLIC 1040 : Access.PUBLIC|Access.SUPER; 1041 if (new_class == mainClass && numClasses > 0) 1042 { 1043 new_class = classes[0]; 1045 classes[0] = mainClass; 1046 } 1047 classes[numClasses++] = new_class; 1048 } 1049 1050 public void addClass (ClassType new_class) 1051 { 1052 if (mainLambda.filename != null) 1053 { 1054 if (emitSourceDebugExtAttr) 1055 new_class.setStratum(getLanguage().getName()); 1056 new_class.setSourceFile(mainLambda.filename); 1057 } 1058 registerClass(new_class); 1059 1060 1062 } 1063 1064 public void addMainClass (ModuleExp module) 1065 { 1066 mustCompile = true; 1067 1068 mainClass = module.classFor(this); 1069 1070 ClassType type = mainClass; 1071 ClassType[] interfaces = module.getInterfaces(); 1072 if (interfaces != null) 1073 type.setInterfaces(interfaces); 1074 ClassType sup = module.getSuperType(); 1075 if (sup == null) 1076 { 1077 if (generateApplet) 1078 sup = typeApplet; 1079 else if (generateServlet) 1080 sup = typeServlet; 1081 else 1082 sup = getModuleType(); 1083 } 1084 if (! generateServlet) 1085 type.addInterface(typeRunnable); 1086 type.setSuper(sup); 1087 1088 module.type = type; 1089 addClass(type); 1090 getConstructor(mainClass, module); 1091 } 1092 1093 public final Method getConstructor (LambdaExp lexp) 1094 { 1095 return getConstructor(lexp.getHeapFrameType(), lexp); 1096 } 1097 1098 public static final Method getConstructor (ClassType clas, LambdaExp lexp) 1099 { 1100 Method meth = clas.getDeclaredMethod("<init>", 0); 1101 if (meth != null) 1102 return meth; 1103 Type[] args; 1104 if (lexp instanceof ClassExp && lexp.staticLinkField != null) 1105 { 1106 args = new Type[1]; 1107 args[0] = lexp.staticLinkField.getType(); 1108 } 1109 else 1110 args = apply0args; 1111 return clas.addMethod("<init>", Access.PUBLIC, args, Type.void_type); 1112 } 1113 1114 public final void generateConstructor (LambdaExp lexp) 1115 { 1116 generateConstructor (lexp.getHeapFrameType(), lexp); 1117 } 1118 1119 public final void generateConstructor (ClassType clas, LambdaExp lexp) 1120 { 1121 Method save_method = method; 1122 Variable callContextSave = callContextVar; 1123 callContextVar = null; 1124 ClassType save_class = curClass; 1125 curClass = clas; 1126 Method constructor_method = getConstructor(clas, lexp); 1127 clas.constructor = constructor_method; 1128 method = constructor_method; 1129 CodeAttr code = constructor_method.startCode(); 1130 1131 if (lexp instanceof ClassExp && lexp.staticLinkField != null) 1132 { 1133 code.emitPushThis(); 1134 code.emitLoad(code.getCurrentScope().getVariable(1)); 1135 code.emitPutField(lexp.staticLinkField); 1136 } 1137 Method superConstructor 1138 = clas.getSuperclass().addMethod("<init>", Access.PUBLIC, 1139 apply0args, Type.void_type); 1140 code.emitPushThis(); 1141 code.emitInvokeSpecial(superConstructor); 1142 1143 if (curClass == mainClass 1144 && minfo != null && minfo.sourcePath != null) 1147 { 1148 code.emitPushThis(); 1149 code.emitInvokeStatic(ClassType.make("gnu.expr.ModuleInfo") 1150 .getDeclaredMethod("register", 1)); 1151 } 1152 1153 if (lexp.initChain != null) 1154 { 1155 LambdaExp save = curLambda; 1158 curLambda = new LambdaExp(); 1159 curLambda.closureEnv = code.getArg(0); 1160 curLambda.outer = save; 1161 Initializer init; 1162 while ((init = lexp.initChain) != null) 1163 { 1164 lexp.initChain = null; 1165 dumpInitializers(init); 1166 } 1167 curLambda = save; 1168 } 1169 1170 if (lexp instanceof ClassExp) 1171 { 1172 ClassExp cexp = (ClassExp) lexp; 1173 callInitMethods(cexp.getCompiledClassType(this), new Vector(10)); 1174 } 1175 1176 code.emitReturn(); 1177 method = save_method; 1178 curClass = save_class; 1179 callContextVar = callContextSave; 1180 } 1181 1182 1187 void callInitMethods (ClassType clas, Vector seen) 1188 { 1189 if (clas == null) 1190 return; 1191 1192 String name = clas.getName(); 1193 if ("java.lang.Object".equals(name)) 1194 return; 1195 for (int i = seen.size(); --i >= 0; ) 1197 if (((ClassType) seen.elementAt(i)).getName() == name) 1198 return; 1199 seen.addElement(clas); 1200 1201 ClassType[] interfaces = clas.getInterfaces(); 1205 if (interfaces != null) 1206 { 1207 int n = interfaces.length; 1208 for (int i = 0; i < n; i++) 1209 callInitMethods(interfaces[i], seen); 1210 } 1211 1212 int clEnvArgs = 1; 1213 if (clas instanceof PairClassType) 1214 clas = ((PairClassType) clas).instanceType; 1215 else if (clas.isInterface()) 1216 { 1217 try 1218 { 1219 clas = ((ClassType) 1220 Type.make(Class.forName(clas.getName() + "$class"))); 1221 } 1222 catch (Throwable ex) 1223 { 1224 return; 1225 } 1226 } 1227 else 1228 clEnvArgs = 0; 1229 Method meth = clas.getDeclaredMethod("$finit$", clEnvArgs); 1230 if (meth != null) 1231 { 1232 CodeAttr code = getCode(); 1233 code.emitPushThis(); 1234 code.emitInvoke(meth); 1235 } 1236 } 1237 1238 public void generateMatchMethods(LambdaExp lexp) 1239 { 1240 int numApplyMethods 1241 = lexp.applyMethods == null ? 0 : lexp.applyMethods.size(); 1242 if (numApplyMethods == 0) 1243 return; 1244 Method save_method = method; 1245 ClassType save_class = curClass; 1246 ClassType procType = typeModuleMethod; 1247 curClass = lexp.getHeapFrameType(); 1248 if (! (curClass.getSuperclass().isSubtype(typeModuleBody))) 1249 curClass = moduleClass; 1250 CodeAttr code = null; 1251 for (int i = 0; i <= 5; i++) 1252 { 1253 boolean needThisMatch = false; 1254 SwitchState aswitch = null; 1255 String mname = null; 1256 Type[] matchArgs = null; 1257 for (int j = numApplyMethods; --j >= 0; ) 1258 { 1259 LambdaExp source = (LambdaExp) lexp.applyMethods.elementAt(j); 1260 Method[] primMethods = source.primMethods; 1263 int numMethods = primMethods.length; 1264 boolean varArgs = source.max_args < 0 1265 || source.max_args >= source.min_args + numMethods; 1266 int methodIndex; 1267 if (i < 5) { 1269 methodIndex = i - source.min_args; 1270 if (methodIndex < 0 || methodIndex >= numMethods 1271 || (methodIndex == numMethods - 1 && varArgs)) 1272 continue; 1273 numMethods = 1; 1274 varArgs = false; 1275 } 1276 else { 1278 methodIndex = 5 - source.min_args; 1279 if (methodIndex > 0 && numMethods <= methodIndex && ! varArgs) 1280 continue; 1281 methodIndex = numMethods-1; 1282 } 1283 if (! needThisMatch) 1284 { 1285 if (i < 5) 1287 { 1288 mname = "match"+i; 1289 matchArgs = new Type[i + 2]; 1290 for (int k = i; k >= 0; k--) 1291 matchArgs[k+1] = typeObject; 1292 matchArgs[i+1] = typeCallContext; 1293 } 1294 else 1295 { 1296 mname = "matchN"; 1297 matchArgs = new Type[3]; 1298 matchArgs[1] = objArrayType; 1299 matchArgs[2] = typeCallContext; 1300 } 1301 matchArgs[0] = procType; 1302 method = curClass.addMethod (mname, matchArgs, Type.int_type, 1303 Access.PUBLIC); 1304 code = method.startCode(); 1305 1306 code.emitLoad(code.getArg(1)); code.emitGetField(procType.getField("selector")); 1308 aswitch = new SwitchState(code); 1309 1310 needThisMatch = true; 1311 } 1312 1313 aswitch.addCase(source.getSelectorValue(this), code); 1314 1315 int line = source.getLineNumber(); 1316 if (line > 0) 1317 code.putLineNumber(source.getFileName(), line); 1318 1319 Variable ctxVar = code.getArg(i == 5 ? 3 : i+2); 1320 1321 if (i < 5) 1322 { 1323 Declaration var = source.firstDecl(); 1324 for (int k = 1; k <= i; k++) 1325 { 1326 code.emitLoad(ctxVar); 1327 code.emitLoad(code.getArg(k+1)); 1328 Type ptype = var.getType(); 1329 if (ptype != Type.pointer_type) 1330 { 1331 if (ptype instanceof TypeValue) 1332 { 1333 Label trueLabel = new Label(code), 1334 falseLabel = new Label(code); 1335 ConditionalTarget ctarget = 1336 new ConditionalTarget(trueLabel, falseLabel, 1337 getLanguage()); 1338 code.emitDup(); 1339 ((TypeValue) ptype).emitIsInstance(null, this, 1340 ctarget); 1341 falseLabel.define(code); 1342 code.emitPushInt(MethodProc.NO_MATCH_BAD_TYPE|k); 1343 code.emitReturn(); 1344 trueLabel.define(code); 1345 } 1346 else if (ptype instanceof ClassType 1347 && ptype != Type.pointer_type 1348 && ptype != Type.tostring_type) { 1350 code.emitDup(); 1351 ptype.emitIsInstance(code); 1352 code.emitIfIntEqZero(); 1353 code.emitPushInt(MethodProc.NO_MATCH_BAD_TYPE|k); 1354 code.emitReturn(); 1355 code.emitFi(); 1356 } 1357 } 1358 code.emitPutField(typeCallContext.getField("value"+k)); 1359 var = var.nextDecl(); 1360 } 1361 } 1362 else 1363 { 1364 code.emitLoad(ctxVar); 1366 code.emitLoad(code.getArg(2)); 1367 code.emitPutField(typeCallContext.getField("values")); 1368 } 1369 code.emitLoad(ctxVar); 1370 if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER) 1371 code.emitLoad(code.getArg(1)); else 1373 code.emitLoad(code.getArg(0)); code.emitPutField(procCallContextField); 1375 code.emitLoad(ctxVar); 1376 if (defaultCallConvention >= CALL_WITH_CONSUMER) 1377 code.emitPushInt(source.getSelectorValue(this)+methodIndex); 1378 else 1379 code.emitPushInt(i); 1380 code.emitPutField(pcCallContextField); 1381 code.emitPushInt(0); 1382 code.emitReturn(); 1383 } 1384 if (needThisMatch) 1385 { 1386 aswitch.addDefault(code); 1387 int nargs = i > 4 ? 2 : i + 1; 1388 nargs++; 1389 for (int k = 0; k <= nargs; k++) 1390 code.emitLoad(code.getArg(k)); 1391 Method defMethod = (typeModuleBody 1392 .getDeclaredMethod(mname, matchArgs.length)); 1393 code.emitInvokeSpecial(defMethod); 1394 code.emitReturn(); 1395 aswitch.finish(code); 1396 } 1397 } 1398 method = save_method; 1399 curClass = save_class; 1400 } 1401 1402 1405 public void generateApplyMethodsWithContext(LambdaExp lexp) 1406 { 1407 int numApplyMethods 1408 = lexp.applyMethods == null ? 0 : lexp.applyMethods.size(); 1409 if (numApplyMethods == 0) 1410 return; 1411 ClassType save_class = curClass; 1412 curClass = lexp.getHeapFrameType(); 1413 if (! (curClass.getSuperclass().isSubtype(typeModuleWithContext))) 1414 curClass = moduleClass; 1415 ClassType procType = typeModuleMethod; 1416 Method save_method = method; 1417 CodeAttr code = null; 1418 Type[] applyArgs = { typeCallContext }; 1419 1420 method = curClass.addMethod ("apply", applyArgs, 1422 (Type) Type.void_type, 1423 Access.PUBLIC); 1424 code = method.startCode(); 1425 Variable ctxVar = code.getArg(1); 1426 1427 code.emitLoad(ctxVar); 1428 code.emitGetField(pcCallContextField); 1429 SwitchState aswitch = new SwitchState(code); 1430 1431 for (int j = 0; j < numApplyMethods; ++j) 1432 { 1433 LambdaExp source = (LambdaExp) lexp.applyMethods.elementAt(j); 1434 Method[] primMethods = source.primMethods; 1435 int numMethods = primMethods.length; 1436 1437 for (int i = 0; i < numMethods; i++) 1438 { 1439 boolean varArgs 1442 = (i == numMethods - 1 1443 && (source.max_args < 0 1444 || source.max_args >= source.min_args + numMethods)); 1445 int methodIndex = i; 1446 1447 aswitch.addCase(source.getSelectorValue(this) + i, code); 1448 1449 int line = source.getLineNumber(); 1450 if (line > 0) 1451 code.putLineNumber(source.getFileName(), line); 1452 1453 Method primMethod = primMethods[methodIndex]; 1454 Type[] primArgTypes = primMethod.getParameterTypes(); 1455 int singleArgs = source.min_args+methodIndex; 1456 Variable counter = null; 1457 int pendingIfEnds = 0; 1458 1459 if (i > 4 && numMethods > 1) { 1461 counter = code.addLocal(Type.int_type); 1462 code.emitLoad(ctxVar); 1463 code.emitGetField(typeCallContext.getDeclaredField("count")); 1464 if (source.min_args != 0) 1465 { 1466 code.emitPushInt(source.min_args); 1467 code.emitSub(Type.int_type); 1468 } 1469 code.emitStore(counter); 1470 } 1471 1472 int needsThis = primMethod.getStaticFlag() ? 0 : 1; 1473 int explicitFrameArg 1474 = singleArgs + (varArgs ? 2 : 1) < primArgTypes.length ? 1 : 0; 1475 if (needsThis + explicitFrameArg > 0) 1476 { 1477 code.emitPushThis(); 1478 if (curClass == moduleClass && mainClass != moduleClass) 1479 code.emitGetField(moduleInstanceMainField); 1480 } 1481 1482 Declaration var = source.firstDecl(); 1483 for (int k = 0; k < singleArgs; k++) 1484 { 1485 if (counter != null && k >= source.min_args) 1486 { 1487 code.emitLoad(counter); 1488 code.emitIfIntLEqZero(); 1489 code.emitLoad(ctxVar); 1490 code.emitInvoke(primMethods[k - source.min_args]); 1491 code.emitElse(); 1492 pendingIfEnds++; 1493 code.emitInc(counter, (short) (-1)); 1494 } 1495 1496 code.emitLoad(ctxVar); 1497 if (k <= 4 && ! varArgs && source.max_args <= 4) 1498 code.emitGetField(typeCallContext 1499 .getDeclaredField("value"+(k+1))); 1500 else 1501 { 1502 code.emitGetField(typeCallContext 1503 .getDeclaredField("values")); 1504 code.emitPushInt(k); 1505 code.emitArrayLoad(Type.pointer_type); 1506 } 1507 Type ptype = var.getType(); 1508 if (ptype != Type.pointer_type) 1509 CheckedTarget.emitCheckedCoerce(this, source, 1510 k+1, ptype); 1511 var = var.nextDecl(); 1512 } 1513 1514 if (varArgs) 1515 { 1516 Type lastArgType = primArgTypes[explicitFrameArg+singleArgs]; 1517 if (lastArgType instanceof ArrayType) 1518 { 1519 Type elType 1520 = ((ArrayType) lastArgType).getComponentType(); 1521 boolean mustConvert 1522 = ! "java.lang.Object".equals(elType.getName()); 1523 if (mustConvert) 1524 new Error ("not implemented mustConvert restarg"); 1525 code.emitLoad(ctxVar); 1526 code.emitPushInt(singleArgs); 1527 code.emitInvokeVirtual(typeCallContext.getDeclaredMethod("getRestArgsArray", 1)); 1528 } 1529 else if ("gnu.lists.LList".equals 1530 (lastArgType.getName())) 1531 { 1532 code.emitLoad(ctxVar); 1533 code.emitPushInt(singleArgs); 1534 code.emitInvokeVirtual(typeCallContext.getDeclaredMethod("getRestArgsList", 1)); 1535 } 1536 else if (lastArgType == typeCallContext) 1537 code.emitLoad(ctxVar); 1538 else 1539 throw new RuntimeException ("unsupported #!rest type:"+lastArgType); 1540 } 1541 code.emitLoad(ctxVar); code.emitInvoke(primMethod); 1543 while (--pendingIfEnds >= 0) 1544 code.emitFi(); 1545 if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER) 1546 Target.pushObject.compileFromStack(this, 1547 source.getReturnType()); 1548 code.emitReturn(); 1549 } 1550 } 1551 aswitch.addDefault(code); 1552 Method errMethod = typeModuleMethod.getDeclaredMethod("applyError", 0); 1553 code.emitInvokeStatic(errMethod); 1554 code.emitReturn(); 1555 aswitch.finish(code); 1556 method = save_method; 1557 curClass = save_class; 1558 } 1559 1560 1564 public void generateApplyMethodsWithoutContext(LambdaExp lexp) 1565 { 1566 int numApplyMethods 1567 = lexp.applyMethods == null ? 0 : lexp.applyMethods.size(); 1568 if (numApplyMethods == 0) 1569 return; 1570 ClassType save_class = curClass; 1571 curClass = lexp.getHeapFrameType(); 1572 ClassType procType = typeModuleMethod; 1573 if (! (curClass.getSuperclass().isSubtype(typeModuleBody))) 1574 curClass = moduleClass; 1575 Method save_method = method; 1576 CodeAttr code = null; 1577 for (int i = defaultCallConvention >= Compilation.CALL_WITH_CONSUMER 1578 ? 5 : 0; 1579 i < 6; i++) 1580 { 1581 boolean needThisApply = false; 1584 SwitchState aswitch = null; 1585 String mname = null; 1586 Type[] applyArgs = null; 1587 1588 for (int j = numApplyMethods; --j >= 0; ) 1589 { 1590 LambdaExp source = (LambdaExp) lexp.applyMethods.elementAt(j); 1591 Method[] primMethods = source.primMethods; 1594 int numMethods = primMethods.length; 1595 boolean varArgs = source.max_args < 0 1596 || source.max_args >= source.min_args + numMethods; 1597 int methodIndex; 1598 boolean skipThisProc = false; 1599 if (i < 5) { 1601 methodIndex = i - source.min_args; 1602 if (methodIndex < 0 || methodIndex >= numMethods 1603 || (methodIndex == numMethods - 1 && varArgs)) 1604 skipThisProc = true; 1605 numMethods = 1; 1606 varArgs = false; 1607 } 1608 else { 1610 methodIndex = 5 - source.min_args; 1611 if (methodIndex > 0 && numMethods <= methodIndex && ! varArgs) 1612 skipThisProc = true; 1613 methodIndex = numMethods-1; 1614 } 1615 if (skipThisProc) 1616 continue; 1617 if (! needThisApply) 1618 { 1619 if (i < 5) 1621 { 1622 mname = "apply"+i; 1623 applyArgs = new Type[i + 1]; 1624 for (int k = i; k > 0; k--) 1625 applyArgs[k] = typeObject; 1626 } 1627 else 1628 { 1629 mname = "applyN"; 1630 applyArgs = new Type[2]; 1631 applyArgs[1] = objArrayType; 1632 } 1633 applyArgs[0] = procType; 1634 method = curClass.addMethod (mname, applyArgs, 1635 defaultCallConvention >= Compilation.CALL_WITH_CONSUMER ? (Type) Type.void_type : (Type) Type.pointer_type, 1636 Access.PUBLIC); 1637 code = method.startCode(); 1638 1639 code.emitLoad(code.getArg(1)); code.emitGetField(procType.getField("selector")); 1641 aswitch = new SwitchState(code); 1642 1643 needThisApply = true; 1644 } 1645 1646 aswitch.addCase(source.getSelectorValue(this), code); 1647 1648 int line = source.getLineNumber(); 1649 if (line > 0) 1650 code.putLineNumber(source.getFileName(), line); 1651 1652 Method primMethod = primMethods[methodIndex]; 1653 Type[] primArgTypes = primMethod.getParameterTypes(); 1654 int singleArgs = source.min_args+methodIndex; 1655 Variable counter = null; 1656 int pendingIfEnds = 0; 1657 1658 if (i > 4 && numMethods > 1) 1659 { 1660 counter = code.addLocal(Type.int_type); 1661 code.emitLoad(code.getArg(2)); 1662 code.emitArrayLength(); 1663 if (source.min_args != 0) 1664 { 1665 code.emitPushInt(source.min_args); 1666 code.emitSub(Type.int_type); 1667 } 1668 code.emitStore(counter); 1669 } 1670 1671 int needsThis = primMethod.getStaticFlag() ? 0 : 1; 1672 int explicitFrameArg 1673 = singleArgs + (varArgs ? 1 : 0) < primArgTypes.length ? 1 : 0; 1674 if (needsThis + explicitFrameArg > 0) 1675 { 1676 code.emitPushThis(); 1677 if (curClass == moduleClass && mainClass != moduleClass) 1678 code.emitGetField(moduleInstanceMainField); 1679 } 1680 1681 Declaration var = source.firstDecl(); 1682 for (int k = 0; k < singleArgs; k++) 1683 { 1684 if (counter != null && k >= source.min_args) 1685 { 1686 code.emitLoad(counter); 1687 code.emitIfIntLEqZero(); 1688 code.emitInvoke(primMethods[k - source.min_args]); 1689 code.emitElse(); 1690 pendingIfEnds++; 1691 code.emitInc(counter, (short) (-1)); 1692 } 1693 1694 Variable pvar = null; 1695 if (i <= 4) { 1697 pvar = code.getArg(k + 2); 1698 code.emitLoad(pvar); 1699 } 1700 else { 1702 code.emitLoad(code.getArg(2)); 1704 code.emitPushInt(k); 1705 code.emitArrayLoad(Type.pointer_type); 1706 } 1707 Type ptype = var.getType(); 1708 if (ptype != Type.pointer_type) 1709 CheckedTarget.emitCheckedCoerce(this, source, 1710 k+1, ptype, pvar); 1711 var = var.nextDecl(); 1712 } 1713 1714 if (varArgs) 1715 { 1716 Type lastArgType = primArgTypes[explicitFrameArg+singleArgs]; 1717 if (lastArgType instanceof ArrayType) 1718 { 1719 Type elType 1720 = ((ArrayType) lastArgType).getComponentType(); 1721 boolean mustConvert 1722 = ! "java.lang.Object".equals(elType.getName()); 1723 if (singleArgs == 0 && ! mustConvert) 1724 code.emitLoad(code.getArg(2)); else 1726 { 1727 code.pushScope(); 1728 if (counter == null) 1729 { 1730 counter = code.addLocal(Type.int_type); 1731 code.emitLoad(code.getArg(2)); 1732 code.emitArrayLength(); 1733 if (singleArgs != 0) 1734 { 1735 code.emitPushInt(singleArgs); 1736 code.emitSub(Type.int_type); 1737 } 1738 code.emitStore(counter); 1739 } 1740 code.emitLoad(counter); 1741 code.emitNewArray(elType); 1742 Label testLabel = new Label(code); 1743 code.emitGoto(testLabel); 1744 Label loopTopLabel = new Label(code); 1745 loopTopLabel.define(code); 1746 1747 code.emitDup(1); code.emitLoad(counter); 1749 code.emitLoad(code.getArg(2)); 1750 code.emitLoad(counter); 1751 if (singleArgs != 0) 1752 { 1753 code.emitPushInt(singleArgs); 1754 code.emitAdd(Type.int_type); 1755 } 1756 code.emitArrayLoad(Type.pointer_type); 1757 if (mustConvert) 1758 { 1759 CheckedTarget.emitCheckedCoerce 1760 (this, source, source.getName(), 1761 0, elType, null); 1762 } 1763 code.emitArrayStore(elType); 1764 testLabel.define(code); 1765 code.emitInc(counter, (short) (-1)); 1766 code.emitLoad(counter); 1767 code.emitGotoIfIntGeZero(loopTopLabel); 1768 code.popScope(); 1769 } 1770 } 1771 else if ("gnu.lists.LList".equals 1772 (lastArgType.getName())) 1773 { 1774 code.emitLoad(code.getArg(2)); code.emitPushInt(singleArgs); 1776 code.emitInvokeStatic(Compilation.makeListMethod); 1777 } 1778 else if (lastArgType == typeCallContext) 1779 code.emitLoad(code.getArg(2)); 1780 else 1781 throw new RuntimeException ("unsupported #!rest type:"+lastArgType); 1782 } 1783 code.emitInvoke(primMethod); 1784 while (--pendingIfEnds >= 0) 1785 code.emitFi(); 1786 if (defaultCallConvention < Compilation.CALL_WITH_CONSUMER) 1787 Target.pushObject.compileFromStack(this, 1788 source.getReturnType()); 1789 code.emitReturn(); 1790 } 1791 if (needThisApply) 1792 { 1793 aswitch.addDefault(code); 1794 if (defaultCallConvention >= Compilation.CALL_WITH_CONSUMER) 1795 { 1796 Method errMethod 1797 = typeModuleMethod.getDeclaredMethod("applyError", 0); 1798 code.emitInvokeStatic(errMethod); 1799 } 1800 else 1801 { 1802 int nargs = i > 4 ? 2 : i + 1; 1803 nargs++; 1804 for (int k = 0; k < nargs; k++) 1805 code.emitLoad(code.getArg(k)); 1806 code.emitInvokeSpecial(typeModuleBody.getDeclaredMethod(mname, applyArgs)); 1807 } 1808 code.emitReturn(); 1809 aswitch.finish(code); 1810 } 1811 } 1812 method = save_method; 1813 curClass = save_class; 1814 } 1815 1816 private Method startClassInit () 1817 { 1818 method = curClass.addMethod ("<clinit>", apply0args, Type.void_type, 1819 Access.PUBLIC|Access.STATIC); 1820 1821 CodeAttr code = method.startCode(); 1822 1823 if (generateMain || generateApplet || generateServlet) 1824 { 1825 ClassType languageType 1826 = (ClassType) Type.make(getLanguage().getClass()); 1827 Method registerMethod 1828 = languageType.getDeclaredMethod("registerEnvironment", 0); 1829 if (registerMethod != null) 1830 code.emitInvokeStatic(registerMethod); 1831 } 1832 return method; 1833 } 1834 1835 1840 public void process (int wantedState) 1841 { 1842 Compilation saveCompilation = Compilation.getCurrent(); 1843 try 1844 { 1845 Compilation.setCurrent(this); 1846 ModuleExp mexp = getModule(); 1847 if (wantedState >= BODY_PARSED && getState() < BODY_PARSED-1) 1848 { 1849 setState(BODY_PARSED-1); 1850 language.parse(this, 0); 1851 lexer.close(); 1852 lexer = null; 1853 setState(messages.seenErrors() ? ERROR_SEEN : BODY_PARSED); 1854 if (pendingImports != null) 1855 return; 1856 } 1857 if (wantedState >= RESOLVED && getState() < RESOLVED) 1858 { 1859 addMainClass(mexp); 1860 language.resolve(this); 1861 setState(messages.seenErrors() ? ERROR_SEEN : RESOLVED); 1862 } 1863 if (wantedState >= WALKED && getState() < WALKED) 1864 { 1865 walkModule(mexp); 1866 setState(messages.seenErrors() ? ERROR_SEEN : WALKED); 1867 } 1868 if (wantedState >= COMPILE_SETUP && getState() < COMPILE_SETUP) 1869 { 1870 litTable = new LitTable(this); 1871 mexp.setCanRead(true); 1872 FindCapturedVars.findCapturedVars(mexp, this); 1873 mexp.allocFields(this); 1874 mexp.allocChildMethods(this); 1875 setState(messages.seenErrors() ? ERROR_SEEN : COMPILE_SETUP); 1876 } 1877 if (wantedState >= COMPILED && getState() < COMPILED) 1878 { 1879 generateBytecode(); 1880 setState(messages.seenErrors() ? ERROR_SEEN : COMPILED); 1881 } 1882 if (wantedState >= CLASS_WRITTEN && getState() < CLASS_WRITTEN) 1883 { 1884 ModuleManager manager = ModuleManager.getInstance(); 1885 outputClass(manager.getCompilationDirectory()); 1886 setState(CLASS_WRITTEN); 1887 } 1888 } 1889 catch (gnu.text.SyntaxException ex) 1890 { 1891 setState(ERROR_SEEN); 1892 if (ex.getMessages() != getMessages()) 1893 throw new RuntimeException ("confussing syntax error: "+ex); 1894 } 1896 catch (java.io.IOException ex) 1897 { 1898 ex.printStackTrace(); 1899 error('f', "caught "+ex); 1900 setState(ERROR_SEEN); 1901 } 1902 finally 1903 { 1904 Compilation.setCurrent(saveCompilation); 1905 } 1906 } 1907 1908 1911 void generateBytecode () 1912 { 1913 ModuleExp module = getModule(); 1914 if (debugPrintFinalExpr) 1915 { 1916 OutPort dout = OutPort.errDefault(); 1917 dout.println ("[Compiling final "+module.getName() 1918 + " to " + mainClass.getName() + ":"); 1919 module.print(dout); 1920 dout.println(']'); 1921 dout.flush(); 1922 } 1923 1924 ClassType neededSuper = getModuleType(); 1925 if (mainClass.getSuperclass().isSubtype(neededSuper)) 1926 moduleClass = mainClass; 1927 else 1928 { 1929 moduleClass = new ClassType(generateClassName("frame")); 1930 moduleClass.setSuper(neededSuper); 1931 addClass(moduleClass); 1932 generateConstructor(moduleClass, module); 1933 } 1934 1935 curClass = module.type; 1936 int arg_count; 1937 LambdaExp saveLambda = curLambda; 1938 curLambda = module; 1939 Type[] arg_types; 1940 if (module.isHandlingTailCalls()) 1941 { 1942 arg_count = 1; 1943 arg_types = new Type[1]; 1944 arg_types[0] = typeCallContext; 1945 } 1946 else if (module.min_args != module.max_args || module.min_args > 4 1947 || (fewerClasses && curClass == mainClass)) 1948 { 1949 arg_count = 1; 1950 arg_types = new Type[1]; 1951 arg_types[0] = new ArrayType (typeObject); 1952 } 1953 else 1954 { 1955 arg_count = module.min_args; 1956 arg_types = new Type[arg_count]; 1957 for (int i = arg_count; --i >= 0; ) 1958 arg_types[i] = typeObject; 1959 } 1960 1961 CodeAttr code; 1962 Variable heapFrame = module.heapFrame; 1963 boolean staticModule = module.isStatic(); 1964 Method apply_method; 1965 1966 apply_method = curClass.addMethod ("run", arg_types, Type.void_type, 1967 Access.PUBLIC+Access.FINAL); 1968 method = apply_method; 1969 method.initCode(); 1974 code = getCode(); 1975 1977 thisDecl = method.getStaticFlag() ? null : module.declareThis(module.type); 1978 module.closureEnv = module.thisVariable; 1979 module.heapFrame = module.isStatic() ? null : module.thisVariable; 1980 module.allocChildClasses(this); 1981 1982 if (module.isHandlingTailCalls() || usingCPStyle()) 1983 { 1984 callContextVar = new Variable ("$ctx", typeCallContext); 1985 module.getVarScope().addVariableAfter(thisDecl, callContextVar); 1986 callContextVar.setParameter(true); 1987 } 1988 1989 int line = module.getLineNumber(); 1990 if (line > 0) 1991 code.putLineNumber(module.getFileName(), line); 1992 1993 module.allocParameters(this); 1994 module.enterFunction(this); 1995 if (usingCPStyle()) 1996 { 1997 loadCallContext(); 1998 code.emitGetField(pcCallContextField); 1999 fswitch = new SwitchState(code); 2000 Label l = new Label(code); 2001 l.define(code); 2002 fswitch.addCase(0, l, code); 2003 } 2004 2005 module.compileBody(this); 2006 module.compileChildMethods(this); 2007 2008 Label startLiterals = null; 2009 Label afterLiterals = null; 2010 Method initMethod = null; 2011 2012 if (curClass == mainClass) 2013 { 2014 Method save_method = method; 2015 Variable callContextSave = callContextVar; 2016 callContextVar = null; 2017 2018 initMethod = startClassInit(); 2019 clinitMethod = initMethod; 2020 code = getCode(); 2021 2022 startLiterals = new Label(code); 2023 afterLiterals = new Label(code); 2024 code.fixupChain(afterLiterals, startLiterals); 2025 2026 if (staticModule) 2027 { 2028 generateConstructor (module); 2029 2030 code.emitNew(moduleClass); 2031 code.emitDup(moduleClass); 2032 code.emitInvokeSpecial(moduleClass.constructor); 2033 moduleInstanceMainField 2034 = moduleClass.addField("$instance", mainClass, 2035 Access.STATIC|Access.PUBLIC|Access.FINAL); 2036 code.emitPutStatic(moduleInstanceMainField); 2037 } 2038 Initializer init; 2039 while ((init = clinitChain) != null) 2040 { 2041 clinitChain = null; 2042 dumpInitializers(init); 2043 } 2044 2045 if (! immediate && module.staticInitRun()) 2046 { 2047 code.emitGetStatic(moduleInstanceMainField); 2048 code.emitInvokeInterface(typeRunnable.getDeclaredMethod("run", 0)); 2049 } 2050 code.emitReturn(); 2051 2052 if (moduleClass != mainClass 2053 && ! staticModule && ! generateMain && ! immediate) 2054 { 2055 method = curClass.addMethod("run", Access.PUBLIC, 2057 Type.typeArray0, Type.void_type); 2058 code = method.startCode(); 2059 Variable ctxVar = code.addLocal(typeCallContext); 2060 Variable saveVar = code.addLocal(typeConsumer); 2061 Variable exceptionVar = code.addLocal(Type.throwable_type); 2062 code.emitInvokeStatic(getCallContextInstanceMethod); 2064 code.emitStore(ctxVar); 2065 Field consumerFld = typeCallContext.getDeclaredField("consumer"); 2066 code.emitLoad(ctxVar); 2068 code.emitGetField(consumerFld); 2069 code.emitStore(saveVar); 2070 code.emitLoad(ctxVar); 2072 code.emitGetStatic(ClassType.make("gnu.lists.VoidConsumer") 2073 .getDeclaredField("instance")); 2074 code.emitPutField(consumerFld); 2075 code.emitTryStart(false, Type.void_type); 2077 code.emitPushThis(); 2079 code.emitLoad(ctxVar); 2080 code.emitInvokeVirtual(save_method); 2081 code.emitPushNull(); 2083 code.emitStore(exceptionVar); 2084 code.emitTryEnd(); 2086 code.emitCatchStart(exceptionVar); 2087 code.emitCatchEnd(); 2088 code.emitTryCatchEnd(); 2089 code.emitLoad(ctxVar); 2091 code.emitLoad(exceptionVar); 2092 code.emitLoad(saveVar); 2093 code.emitInvokeStatic(typeModuleBody 2094 .getDeclaredMethod("runCleanup", 3)); 2095 code.emitReturn(); 2096 } 2097 2098 method = save_method; 2099 callContextVar = callContextSave; 2100 } 2101 2102 module.compileEnd(this); 2103 2104 curLambda = saveLambda; 2105 2106 if (Compilation.fewerClasses) method.popScope(); 2109 module.heapFrame = heapFrame; if (usingCPStyle() || (fewerClasses && curClass == mainClass)) 2111 { 2112 code = getCode(); 2113 fswitch.finish(code); 2114 } 2115 2116 if (startLiterals != null || callContextVar != null) 2117 { 2118 method = initMethod; 2119 code = getCode(); 2120 2121 Label endLiterals = new Label(code); 2122 code.fixupChain(startLiterals, endLiterals); 2123 2124 if (callContextVarForInit != null) 2125 { 2126 code.emitInvokeStatic(getCallContextInstanceMethod); 2127 code.emitStore(callContextVarForInit); 2128 } 2129 2130 try 2131 { 2132 if (immediate) 2133 { 2134 code.emitPushInt(registerForImmediateLiterals(this)); 2135 code.emitInvokeStatic(ClassType.make("gnu.expr.Compilation") 2136 .getDeclaredMethod("setupLiterals", 1)); 2137 } 2138 else 2139 litTable.emit(); 2140 } 2141 catch (Throwable ex) 2142 { 2143 error('e', "Literals: Internal error:" + ex); 2144 } 2145 code.fixupChain(endLiterals, afterLiterals); 2146 } 2147 2148 if (generateMain && curClass == mainClass) 2149 { 2150 Type[] args = { new ArrayType(javaStringType) }; 2151 method = curClass.addMethod("main", Access.PUBLIC|Access.STATIC, 2152 args, Type.void_type); 2153 2154 code = method.startCode(); 2155 2156 if (Shell.defaultFormatName != null) 2157 { 2158 code.emitPushString(Shell.defaultFormatName); 2159 code.emitInvokeStatic(ClassType.make("kawa.Shell") 2160 .getDeclaredMethod("setDefaultFormat", 1)); 2161 } 2162 code.emitLoad(code.getArg(0)); 2163 code.emitInvokeStatic(typeModuleBody.getDeclaredMethod("processArgs", 1)); 2164 if (moduleInstanceMainField != null) 2165 code.emitGetStatic(moduleInstanceMainField); 2166 else 2167 { 2168 code.emitNew(curClass); 2169 code.emitDup(curClass); 2170 code.emitInvokeSpecial(curClass.constructor); 2171 } 2172 code.emitInvokeVirtual(typeModuleBody.getDeclaredMethod("runAsMain", 0)); 2173 code.emitReturn(); 2174 } 2175 2176 String uri; 2177 if (minfo != null && (uri = minfo.getNamespaceUri()) != null) 2178 { 2179 ModuleManager manager = ModuleManager.getInstance(); 2182 String mainPrefix = mainClass.getName(); 2183 int dot = mainPrefix.lastIndexOf('.'); 2184 if (dot < 0) 2185 { 2186 mainPrefix = ""; 2187 } 2188 else 2189 { 2190 String mainPackage = mainPrefix.substring(0, dot); 2191 try 2192 { 2193 manager.loadPackageInfo(mainPackage); 2194 } 2195 catch (ClassNotFoundException ex) 2196 { 2197 } 2199 catch (Throwable ex) 2200 { 2201 error('e', "error loading map for "+mainPackage+" - "+ex); 2202 } 2203 mainPrefix = mainPrefix.substring(0, dot+1); 2204 } 2205 ClassType mapClass = new ClassType(mainPrefix + ModuleSet.MODULES_MAP); 2206 ClassType typeModuleSet = ClassType.make("gnu.expr.ModuleSet"); 2207 mapClass.setSuper(typeModuleSet); 2208 registerClass(mapClass); 2209 2210 method = mapClass.addMethod("<init>", Access.PUBLIC, 2211 apply0args, Type.void_type); 2212 Method superConstructor 2213 = typeModuleSet.addMethod("<init>", Access.PUBLIC, 2214 apply0args, Type.void_type); 2215 code = method.startCode(); 2216 code.emitPushThis(); 2217 code.emitInvokeSpecial(superConstructor); 2218 code.emitReturn(); 2219 2220 ClassType typeModuleManager = ClassType.make("gnu.expr.ModuleManager"); 2221 Type[] margs = { typeModuleManager }; 2222 method = mapClass.addMethod("register", margs, Type.void_type, 2223 Access.PUBLIC); 2224 code = method.startCode(); 2225 Method reg = typeModuleManager.getDeclaredMethod("register", 3); 2226 2227 for (ModuleInfo mi = manager.firstModule(); 2228 mi != null; mi = mi.nextModule()) 2229 { 2230 String miClassName = mi.className; 2231 if (miClassName == null 2232 || ! miClassName.startsWith(mainPrefix)) 2233 continue; 2234 String moduleSource = mi.sourcePath; 2235 String moduleUri = mi.getNamespaceUri(); 2236 code.emitLoad(code.getArg(1)); 2237 compileConstant(miClassName); 2238 if (! URI_utils.isAbsolute(moduleSource)) 2239 try 2240 { 2241 char sep = File.separatorChar; 2245 String path = manager.getCompilationDirectory(); 2246 path = path + mainPrefix.replace('.', sep); 2247 path = URI_utils.toURL(path).toString(); 2248 int plen = path.length(); 2249 if (plen > 0 && path.charAt(plen-1) != sep) 2250 path = path + sep; 2251 moduleSource = URI_utils.relativize(mi.sourceAbsPath, path).toString(); 2252 } 2253 catch (Throwable ex) 2254 { 2255 throw new WrappedException("exception while fixing up '" 2256 +moduleSource+'\'', 2257 ex); 2258 } 2259 compileConstant(moduleSource); 2260 compileConstant(moduleUri); 2261 code.emitInvokeVirtual(reg); 2262 } 2263 code.emitReturn(); 2264 } 2265 } 2266 2267 int localFieldIndex; 2268 public Field allocLocalField (Type type, String name) 2269 { 2270 if (name == null) 2271 name = "tmp_"+(++localFieldIndex); 2272 Field field = curClass.addField(name, type, 0); 2273 return field; 2274 } 2275 2276 2277 Variable callContextVar; 2278 Variable callContextVarForInit; 2279 2280 2281 public final void loadCallContext() 2282 { 2283 CodeAttr code = getCode(); 2284 if (callContextVar != null && ! callContextVar.dead()) 2285 code.emitLoad(callContextVar); 2286 else if (method == clinitMethod) 2293 { 2294 callContextVar = new Variable("$ctx", typeCallContext); 2296 callContextVar.reserveLocal(code.getMaxLocals(), code); 2299 code.emitLoad(callContextVar); 2300 callContextVarForInit = callContextVar; 2301 } 2302 else 2303 { 2304 code.emitInvokeStatic(getCallContextInstanceMethod); 2305 code.emitDup(); 2306 callContextVar = new Variable("$ctx", typeCallContext); 2307 code.getCurrentScope().addVariable(code, callContextVar); 2308 code.emitStore(callContextVar); 2309 } 2310 } 2311 2312 public void freeLocalField (Field field) 2313 { 2314 } 2316 2317 2319 public Expression parse (Object input) 2320 { 2321 throw new Error ("unimeplemented parse"); 2322 } 2323 2324 protected Language language; 2325 public Language getLanguage() { return language; } 2326 2327 public LambdaExp currentLambda () { return current_scope.currentLambda (); } 2328 2329 public final ModuleExp getModule() { return mainLambda; } 2330 public void setModule(ModuleExp mexp) { mainLambda = mexp; } 2331 2332 public boolean isStatic() { return mainLambda.isStatic(); } 2333 2334 2335 public ModuleExp currentModule() { return current_scope.currentModule(); } 2336 2337 2341 public void mustCompileHere () 2342 { 2343 mustCompile = true; 2344 } 2345 2346 public ScopeExp currentScope() { return current_scope; } 2347 2348 2351 public void setCurrentScope (ScopeExp scope) 2352 { 2353 int scope_nesting = ScopeExp.nesting(scope); 2354 int current_nesting = ScopeExp.nesting(current_scope); 2355 while (current_nesting > scope_nesting) 2356 { 2357 pop(current_scope); 2358 current_nesting--; 2359 } 2360 ScopeExp sc = scope; 2361 while (scope_nesting > current_nesting) 2362 { 2363 sc = sc.outer; 2364 scope_nesting--; 2365 } 2366 while (sc != current_scope) 2367 { 2368 pop(current_scope); 2369 sc = sc.outer; 2370 } 2371 pushChain(scope, sc); 2372 } 2373 2374 void pushChain (ScopeExp scope, ScopeExp limit) 2375 { 2376 if (scope != limit) 2377 { 2378 pushChain(scope.outer, limit); 2379 pushScope(scope); 2380 lexical.push(scope); 2381 } 2382 } 2383 2384 public ModuleExp pushNewModule (Lexer lexer) 2385 { 2386 this.lexer = lexer; 2387 return pushNewModule(lexer.getName()); 2388 } 2389 2390 public ModuleExp pushNewModule (String filename) 2391 { 2392 ModuleExp module = new ModuleExp(); 2393 if (filename != null) 2394 module.setFile(filename); 2395 if (Compilation.generateAppletDefault) 2396 module.setFlag(ModuleExp.SUPERTYPE_SPECIFIED); 2397 if (immediate) 2398 { 2399 module.setFlag(ModuleExp.IMMEDIATE); 2400 new ModuleInfo().setCompilation(this); 2401 } 2402 mainLambda = module; 2403 push(module); 2404 return module; 2405 } 2406 2407 public void push (ScopeExp scope) 2408 { 2409 pushScope(scope); 2410 lexical.push(scope); 2411 } 2412 2413 public final void pushScope (ScopeExp scope) 2414 { 2415 if (! mustCompile 2416 && (scope.mustCompile() 2419 || (scope instanceof LambdaExp && ! (scope instanceof ModuleExp)))) 2420 mustCompileHere(); 2421 scope.outer = current_scope; 2422 current_scope = scope; 2423 } 2424 2425 public void pop (ScopeExp scope) 2426 { 2427 lexical.pop(scope); 2428 current_scope = scope.outer; 2429 } 2430 2431 public final void pop () 2432 { 2433 pop(current_scope); 2434 } 2435 2436 public void push (Declaration decl) 2437 { 2438 lexical.push(decl); 2439 } 2440 2441 public Declaration lookup(Object name, int namespace) 2442 { 2443 return lexical.lookup(name, namespace); 2444 } 2445 2446 2452 public void usedClass (Type type) 2453 { 2454 while (type instanceof ArrayType) 2455 type = ((ArrayType) type).getComponentType(); 2456 if (! immediate || ! (type instanceof ClassType)) 2457 return; 2458 ClassType clas = (ClassType) type; 2459 if (loader != null && clas.isExisting()) 2460 { 2461 loader.addClass(clas.getReflectClass()); 2462 } 2463 } 2464 2465 public SourceMessages getMessages() { return messages; } 2466 public void setMessages (SourceMessages messages) 2467 { this.messages = messages; } 2468 2469 public void error(char severity, String message, SourceLocator location) 2470 { 2471 String file = location.getFileName(); 2472 int line = location.getLineNumber(); 2473 int column = location.getColumnNumber(); 2474 if (file == null || line <= 0) 2475 { 2476 file = getFileName(); 2477 line = getLineNumber(); 2478 column = getColumnNumber(); 2479 } 2480 2481 if (severity == 'w' && getBooleanOption("warn-as-error", false)) 2482 severity = 'e'; 2483 messages.error(severity, file, line, column, message); 2484 } 2485 2486 public void error(char severity, String message) 2487 { 2488 if (severity == 'w' && getBooleanOption("warn-as-error", false)) 2489 severity = 'e'; 2490 2491 messages.error(severity, this, message); 2492 } 2493 2494 public void error(char severity, Declaration decl, String msg1, String msg2) 2495 { 2496 error(severity, msg1 + decl.getName() + msg2, null, decl); 2497 } 2498 2499 public void error(char severity, String message, 2500 String code, Declaration decl) 2501 { 2502 if (severity == 'w' && getBooleanOption("warn-as-error", false)) 2503 severity = 'e'; 2504 2505 String filename = getFileName(); 2506 int line = getLineNumber(); 2507 int column = getColumnNumber(); 2508 int decl_line = decl.getLineNumber(); 2509 if (decl_line > 0) 2510 { 2511 filename = decl.getFileName(); 2512 line = decl_line; 2513 column = decl.getColumnNumber(); 2514 } 2515 messages.error(severity, filename, line, column, message, code); 2516 } 2517 2518 2523 public Expression syntaxError (String message) 2524 { 2525 error('e', message); 2526 return new ErrorExp (message); 2527 } 2528 2529 public final int getLineNumber() { return messages.getLineNumber(); } 2530 public final int getColumnNumber() { return messages.getColumnNumber(); } 2531 public final String getFileName() { return messages.getFileName(); } 2532 public String getPublicId() { return messages.getPublicId(); } 2533 public String getSystemId() { return messages.getSystemId(); } 2534 public boolean isStableSourceLocation() { return false; } 2535 2536 public void setFile(String filename) { messages.setFile(filename); } 2537 public void setLine(int line) { messages.setLine(line); } 2538 public void setColumn(int column) { messages.setColumn(column); } 2539 public final void setLine(Expression position) 2540 { messages.setLocation(position); } 2541 public final void setLocation (SourceLocator position) 2542 { messages.setLocation(position); } 2543 2544 public void setLine(String filename, int line, int column) 2545 { 2546 messages.setLine(filename, line, column); 2547 } 2548 2549 2550 public Stack exprStack; 2551 2552 public void letStart () 2553 { 2554 pushScope(new LetExp(null)); 2555 } 2556 2557 public Declaration letVariable (Object name, Type type, Expression init) 2558 { 2559 LetExp let = (LetExp) current_scope; 2560 Declaration decl = let.addDeclaration(name, type); 2561 decl.noteValue(init); 2562 return decl; 2563 } 2564 2565 public void letEnter () 2566 { 2567 LetExp let = (LetExp) current_scope; 2568 int ndecls = let.countDecls(); 2569 Expression[] inits = new Expression[ndecls]; 2570 int i = 0; 2571 for (Declaration decl = let.firstDecl(); 2572 decl != null; 2573 decl = decl.nextDecl()) 2574 inits[i++] = decl.getValue(); 2575 let.inits = inits; 2576 lexical.push(let); 2577 } 2578 2579 public LetExp letDone (Expression body) 2580 { 2581 LetExp let = (LetExp) current_scope; 2582 let.body = body; 2583 pop(let); 2584 return let; 2585 } 2586 2587 private void checkLoop() 2588 { 2589 if (((LambdaExp) current_scope).getName() != "%do%loop") 2590 throw new Error ("internal error - bad loop state"); 2591 } 2592 2593 2595 public void loopStart() 2596 { 2597 LambdaExp loopLambda = new LambdaExp(); 2598 Expression[] inits = { loopLambda }; 2599 LetExp let = new LetExp(inits); 2600 String fname = "%do%loop"; 2601 Declaration fdecl = let.addDeclaration(fname); 2602 fdecl.noteValue(loopLambda); 2603 loopLambda.setName(fname); 2604 let.outer = current_scope; 2605 loopLambda.outer = let; 2606 current_scope = loopLambda; 2607 } 2608 2609 public Declaration loopVariable(Object name, Type type, Expression init) 2610 { 2611 checkLoop(); 2612 LambdaExp loopLambda = (LambdaExp) current_scope; 2613 Declaration decl = loopLambda.addDeclaration(name, type); 2614 if (exprStack == null) 2615 exprStack = new Stack (); 2616 exprStack.push(init); 2617 loopLambda.min_args++; 2618 return decl; 2619 } 2620 2621 2623 public void loopEnter () 2624 { 2625 checkLoop(); 2626 LambdaExp loopLambda = (LambdaExp) current_scope; 2627 int ninits = loopLambda.min_args; 2628 loopLambda.max_args = ninits; 2629 Expression[] inits = new Expression[ninits]; 2630 for (int i = ninits; --i >= 0; ) 2631 inits[i] = (Expression) exprStack.pop(); 2632 LetExp let = (LetExp) loopLambda.outer; 2633 Declaration fdecl = let.firstDecl(); let.setBody(new ApplyExp(new ReferenceExp(fdecl), inits)); 2635 lexical.push(loopLambda); 2636 } 2637 public void loopCond(Expression cond) 2638 { 2639 checkLoop(); 2640 exprStack.push(cond); 2641 } 2642 public void loopBody(Expression body) 2643 { 2644 LambdaExp loopLambda = (LambdaExp) current_scope; 2645 loopLambda.body = body; 2646 } 2647 public Expression loopRepeat(Expression[] exps) 2648 { 2649 LambdaExp loopLambda = (LambdaExp) current_scope; 2650 ScopeExp let = loopLambda.outer; 2651 Declaration fdecl = let.firstDecl(); Expression cond = (Expression) exprStack.pop(); 2653 Expression recurse = new ApplyExp(new ReferenceExp(fdecl), exps); 2654 loopLambda.body = new IfExp(cond, 2655 new BeginExp(loopLambda.body, recurse), 2656 QuoteExp.voidExp); 2657 lexical.pop(loopLambda); 2658 current_scope = let.outer; 2659 return let; 2660 } 2661 2662 public Expression loopRepeat () 2663 { 2664 return loopRepeat(Expression.noExpressions); 2665 } 2666 2667 public Expression loopRepeat (Expression exp) 2668 { 2669 Expression[] args = { exp }; 2670 return loopRepeat(args); 2671 } 2672 2673 2674 Method forNameHelper; 2675 2676 public void loadClassRef (ClassType clas) 2677 { 2678 if (clas == mainClass && mainLambda.isStatic() 2680 && moduleInstanceMainField != null) 2682 { 2683 CodeAttr code = getCode(); 2684 code.emitGetStatic(moduleInstanceMainField); 2685 code.emitInvokeVirtual(Type.pointer_type.getDeclaredMethod("getClass", 0)); 2686 } 2687 else 2688 loadClassRef(clas.getName()); 2689 } 2690 2691 2693 public void loadClassRef (String className) 2694 { 2695 CodeAttr code = getCode(); 2696 if (curClass.getClassfileMajorVersion() >= 49) code.emitPushClass(className); 2698 else 2699 { 2700 code.emitPushString(className); 2701 code.emitInvokeStatic(getForNameHelper()); 2702 } 2703 } 2704 2705 2715 public Method getForNameHelper () 2716 { 2717 if (forNameHelper == null) 2718 { 2719 2720 Method save_method = method; 2721 method = curClass.addMethod("class$", Access.PUBLIC|Access.STATIC, 2722 string1Arg, typeClass); 2723 forNameHelper = method; 2724 CodeAttr code = method.startCode(); 2725 code.emitLoad(code.getArg(0)); 2726 code.emitPushInt(0); 2727 code.emitPushString(mainClass.getName()); 2728 code.emitInvokeStatic(typeClass.getDeclaredMethod("forName", 1)); 2729 code.emitInvokeVirtual(typeClass.getDeclaredMethod("getClassLoader", 0)); 2730 code.emitInvokeStatic(typeClass.getDeclaredMethod("forName", 3)); 2731 code.emitReturn(); 2732 method = save_method; 2733 2734 2736 } 2737 return forNameHelper; 2738 } 2739 2740 public Object resolve(Object name, boolean function) 2741 { 2742 Environment env = Environment.getCurrent(); 2743 Symbol symbol; 2744 if (name instanceof String ) 2745 symbol = env.defaultNamespace().lookup((String ) name); 2746 else 2747 symbol = (Symbol) name; 2748 if (symbol == null) 2749 return null; 2750 if (function && getLanguage().hasSeparateFunctionNamespace()) 2751 return env.getFunction(symbol, null); 2752 return env.get(symbol, null); 2753 } 2754 2755 2756 private int keyUninitialized; 2757 2758 private static Compilation chainUninitialized; 2759 2760 private Compilation nextUninitialized; 2761 2762 2773 public static void setupLiterals (int key) 2774 { 2775 Compilation comp = Compilation.findForImmediateLiterals(key); 2776 try 2777 { 2778 Class clas = comp.loader.loadClass(comp.mainClass.getName(), true); 2779 2780 2781 for (Literal init = comp.litTable.literalsChain; init != null; 2782 init = init.next) 2783 { 2784 2790 clas.getDeclaredField(init.field.getName()) 2791 .set(null, init.value); 2792 } 2793 } 2794 catch (Throwable ex) 2795 { 2796 throw new WrappedException("internal error", ex); 2797 } 2798 } 2799 2800 public static synchronized int 2801 registerForImmediateLiterals (Compilation comp) 2802 { 2803 int i = 0; 2804 for (Compilation c = chainUninitialized; c != null; c = c.nextUninitialized) 2805 { 2806 if (i <= c.keyUninitialized) 2807 i = c.keyUninitialized + 1; 2808 } 2809 comp.keyUninitialized = i; 2810 comp.nextUninitialized = chainUninitialized; 2811 chainUninitialized = comp; 2812 return i; 2813 } 2814 2815 public static synchronized Compilation findForImmediateLiterals (int key) 2816 { 2817 Compilation prev = null; 2818 for (Compilation comp = chainUninitialized; ; ) 2819 { 2820 Compilation next = comp.nextUninitialized; 2821 if (comp.keyUninitialized == key) 2822 { 2823 if (prev == null) 2824 chainUninitialized = next; 2825 else 2826 prev.nextUninitialized = next; 2827 return comp; 2828 } 2829 prev = comp; 2830 comp = next; 2831 } 2832 } 2833 2834 2835 public NameLookup lexical; 2836 2837 protected ScopeExp current_scope; 2838 2839 protected SourceMessages messages; 2840 2841 private static final ThreadLocation current = 2842 new ThreadLocation("current-compilation"); 2843 2844 public static Compilation getCurrent () 2845 { 2846 return (Compilation) current.get(); 2847 } 2848 2849 public static void setCurrent (Compilation comp) 2850 { 2851 current.set(comp); 2852 } 2853 2854 public String toString () 2855 { 2856 return "<compilation "+mainLambda+">"; 2857 } 2858} 2859 | Popular Tags |