| 1 4 package gnu.expr; 5 import gnu.bytecode.*; 6 import gnu.mapping.*; 7 import gnu.lists.LList; 8 import java.util.Vector ; 9 10 14 15 public class LambdaExp extends ScopeExp 16 { 17 public Expression body; 18 20 public int min_args; 21 22 public int max_args; 23 24 25 Vector applyMethods; 26 27 Variable argsArray; 29 private Declaration firstArgsArrayArg; 31 32 public Keyword[] keywords; 33 public Expression[] defaultArgs; 34 35 37 Declaration capturedVars; 38 39 public void capture (Declaration decl) 40 { 41 if (decl.isSimple()) 42 { 43 if (capturedVars == null 44 && ! decl.isStatic() 45 && ! (this instanceof ModuleExp || this instanceof ClassExp)) 46 { 47 heapFrame = new gnu.bytecode.Variable("heapFrame"); 48 } 49 decl.setSimple(false); 50 if (! decl.isPublic()) 51 { 52 decl.nextCapturedVar = capturedVars; 53 capturedVars = decl; 54 } 55 } 56 } 57 58 67 Variable heapFrame; 68 69 public LambdaExp firstChild; 70 public LambdaExp nextSibling; 71 72 73 final static ApplyExp unknownContinuation = new ApplyExp ((Expression) null, null); 74 75 83 public ApplyExp returnContinuation; 84 85 86 ReferenceExp[] throwsSpecification; 87 88 public void setExceptions(ReferenceExp[] exceptions) 89 { 90 throwsSpecification = exceptions; 91 } 92 93 94 public Declaration nameDecl; 95 96 100 public Field closureEnvField; 101 102 105 public Field staticLinkField; 106 107 115 Variable closureEnv; 116 117 static final int INLINE_ONLY = 1; 118 static final int CAN_READ = 2; 119 static final int CAN_CALL = 4; 120 static final int IMPORTS_LEX_VARS = 8; 121 static final int NEEDS_STATIC_LINK = 16; 122 123 static final int CANNOT_INLINE = 32; 124 static final int CLASS_METHOD = 64; 125 static final int METHODS_COMPILED = 128; 126 public static final int NO_FIELD = 256; 127 128 static final int DEFAULT_CAPTURES_ARG = 512; 129 public static final int SEQUENCE_RESULT = 1024; 130 public static final int OVERLOADABLE_FIELD = 2048; 131 protected static final int NEXT_AVAIL_FLAG = 4096; 132 133 134 public final boolean getInlineOnly() { return (flags & INLINE_ONLY) != 0; } 135 public final void setInlineOnly(boolean inlineOnly) 136 { setFlag(inlineOnly, INLINE_ONLY); } 137 138 public final boolean getNeedsClosureEnv () 139 { return (flags & (NEEDS_STATIC_LINK|IMPORTS_LEX_VARS)) != 0; } 140 141 143 public final boolean getNeedsStaticLink () 144 { return (flags & NEEDS_STATIC_LINK) != 0; } 145 146 public final void setNeedsStaticLink(boolean needsStaticLink) 147 { 148 if (needsStaticLink) flags |= NEEDS_STATIC_LINK; 149 else flags &= ~NEEDS_STATIC_LINK; 150 } 151 152 153 public final boolean getImportsLexVars () 154 { return (flags & IMPORTS_LEX_VARS) != 0; } 155 156 public final void setImportsLexVars(boolean importsLexVars) 157 { 158 if (importsLexVars) flags |= IMPORTS_LEX_VARS; 159 else flags &= ~IMPORTS_LEX_VARS; 160 } 161 162 public final void setImportsLexVars() 163 { 164 int old = flags; 165 flags |= IMPORTS_LEX_VARS; 166 167 if ((old & IMPORTS_LEX_VARS) == 0 && nameDecl != null) 169 setCallersNeedStaticLink(); 170 } 171 172 public final void setNeedsStaticLink() 173 { 174 int old = flags; 175 flags |= NEEDS_STATIC_LINK; 176 177 if ((old & NEEDS_STATIC_LINK) == 0 && nameDecl != null) 179 setCallersNeedStaticLink(); 180 } 181 182 void setCallersNeedStaticLink() 183 { 184 LambdaExp outer = outerLambda(); 185 for (ApplyExp app = nameDecl.firstCall; app != null; app = app.nextCall) 186 { 187 LambdaExp caller = app.context; 188 for (; caller != outer && !(caller instanceof ModuleExp); caller = caller.outerLambda()) 189 caller.setNeedsStaticLink(); 190 } 191 } 192 193 public final boolean getCanRead() 194 { return (flags & CAN_READ) != 0; } 195 public final void setCanRead(boolean read) 196 { 197 if (read) flags |= CAN_READ; 198 else flags &= ~CAN_READ; 199 } 200 201 public final boolean getCanCall() 202 { return (flags & CAN_CALL) != 0; } 203 public final void setCanCall(boolean called) 204 { 205 if (called) flags |= CAN_CALL; 206 else flags &= ~CAN_CALL; 207 } 208 209 210 public final boolean isClassMethod() 211 { return (flags & CLASS_METHOD) != 0; } 212 213 public final void setClassMethod(boolean isMethod) 214 { 215 if (isMethod) flags |= CLASS_METHOD; 216 else flags &= ~CLASS_METHOD; 217 } 218 219 220 public final boolean isModuleBody () { return this instanceof ModuleExp; } 221 222 223 public final boolean isClassGenerated () 224 { 225 return isModuleBody() || this instanceof ClassExp; 226 } 227 228 230 public int getCallConvention () 231 { 232 if (isModuleBody()) 233 return ((Compilation.defaultCallConvention 234 >= Compilation.CALL_WITH_CONSUMER) 235 ? Compilation.defaultCallConvention 236 : Compilation.CALL_WITH_CONSUMER); 237 if (isClassMethod()) 238 return Compilation.CALL_WITH_RETURN; 239 return ((Compilation.defaultCallConvention 240 != Compilation.CALL_WITH_UNSPECIFIED) 241 ? Compilation.defaultCallConvention 242 : Compilation.CALL_WITH_RETURN); 243 } 244 245 public final boolean isHandlingTailCalls () 246 { 247 return isModuleBody() 248 || (Compilation.defaultCallConvention >= Compilation.CALL_WITH_TAILCALLS 249 && ! isClassMethod()); 250 } 251 252 public final boolean variable_args () { return max_args < 0; } 253 254 ClassType type = Compilation.typeProcedure; 255 256 257 protected ClassType getCompiledClassType(Compilation comp) 258 { 259 if (type == Compilation.typeProcedure) 260 throw new Error ("internal error: getCompiledClassType"); 261 return type; 262 } 263 264 public Type getType() 265 { 266 return type; 267 } 268 269 public void setType (ClassType type) 270 { 271 this.type = type; 272 } 273 274 277 public int incomingArgs () 278 { 279 return min_args == max_args && max_args <= 4 && max_args > 0 ? max_args : 1; 282 } 283 284 285 int selectorValue; 286 287 int getSelectorValue(Compilation comp) 288 { 289 int s = selectorValue; 290 if (s == 0) 291 { 292 s = comp.maxSelectorValue; 293 comp.maxSelectorValue = s + primMethods.length; 294 selectorValue = ++s; 295 } 296 return s; 297 } 298 299 304 Method[] primMethods; 305 306 307 public final Method getMethod(int argCount) 308 { 309 if (primMethods == null || (max_args >= 0 && argCount > max_args)) 310 return null; 311 int index = argCount - min_args; 312 if (index < 0) 313 return null; int length = primMethods.length; 315 return primMethods[index < length ? index : length - 1]; 316 } 317 318 320 public final Method getMainMethod() 321 { 322 Method[] methods = primMethods; 323 return methods == null ? null : methods[methods.length-1]; 324 } 325 326 327 public final Type restArgType() 328 { 329 if (min_args == max_args) 330 return null; 331 if (primMethods == null) 332 throw new Error ("internal error - restArgType"); 333 Method[] methods = primMethods; 334 if (max_args >= 0 && methods.length > max_args - min_args) 335 return null; 336 Method method = methods[methods.length-1]; 337 Type[] types = method.getParameterTypes(); 338 int ilast = types.length-1; 339 if (method.getName().endsWith("$X")) 340 ilast--; 341 return types[ilast]; 342 } 343 344 public LambdaExp outerLambda () 345 { 346 return outer == null ? null : outer.currentLambda (); 347 } 348 349 350 351 public LambdaExp outerLambdaNotInline () 352 { 353 for (ScopeExp exp = this; (exp = exp.outer) != null; ) 354 { 355 if (exp instanceof LambdaExp) 356 { 357 LambdaExp result = (LambdaExp) exp; 358 if (! result.getInlineOnly()) 359 return result; 360 } 361 } 362 return null; 363 } 364 365 369 boolean inlinedIn (LambdaExp outer) 370 { 371 if (! getInlineOnly()) 372 return false; 373 for (ScopeExp exp = getCaller(); exp != null; exp = exp.outer) 374 { 375 if (exp instanceof LambdaExp) 376 { 377 378 LambdaExp result = (LambdaExp) exp; 379 if (result == outer) 380 return true; 381 if (! result.getInlineOnly()) 382 return false; 383 } 384 } 385 return false; 386 } 387 388 389 public LambdaExp getCaller () 390 { 391 return returnContinuation.context; 392 } 393 394 Variable thisVariable; 395 396 public Variable declareThis(ClassType clas) 397 { 398 if (thisVariable == null) 399 { 400 thisVariable = new Variable("this"); 401 getVarScope().addVariableAfter(null, thisVariable); 402 thisVariable.setParameter (true); 403 } 404 if (thisVariable.getType() == null) 405 thisVariable.setType(clas); 406 if (decls != null && decls.isThisParameter()) 407 decls.var = thisVariable; 408 return thisVariable; 409 } 410 411 public Variable declareClosureEnv() 412 { 413 if (closureEnv == null && getNeedsClosureEnv()) 414 { 415 LambdaExp parent = outerLambda(); 416 if (parent instanceof ClassExp) 417 parent = parent.outerLambda(); 418 Variable parentFrame = parent.heapFrame != null ? parent.heapFrame 419 : parent.closureEnv; 420 if (isClassMethod()) 421 closureEnv = declareThis(type); 422 else if (parent.heapFrame == null && ! parent.getNeedsStaticLink() 423 && ! (parent instanceof ModuleExp)) 424 closureEnv = null; 425 else if (! isClassGenerated() && ! getInlineOnly()) 426 { 427 Method primMethod = getMainMethod(); 428 if (! primMethod.getStaticFlag()) 429 closureEnv = declareThis(primMethod.getDeclaringClass()); 430 else 431 { 432 Type envType = primMethod.getParameterTypes()[0]; 433 closureEnv = new Variable("closureEnv", envType); 434 getVarScope().addVariableAfter(null, closureEnv); 435 closureEnv.setParameter(true); 436 } 437 } 438 else if (inlinedIn(parent)) 439 closureEnv = parentFrame; 440 else 441 { 442 closureEnv = new Variable("closureEnv", parentFrame.getType()); 443 getVarScope().addVariable(closureEnv); 444 } 445 } 446 return closureEnv; 447 } 448 449 public LambdaExp () 450 { 451 } 452 453 public LambdaExp(int args) 454 { 455 min_args = args; 456 max_args = args; 457 } 458 459 460 public LambdaExp (Expression body) 461 { 462 this.body = body; 463 } 464 465 466 public void loadHeapFrame (Compilation comp) 467 { 468 LambdaExp curLambda = comp.curLambda; 469 while (curLambda != this && curLambda.getInlineOnly()) 470 curLambda = curLambda.getCaller(); 471 472 gnu.bytecode.CodeAttr code = comp.getCode(); 473 if (curLambda.heapFrame != null && this == curLambda) 474 { 475 code.emitLoad(curLambda.heapFrame); 476 return; 477 } 478 ClassType curType; 479 if (curLambda.closureEnv != null) 480 { 481 code.emitLoad(curLambda.closureEnv); 482 curType = (ClassType) curLambda.closureEnv.getType(); 483 } 484 else 485 { 486 code.emitPushThis(); 487 curType = comp.curClass; 488 } 489 while (curLambda != this) 490 { 491 Field link = curLambda.staticLinkField; 492 if (link != null && link.getDeclaringClass() == curType) 493 { 494 code.emitGetField(link); 495 curType = (ClassType) link.getType(); 496 } 497 curLambda = curLambda.outerLambda(); 498 } 499 } 500 501 502 Declaration getArg (int i) 503 { 504 for (Declaration var = firstDecl(); ; var = var.nextDecl ()) 505 { 506 if (var == null) 507 throw new Error ("internal error - getArg"); 508 if (i == 0) 509 return var; 510 --i; 511 } 512 } 513 514 public void compileEnd (Compilation comp) 515 { 516 gnu.bytecode.CodeAttr code = comp.getCode(); 517 if (! getInlineOnly()) 518 { 519 if (comp.method.reachableHere() 520 && (Compilation.defaultCallConvention < Compilation.CALL_WITH_TAILCALLS 521 || isModuleBody() || isClassMethod() || isHandlingTailCalls())) 522 code.emitReturn(); 523 popScope(code); if (! Compilation.fewerClasses) code.popScope(); } 527 528 if (heapFrame != null) 529 comp.generateConstructor((ClassType) heapFrame.getType(), this); 530 531 generateApplyMethods(comp); 532 } 533 534 public void generateApplyMethods(Compilation comp) 535 { 536 comp.generateMatchMethods(this); 537 if (Compilation.defaultCallConvention >= Compilation.CALL_WITH_CONSUMER) 538 comp.generateApplyMethodsWithContext(this); 539 else 540 comp.generateApplyMethodsWithoutContext(this); 541 } 542 543 Field allocFieldFor (Compilation comp) 544 { 545 if (nameDecl != null && nameDecl.field != null) 546 return nameDecl.field; 547 ClassType frameType = getOwningLambda().getHeapFrameType(); 548 String name = getName(); 549 String fname 550 = name == null ? "lambda" : Compilation.mangleNameIfNeeded(name); 551 int fflags = Access.FINAL; 552 if (nameDecl != null && nameDecl.context instanceof ModuleExp) 553 { 554 boolean external_access = nameDecl.needsExternalAccess(); 555 if (external_access) 556 fname = Declaration.PRIVATE_PREFIX + fname; 557 if (nameDecl.getFlag(Declaration.STATIC_SPECIFIED)) 558 { 559 fflags |= Access.STATIC; 560 if (! ((ModuleExp) nameDecl.context).isStatic()) 564 fflags &= ~Access.FINAL; 565 } 566 if (! nameDecl.isPrivate() || external_access) 567 fflags |= Access.PUBLIC; 568 if ((flags & OVERLOADABLE_FIELD) != 0) 569 { 570 String fname0 = fname; 571 int suffix = min_args == max_args ? min_args : 1; 572 do { fname = fname0 + '$' + suffix++; } 573 while (frameType.getDeclaredField(fname) != null); 574 } 575 } 576 else 577 { 578 fname = fname + "$Fn" + ++comp.localFieldIndex; 579 if (! getNeedsClosureEnv()) 580 fflags = (fflags | Access.STATIC) & ~Access.FINAL; 581 } 582 Type rtype = Compilation.typeModuleMethod; 583 Field field = frameType.addField (fname, rtype, fflags); 584 if (nameDecl != null) 585 nameDecl.field = field; 586 return field; 587 } 588 589 final void addApplyMethod (Compilation comp) 590 { 591 LambdaExp owner = this; 592 for (;;) 595 { 596 owner = owner.outerLambda(); 597 if (owner instanceof ModuleExp 598 || owner.heapFrame != null) 599 break; 600 } 601 ClassType frameType = owner.getHeapFrameType(); 602 if (! (frameType.getSuperclass().isSubtype(Compilation.typeModuleBody))) 603 owner = comp.getModule(); 604 if (owner.applyMethods == null) 605 owner.applyMethods = new Vector (); 606 owner.applyMethods.addElement(this); 607 } 608 609 public Field compileSetField (Compilation comp) 610 { 611 if (comp.usingCPStyle()) 612 compile(comp, Type.pointer_type); 613 else 614 { 615 compileAsMethod(comp); 616 addApplyMethod(comp); 617 } 618 619 return (new ProcInitializer(this, comp)).field; 620 } 621 622 public void compile (Compilation comp, Target target) 623 { 624 if (target instanceof IgnoreTarget 625 && (getInlineOnly() || ! getCanRead())) 626 return; 627 Type rtype; 628 CodeAttr code = comp.getCode(); 629 630 if (comp.usingCPStyle()) 631 { 632 Label func_end = new Label(code); 634 LambdaExp saveLambda = comp.curLambda; 635 comp.curLambda = this; 636 type = saveLambda.type; 637 closureEnv = saveLambda.closureEnv; 638 647 gnu.bytecode.SwitchState fswitch = comp.fswitch; 648 int pc = comp.fswitch.getMaxValue() + 1; 649 code.emitGoto(func_end); 650 Type[] stackTypes = code.saveStackTypeState(true); 651 652 fswitch.addCase(pc, code); 653 658 allocParameters(comp); 659 enterFunction(comp); 660 661 compileBody(comp); 662 compileEnd(comp); 663 comp.curLambda = saveLambda; 664 func_end.define(code); 665 code.restoreStackTypeState(stackTypes); 666 ClassType ctype = comp.curClass; 667 rtype = ctype; 668 694 } 695 else 696 { LambdaExp outer = outerLambda(); 697 rtype = Compilation.typeModuleMethod; 698 if ((flags & NO_FIELD) != 0 699 || (comp.immediate && outer instanceof ModuleExp)) 700 { 701 compileAsMethod(comp); 702 addApplyMethod(comp); 703 ProcInitializer.emitLoadModuleMethod(this, comp); 704 } 705 else 706 { 707 Field field = compileSetField(comp); 708 if (field.getStaticFlag()) 709 code.emitGetStatic(field); 710 else 711 { 712 LambdaExp parent = comp.curLambda; 713 Variable frame 714 = parent.heapFrame != null ? parent.heapFrame 715 : parent.closureEnv; 716 code.emitLoad(frame); 717 code.emitGetField(field); 718 } 719 } 720 } 721 target.compileFromStack(comp, rtype); 722 } 723 724 public ClassType getHeapFrameType() 725 { 726 if (this instanceof ModuleExp || this instanceof ClassExp) 727 return (ClassType) getType(); 728 else 729 return (ClassType) heapFrame.getType(); 730 } 731 732 733 public LambdaExp getOwningLambda() 734 { 735 ScopeExp exp = outer; 736 for (;; exp = exp.outer) 737 { 738 if (exp == null) 739 return null; 740 if (exp instanceof ModuleExp 741 || (exp instanceof ClassExp && getNeedsClosureEnv()) 742 || (exp instanceof LambdaExp 743 && ((LambdaExp) exp).heapFrame != null)) 744 return (LambdaExp) exp; 745 } 746 } 747 748 void addMethodFor (Compilation comp, ObjectType closureEnvType) 749 { 750 ScopeExp sc = this; 751 while (sc != null && ! (sc instanceof ClassExp)) 752 sc = sc.outer; 753 ClassType ctype; 754 if (sc != null) 757 ctype = ((ClassExp) sc).instanceType; 758 else 759 ctype = getOwningLambda().getHeapFrameType(); 760 addMethodFor(ctype, comp, closureEnvType); 761 } 762 763 void addMethodFor (ClassType ctype, Compilation comp, ObjectType closureEnvType) 764 { 765 String name = getName(); 767 LambdaExp outer = outerLambda(); 768 769 int key_args = keywords == null ? 0 : keywords.length; 770 int opt_args = defaultArgs == null ? 0 : defaultArgs.length - key_args; 771 int numStubs = 772 ((flags & DEFAULT_CAPTURES_ARG) != 0) ? 0 : opt_args; 773 boolean varArgs = max_args < 0 || min_args + numStubs < max_args; 774 primMethods = new Method[numStubs + 1]; 775 776 boolean isStatic; 777 char isInitMethod = '\0'; 779 if (nameDecl != null 780 && nameDecl.getFlag(Declaration.NONSTATIC_SPECIFIED)) 781 isStatic = false; 782 else if (nameDecl != null 783 && nameDecl.getFlag(Declaration.STATIC_SPECIFIED)) 784 isStatic = true; 785 else if (isClassMethod()) 786 { 787 if (outer instanceof ClassExp) 788 { 789 ClassExp cl = (ClassExp) outer; 790 isStatic = cl.isMakingClassPair() && closureEnvType != null; 791 if (this == cl.initMethod) 792 isInitMethod = 'I'; 793 else if (this == cl.clinitMethod) 794 { 795 isInitMethod = 'C'; 796 isStatic = true; 797 } 798 } 799 else 800 isStatic = false; 801 } 802 else if (thisVariable != null || closureEnvType == ctype) 803 isStatic = false; 804 else if (nameDecl != null && nameDecl.context instanceof ModuleExp) 805 { 806 ModuleExp mexp = (ModuleExp) nameDecl.context; 807 isStatic = mexp.getSuperType() == null && mexp.getInterfaces() == null; 808 } 809 else 810 isStatic = true; 811 812 StringBuffer nameBuf = new StringBuffer (60); 813 int mflags = isStatic ? Access.STATIC : 0; 814 if (nameDecl != null) 815 { 816 if (nameDecl.needsExternalAccess()) 817 mflags |= Access.PUBLIC; 818 else 819 { 820 short defaultFlag = nameDecl.isPrivate() ? 0 : Access.PUBLIC; 821 if (isClassMethod()) 822 defaultFlag = nameDecl.getAccessFlags(defaultFlag); 823 mflags |= defaultFlag; 824 } 825 } 826 if (! (outer.isModuleBody() || outer instanceof ClassExp) 827 || name == null) 828 { 829 nameBuf.append("lambda"); 830 nameBuf.append(+(++comp.method_counter)); 831 } 832 if (isInitMethod == 'C') 833 nameBuf.append("<clinit>"); 834 else if (getSymbol() != null) 835 nameBuf.append(Compilation.mangleName(name)); 836 if (getFlag(SEQUENCE_RESULT)) 837 nameBuf.append("$C"); 838 boolean withContext 839 = (getCallConvention() >= Compilation.CALL_WITH_CONSUMER 840 && isInitMethod == '\0'); 841 if (isInitMethod != '\0') 842 { 843 if (isStatic) 844 { mflags = (mflags & ~Access.PROTECTED+Access.PRIVATE)+Access.PUBLIC; 848 } 849 else 850 { mflags = (mflags & ~Access.PUBLIC+Access.PROTECTED)+Access.PRIVATE; 854 } 855 } 856 if (ctype.isInterface()) 857 mflags |= Access.ABSTRACT; 858 if (! isStatic) 859 declareThis(ctype); 860 861 Type rtype 862 = (getFlag(SEQUENCE_RESULT) 863 || getCallConvention () >= Compilation.CALL_WITH_CONSUMER) 864 ? Type.void_type 865 : getReturnType().getImplementationType(); 866 int extraArg = (closureEnvType != null && closureEnvType != ctype) ? 1 : 0; 867 868 int ctxArg = 0; 869 if (getCallConvention () >= Compilation.CALL_WITH_CONSUMER 870 && isInitMethod == '\0') 871 ctxArg = 1; 872 873 int nameBaseLength = nameBuf.length(); 874 for (int i = 0; i <= numStubs; i++) 875 { 876 nameBuf.setLength(nameBaseLength); 877 int plainArgs = min_args + i; 878 int numArgs = plainArgs; 879 if (i == numStubs && varArgs) 880 numArgs++; 881 Type[] atypes = new Type[extraArg + numArgs + ctxArg]; 882 if (extraArg > 0) 883 atypes[0] = closureEnvType; 884 Declaration var = firstDecl(); 885 if (var != null && var.isThisParameter()) 886 var = var.nextDecl(); 887 for (int itype = 0; itype < plainArgs; var = var.nextDecl()) 888 atypes[extraArg + itype++] = var.getType().getImplementationType(); 889 if (ctxArg != 0) 890 atypes[atypes.length-1] = Compilation.typeCallContext; 891 if (plainArgs < numArgs) 892 { 893 nameBuf.append("$V"); 894 name = nameBuf.toString(); 895 Type lastType = var.getType(); 896 String lastTypeName = lastType.getName(); 897 if (key_args > 0 || numStubs < opt_args 898 || ! ("gnu.lists.LList".equals(lastTypeName) 899 || "java.lang.Object[]".equals(lastTypeName))) 900 { 901 lastType = Compilation.objArrayType; 902 argsArray = new Variable("argsArray", 903 Compilation.objArrayType); 904 argsArray.setParameter(true); 905 } 906 firstArgsArrayArg = var; 907 atypes[atypes.length-(withContext ? 2 : 1)] = lastType; 908 } 909 if (withContext) 910 nameBuf.append("$X"); 911 912 boolean classSpecified 913 = (outer instanceof ClassExp 914 || (outer instanceof ModuleExp 915 && (((ModuleExp) outer) 916 .getFlag(ModuleExp.SUPERTYPE_SPECIFIED)))); 917 name = nameBuf.toString(); 918 { 919 int renameCount = 0; 925 int len = nameBuf.length(); 926 retry: 927 for (;;) 928 { 929 for (ClassType t = ctype; t != null; t = t.getSuperclass ()) 930 { 931 if (t.getDeclaredMethod(name, atypes) != null) 932 { 933 nameBuf.setLength(len); 934 nameBuf.append('$'); 935 nameBuf.append(++renameCount); 936 name = nameBuf.toString(); 937 continue retry; 938 } 939 if (classSpecified) 940 break; 942 } 943 break; 944 } 945 } 946 Method method = ctype.addMethod(name, atypes, rtype, mflags); 947 primMethods[i] = method; 948 949 if (throwsSpecification != null && throwsSpecification.length > 0) 950 { 951 int n = throwsSpecification.length; 952 ClassType[] exceptions = new ClassType[n]; 953 for (int j = 0; j < n; j++) 954 { 955 ClassType exception = null; 956 Declaration decl = throwsSpecification[j].getBinding(); 957 if (decl != null) 958 { 959 Expression declValue = decl.getValue(); 960 if (declValue instanceof ClassExp) 961 exception 962 = ((ClassExp) declValue).getCompiledClassType(comp); 963 else 964 comp.error('e', "throws specification "+decl.getName() 965 + " has non-class lexical binding"); 966 } 967 if (exception == null) 968 { 969 String exName = throwsSpecification[j].getName(); 970 int nlen = exName.length(); 971 if (nlen > 2 972 && exName.charAt(0) == '<' 973 && exName.charAt(nlen-1) == '>') 974 exName = exName.substring(1, nlen-1); 975 exception = ClassType.make(exName); 976 } 977 exceptions[j] = exception; 978 } 979 ExceptionsAttr attr = new ExceptionsAttr(method); 980 attr.setExceptions(exceptions); 981 } 982 } 983 } 984 985 public void allocChildClasses (Compilation comp) 987 { 988 Method main = getMainMethod(); 989 990 Declaration decl = firstDecl(); 991 for (;;) 992 { 993 if (decl == firstArgsArrayArg && argsArray != null) 994 { 995 getVarScope().addVariable(argsArray); 996 } 997 if (! getInlineOnly() 998 && getCallConvention() >= Compilation.CALL_WITH_CONSUMER 999 && (firstArgsArrayArg == null ? decl == null 1000 : argsArray != null ? decl == firstArgsArrayArg 1001 : decl == firstArgsArrayArg.nextDecl())) 1002 { 1003 Variable var = 1004 getVarScope().addVariable(null, 1005 Compilation.typeCallContext, 1006 "$ctx"); 1007 var.setParameter(true); 1008 } 1009 if (decl == null) 1010 break; 1011 Variable var = decl.var; 1012 if (var != null 1014 || (getInlineOnly() && decl.ignorable())) 1015 ; 1016 else if (decl.isSimple () && ! decl.isIndirectBinding()) 1017 { 1018 var = decl.allocateVariable(null); 1021 } 1023 else 1024 { 1025 String vname 1031 = Compilation.mangleName(decl.getName()).intern(); 1032 Type vtype = decl.getType().getImplementationType(); 1033 var = decl.var = getVarScope().addVariable(null, vtype, vname); 1034 var.setParameter (true); 1036 } 1038 decl = decl.nextDecl(); 1039 } 1040 1041 declareClosureEnv(); 1042 1043 allocFrame(comp); 1044 1045 allocChildMethods(comp); 1046 } 1047 1048 void allocChildMethods (Compilation comp) 1049 { 1050 for (LambdaExp child = firstChild; child != null; 1051 child = child.nextSibling) 1052 { 1053 if (! child.isClassGenerated() && ! child.getInlineOnly()) 1054 { 1055 ObjectType closureEnvType; 1056 if (! child.getNeedsClosureEnv()) 1057 closureEnvType = null; 1058 else if (this instanceof ClassExp || this instanceof ModuleExp) 1059 closureEnvType = getCompiledClassType(comp); 1060 else 1061 { 1062 LambdaExp owner = this; 1063 while (owner.heapFrame == null) 1064 owner = owner.outerLambda(); 1065 closureEnvType = (ClassType) owner.heapFrame.getType(); 1066 } 1067 child.addMethodFor(comp, closureEnvType); 1068 } 1069 } 1070 } 1071 1072 public void allocFrame (Compilation comp) 1073 { 1074 if (heapFrame != null) 1075 { 1076 ClassType frameType; 1077 if (this instanceof ModuleExp || this instanceof ClassExp) 1078 frameType = getCompiledClassType(comp); 1079 else 1080 { 1081 frameType = new ClassType(comp.generateClassName("frame")); 1082 frameType.setSuper(comp.getModuleType()); 1083 comp.addClass(frameType); 1084 } 1085 heapFrame.setType(frameType); 1086 } 1087 } 1088 1089 void allocParameters (Compilation comp) 1090 { 1091 CodeAttr code = comp.getCode(); 1092 1093 int i = 0; 1094 int j = 0; 1095 1096 code.locals.enterScope(getVarScope()); 1097 int line = getLineNumber(); 1098 if (line > 0) 1099 code.putLineNumber(getFileName(), line); 1100 1101 for (Declaration decl = firstDecl(); decl != null; ) 1102 { 1103 if (argsArray != null && min_args == max_args 1109 && primMethods == null 1110 && getCallConvention() < Compilation.CALL_WITH_CONSUMER) 1111 { 1112 code.emitLoad(argsArray); 1113 code.emitPushInt(j); 1114 code.emitArrayLoad(Type.pointer_type); 1115 decl.getType().emitCoerceFromObject(code); 1116 code.emitStore(decl.getVariable()); 1117 } 1118 j++; 1119 i++; 1120 decl = decl.nextDecl(); 1121 } 1122 if (heapFrame != null) 1123 heapFrame.allocateLocal(code); 1124 } 1125 1126 static Method searchForKeywordMethod3; 1127 static Method searchForKeywordMethod4; 1128 1129 1130 Initializer initChain; 1131 1132 void enterFunction (Compilation comp) 1133 { 1134 CodeAttr code = comp.getCode(); 1135 1136 getVarScope().setStartPC(code); 1138 1139 if (closureEnv != null && ! closureEnv.isParameter() 1140 && ! comp.usingCPStyle()) 1141 { 1142 if (! getInlineOnly()) 1143 { 1144 code.emitPushThis(); 1145 Field field = closureEnvField; 1146 if (field == null) 1147 field = outerLambda().closureEnvField; 1148 code.emitGetField(field); 1149 code.emitStore(closureEnv); 1150 } 1151 else if (! inlinedIn(outerLambda())) 1152 { 1153 outerLambda().loadHeapFrame(comp); 1154 code.emitStore(closureEnv); 1155 } 1156 } 1157 if (! comp.usingCPStyle()) 1158 { 1159 ClassType frameType = heapFrame == null 1160 ? currentModule().getCompiledClassType(comp) 1161 : (ClassType) heapFrame.getType(); 1162 for (Declaration decl = capturedVars; decl != null; 1163 decl = decl.nextCapturedVar) 1164 { 1165 if (decl.field != null) 1166 continue; 1167 decl.makeField(frameType, comp, null); 1168 } 1169 } 1170 if (heapFrame != null && ! comp.usingCPStyle()) 1171 { 1172 ClassType frameType = (ClassType) heapFrame.getType(); 1173 if (closureEnv != null && ! (this instanceof ModuleExp)) 1174 staticLinkField = frameType.addField("staticLink", 1175 closureEnv.getType()); 1176 if (! (this instanceof ModuleExp) && ! (this instanceof ClassExp)) 1177 { 1178 code.emitNew(frameType); 1179 code.emitDup(frameType); 1180 Method constructor = Compilation.getConstructor(frameType, this); 1181 code.emitInvokeSpecial(constructor); 1182 1183 if (staticLinkField != null) 1184 { 1185 code.emitDup(heapFrame.getType()); 1186 code.emitLoad(closureEnv); 1187 code.emitPutField(staticLinkField); 1188 } 1189 code.emitStore(heapFrame); 1190 } 1191 } 1192 1193 Variable argsArray = this.argsArray; 1194 if (min_args == max_args && ! Compilation.fewerClasses 1195 && primMethods == null 1196 && getCallConvention () < Compilation.CALL_WITH_CONSUMER) 1197 argsArray = null; 1198 1199 int i = 0; 1203 int opt_i = 0; 1204 int key_i = 0; 1205 int key_args = keywords == null ? 0 : keywords.length; 1206 int opt_args = defaultArgs == null ? 0 1207 : defaultArgs.length - key_args; 1208 if (this instanceof ModuleExp) 1209 return; 1210 int plainArgs = -1; 1212 int defaultStart = 0; 1213 Method mainMethod = getMainMethod(); 1214 Variable callContextSave = comp.callContextVar; 1215 1216 for (Declaration param = firstDecl(); param != null; param = param.nextDecl()) 1217 { 1218 comp.callContextVar 1219 = (getCallConvention() < Compilation.CALL_WITH_CONSUMER ? null 1220 : getVarScope().lookup("$ctx")); 1221 if (param == firstArgsArrayArg && argsArray != null) 1222 { 1223 if (primMethods != null) 1224 { 1225 plainArgs = i; 1226 defaultStart = plainArgs - min_args; 1227 } 1228 else 1229 { 1230 plainArgs = 0; 1231 defaultStart = 0; 1232 } 1233 } 1234 if (plainArgs >= 0 || ! param.isSimple() 1235 || param.isIndirectBinding()) 1236 { 1237 Type paramType = param.getType(); 1238 Type stackType 1239 = (mainMethod == null || plainArgs >= 0 ? Type.pointer_type 1240 : paramType); 1241 if (!param.isSimple ()) 1247 param.loadOwningObject(null, comp); 1248 if (plainArgs < 0) 1250 { 1251 code.emitLoad(param.getVariable()); 1253 } 1254 else if (i < min_args) 1255 { code.emitLoad(argsArray); 1257 code.emitPushInt(i); 1258 code.emitArrayLoad(Type.pointer_type); 1259 } 1260 else if (i < min_args + opt_args) 1261 { code.emitPushInt(i - plainArgs); 1263 code.emitLoad(argsArray); 1264 code.emitArrayLength(); 1265 code.emitIfIntLt(); 1266 code.emitLoad(argsArray); 1267 code.emitPushInt(i - plainArgs); 1268 code.emitArrayLoad(Type.pointer_type); 1269 code.emitElse(); 1270 defaultArgs[defaultStart + opt_i++].compile(comp, paramType); 1271 code.emitFi(); 1272 } 1273 else if (max_args < 0 && i == min_args + opt_args) 1274 { 1275 code.emitLoad(argsArray); 1278 code.emitPushInt(i - plainArgs); 1279 code.emitInvokeStatic(Compilation.makeListMethod); 1280 stackType = Compilation.scmListType; 1281 } 1282 else 1283 { code.emitLoad(argsArray); 1285 code.emitPushInt(min_args + opt_args - plainArgs); 1286 comp.compileConstant(keywords[key_i++]); 1287 Expression defaultArg = defaultArgs[defaultStart + opt_i++]; 1288 if (defaultArg instanceof QuoteExp) 1292 { 1293 if (searchForKeywordMethod4 == null) 1294 { 1295 Type[] argts = new Type[4]; 1296 argts[0] = Compilation.objArrayType; 1297 argts[1] = Type.int_type; 1298 argts[2] = Type.pointer_type; 1299 argts[3] = Type.pointer_type; 1300 searchForKeywordMethod4 1301 = Compilation.scmKeywordType.addMethod 1302 ("searchForKeyword", argts, 1303 Type.pointer_type, Access.PUBLIC|Access.STATIC); 1304 } 1305 defaultArg.compile(comp, paramType); 1306 code.emitInvokeStatic(searchForKeywordMethod4); 1307 } 1308 else 1309 { 1310 if (searchForKeywordMethod3 == null) 1311 { 1312 Type[] argts = new Type[3]; 1313 argts[0] = Compilation.objArrayType; 1314 argts[1] = Type.int_type; 1315 argts[2] = Type.pointer_type; 1316 searchForKeywordMethod3 1317 = Compilation.scmKeywordType.addMethod 1318 ("searchForKeyword", argts, 1319 Type.pointer_type, Access.PUBLIC|Access.STATIC); 1320 } 1321 code.emitInvokeStatic(searchForKeywordMethod3); 1322 code.emitDup(1); 1323 comp.compileConstant(Special.dfault); 1324 code.emitIfEq(); 1325 code.emitPop(1); 1326 defaultArg.compile(comp, paramType); 1327 code.emitFi(); 1328 } 1329 } 1330 if (paramType != stackType) 1333 CheckedTarget.emitCheckedCoerce(comp, this, i+1, paramType); 1334 if (param.isIndirectBinding()) 1335 param.pushIndirectBinding(comp); 1336 if (param.isSimple()) 1337 code.emitStore(param.getVariable()); 1338 else 1339 code.emitPutField(param.field); 1340 } 1341 i++; 1342 } 1343 comp.callContextVar = callContextSave; 1344 } 1345 1346 void compileChildMethods (Compilation comp) 1347 { 1348 for (LambdaExp child = firstChild; child != null; ) 1349 { 1350 if (! child.getCanRead() && ! child.getInlineOnly()) 1351 { 1352 child.compileAsMethod(comp); 1353 } 1354 child = child.nextSibling; 1355 } 1356 } 1357 1358 void compileAsMethod (Compilation comp) 1359 { 1360 if ((flags & METHODS_COMPILED) != 0) 1361 return; 1362 flags |= METHODS_COMPILED; 1363 Method save_method = comp.method; 1364 LambdaExp save_lambda = comp.curLambda; 1365 comp.curLambda = this; 1366 1367 Method method = primMethods[0]; 1368 boolean isStatic = method.getStaticFlag(); 1369 int numStubs = primMethods.length - 1; 1370 Type restArgType = restArgType(); 1371 1372 int[] saveDeclFlags = null; 1373 if (numStubs > 0) 1374 { 1375 saveDeclFlags = new int[min_args + numStubs]; 1376 int k = 0; 1377 for (Declaration decl = firstDecl(); 1378 k < min_args + numStubs; decl = decl.nextDecl()) 1379 saveDeclFlags[k++] = decl.flags; 1380 } 1381 1382 boolean ctxArg = getCallConvention () >= Compilation.CALL_WITH_CONSUMER; 1383 1384 for (int i = 0; i <= numStubs; i++) 1385 { 1386 comp.method = primMethods[i]; 1387 if (i < numStubs) 1388 { 1389 CodeAttr code = comp.method.startCode(); 1390 int toCall = i + 1; 1391 while (toCall < numStubs 1392 && defaultArgs[toCall] instanceof QuoteExp) 1393 toCall++; 1394 boolean varArgs = toCall == numStubs && restArgType != null; 1395 Declaration decl; 1396 Variable callContextSave = comp.callContextVar; 1397 Variable var = code.getArg(0); 1398 if (! isStatic) 1399 { 1400 code.emitPushThis(); 1401 if (getNeedsClosureEnv()) 1402 closureEnv = var; 1403 var = code.getArg(1); 1404 } 1405 decl = firstDecl(); 1406 for (int j = 0; j < min_args + i; j++, decl = decl.nextDecl()) 1407 { 1408 decl.flags |= Declaration.IS_SIMPLE; 1409 decl.var = var; 1410 code.emitLoad(var); 1411 var = var.nextVar(); 1412 } 1413 comp.callContextVar = ctxArg ? var : null; 1414 for (int j = i; j < toCall; j++, decl = decl.nextDecl()) 1415 { 1416 Target paramTarget = StackTarget.getInstance(decl.getType()); 1417 defaultArgs[j].compile(comp, paramTarget); 1418 } 1419 if (varArgs) 1420 { 1421 Expression arg; 1422 String lastTypeName = restArgType.getName(); 1423 if ("gnu.lists.LList".equals(lastTypeName)) 1424 arg = new QuoteExp(gnu.lists.LList.Empty); 1425 else if ("java.lang.Object[]".equals(lastTypeName)) 1426 arg = new QuoteExp(Values.noArgs); 1427 else throw new Error ("unimplemented #!rest type "+lastTypeName); 1429 arg.compile(comp, restArgType); 1430 } 1431 if (ctxArg) 1432 code.emitLoad(var); 1433 if (isStatic) 1434 code.emitInvokeStatic(primMethods[toCall]); 1435 else 1436 code.emitInvokeVirtual(primMethods[toCall]); 1437 code.emitReturn(); 1438 closureEnv = null; 1439 comp.callContextVar = callContextSave; 1440 } 1441 else 1442 { 1443 if (saveDeclFlags != null) 1444 { 1445 int k = 0; 1446 for (Declaration decl = firstDecl(); 1447 k < min_args + numStubs; decl = decl.nextDecl()) 1448 { 1449 decl.flags = saveDeclFlags[k++]; 1450 decl.var = null; 1451 } 1452 } 1453 comp.method.initCode(); 1454 allocChildClasses(comp); 1455 allocParameters(comp); 1456 enterFunction(comp); 1457 1458 compileBody(comp); 1459 compileEnd(comp); 1460 } 1461 } 1462 1463 compileChildMethods(comp); 1464 comp.method = save_method; 1465 comp.curLambda = save_lambda; 1466 } 1467 1468 public void compileBody (Compilation comp) 1469 { 1470 Target target; 1471 Variable callContextSave = comp.callContextVar; 1472 comp.callContextVar = null; 1473 if (getCallConvention() >= Compilation.CALL_WITH_CONSUMER) 1474 { 1475 Variable var = getVarScope().lookup("$ctx"); 1476 if (var != null && var.getType() == Compilation.typeCallContext) 1477 comp.callContextVar = var; 1478 target = ConsumerTarget.makeContextTarget(comp); 1479 } 1480 else 1481 target = Target.pushValue(getReturnType()); 1482 body.compileWithPosition(comp, target, 1483 body.getLineNumber() > 0 ? body : this); 1484 comp.callContextVar = callContextSave; 1485 } 1486 1487 1488 Procedure thisValue; 1489 1490 protected Expression walk (ExpWalker walker) 1491 { 1492 return walker.walkLambdaExp(this); 1493 } 1494 1495 protected void walkChildren(ExpWalker walker) 1496 { 1497 walkChildrenOnly(walker); 1498 walkProperties(walker); 1499 } 1500 1501 protected final void walkChildrenOnly(ExpWalker walker) 1502 { 1503 LambdaExp save = walker.currentLambda; 1504 walker.currentLambda = this; 1505 try 1506 { 1507 walker.walkDefaultArgs(this); 1508 if (walker.exitValue == null && body != null) 1509 body = walker.walk(body); 1510 } 1511 finally 1512 { 1513 walker.currentLambda = save; 1514 } 1515 } 1516 1517 protected final void walkProperties(ExpWalker walker) 1518 { 1519 if (properties != null) 1520 { 1521 int len = properties.length; 1522 for (int i = 1; i < len; i += 2) 1523 { 1524 Object val = properties[i]; 1525 if (val instanceof Expression) 1526 { 1527 properties[i] = walker.walk((Expression) properties[i]); 1528 } 1529 } 1530 } 1531 } 1532 1533 protected boolean mustCompile () 1534 { 1535 if (keywords != null && keywords.length > 0) 1536 return true; 1537 if (defaultArgs != null) 1538 { 1539 for (int i = defaultArgs.length; --i >= 0; ) 1540 { 1541 Expression def = defaultArgs[i]; 1542 if (def != null && ! (def instanceof QuoteExp)) 1544 return true; 1545 } 1546 } 1547 return false; 1548 } 1549 1550 public void apply (CallContext ctx) throws Throwable  1551 { 1552 setIndexes(); 1557 ctx.writeValue(new Closure(this, ctx)); 1558 } 1559 1560 public Expression inline (ApplyExp exp, InlineCalls walker, Declaration decl) 1561 { 1562 int args_length = exp.args.length; 1563 String msg = WrongArguments.checkArgCount(getName(), 1564 min_args, max_args, args_length); 1565 if (msg != null) 1566 return walker.noteError(msg); 1567 int conv = getCallConvention(); 1568 Compilation comp = walker.getCompilation(); 1569 Method method; 1570 if (comp.inlineOk(this) && isClassMethod() 1571 && (conv <= Compilation.CALL_WITH_CONSUMER 1572 || (conv == Compilation.CALL_WITH_TAILCALLS)) 1573 && (method = getMethod(args_length)) != null) 1574 { 1575 PrimProcedure mproc = new PrimProcedure(method, this); 1581 Expression[] margs; 1582 if (mproc.getStaticFlag()) 1583 margs = exp.args; 1584 else 1585 { 1586 LambdaExp curLambda = walker.getCurrentLambda(); 1587 for (;;) 1588 { 1589 if (curLambda == null) 1590 return walker.noteError("internal error: missing "+this); 1591 if (curLambda.outer == outer) break; 1593 curLambda = curLambda.outerLambda(); 1594 } 1595 Declaration d = curLambda.firstDecl(); 1596 if (d==null || ! d.isThisParameter()) 1597 return walker.noteError("calling non-static method " 1598 +getName()+" from static method " 1599 +curLambda.getName()); 1600 int nargs = exp.getArgCount(); 1601 margs = new Expression[1 + nargs]; 1602 System.arraycopy(exp.getArgs(), 0, margs, 1, nargs); 1603 margs[0] = new ThisExp(d); 1604 } 1605 ApplyExp nexp = new ApplyExp(mproc, margs); 1606 return nexp.setLine(exp); 1607 } 1608 return exp; 1609 } 1610 1611 public void print (OutPort out) 1612 { 1613 out.startLogicalBlock("(Lambda/", ")", 2); 1614 Object sym = getSymbol(); 1615 if (sym != null) 1616 { 1617 out.print(sym); 1618 out.print('/'); 1619 } 1620 out.print(id); 1621 out.print('/'); 1622 out.print("fl:"); out.print(Integer.toHexString(flags)); 1623 out.writeSpaceFill(); 1624 printLineColumn(out); 1625 out.startLogicalBlock("(", false, ")"); 1626 Special prevMode = null; 1627 int i = 0; 1628 int opt_i = 0; 1629 int key_args = keywords == null ? 0 : keywords.length; 1630 int opt_args = defaultArgs == null ? 0 : defaultArgs.length - key_args; 1631 Declaration decl = firstDecl(); 1632 if (decl != null && decl.isThisParameter()) 1633 i = -1; 1634 for (; decl != null; decl = decl.nextDecl()) 1635 { 1636 Special mode; 1637 if (i < min_args) 1638 mode = null; 1639 else if (i < min_args + opt_args) 1640 mode = Special.optional; 1641 else if (max_args < 0 && i == min_args + opt_args) 1642 mode = Special.rest; 1643 else 1644 mode = Special.key; 1645 if (decl != firstDecl()) 1646 out.writeSpaceFill(); 1647 if (mode != prevMode) 1648 { 1649 out.print(mode); 1650 out.writeSpaceFill(); 1651 } 1652 Expression defaultArg = null; 1653 if (mode == Special.optional || mode == Special.key) 1654 defaultArg = defaultArgs[opt_i++]; 1655 if (defaultArg != null) 1656 out.print('('); 1657 decl.printInfo(out); 1658 if (defaultArg != null && defaultArg != QuoteExp.falseExp) 1659 { 1660 out.print(' '); 1661 defaultArg.print(out); 1662 out.print(')'); 1663 } 1664 i++; 1665 prevMode = mode; 1666 } 1667 out.endLogicalBlock(")"); 1668 out.writeSpaceLinear(); 1669 if (body == null) 1670 out.print("<null body>"); 1671 else 1672 body.print(out); 1673 out.endLogicalBlock(")"); 1674 } 1675 1676 protected final String getExpClassName() 1677 { 1678 String cname = getClass().getName(); 1679 int index = cname.lastIndexOf('.'); 1680 if (index >= 0) 1681 cname = cname.substring(index+1); 1682 return cname; 1683 } 1684 1685 public String toString() 1686 { 1687 String str = getExpClassName()+':'+getSymbol()+'/'+id+'/'; 1688 1689 int l = getLineNumber(); 1690 if (l <= 0 && body != null) 1691 l = body.getLineNumber(); 1692 if (l > 0) 1693 str = str + "l:" + l; 1694 1695 return str; 1696 } 1697 1698 1700 Object [] properties; 1701 1702 public Object getProperty(Object key, Object defaultValue) 1703 { 1704 if (properties != null) 1705 { 1706 for (int i = properties.length; (i -= 2) >= 0; ) 1707 { 1708 if (properties[i] == key) 1709 return properties[i + 1]; 1710 } 1711 } 1712 return defaultValue; 1713 } 1714 1715 public synchronized void setProperty(Object key, Object value) 1716 { 1717 properties = PropertySet.setProperty(properties, key, value); 1718 } 1719 1720 1722 public Type returnType; 1723 1724 1725 public final Type getReturnType() 1726 { 1727 if (returnType == null) 1728 { 1729 returnType = Type.pointer_type; if (body != null) 1732 returnType = body.getType(); 1733 } 1734 return returnType; 1735 } 1736 1737 1738 public final void setReturnType (Type returnType) 1739 { 1740 this.returnType = returnType; 1741 } 1742} 1743 1744class Closure extends MethodProc 1745{ 1746 Object [][] evalFrames; 1747 LambdaExp lambda; 1748 1749 public int numArgs() { return lambda.min_args | (lambda.max_args << 12); } 1750 1751 public Closure (LambdaExp lexp, CallContext ctx) 1752 { 1753 this.lambda = lexp; 1754 1755 Object [][] oldFrames = ctx.evalFrames; 1756 if (oldFrames != null) 1757 { 1758 int n = oldFrames.length; 1759 while (n > 0 && oldFrames[n-1] == null) 1760 n--; 1761 1762 evalFrames = new Object [n][]; 1763 System.arraycopy(oldFrames, 0, evalFrames, 0, n); 1764 } 1765 setSymbol(lambda.getSymbol()); 1766 } 1767 1768 public int match0 (CallContext ctx) 1769 { 1770 return matchN(new Object [] { }, ctx); 1771 } 1772 1773 public int match1 (Object arg1, CallContext ctx) 1774 { 1775 return matchN(new Object [] { arg1 }, ctx); 1776 } 1777 1778 public int match2 (Object arg1, Object arg2, CallContext ctx) 1779 { 1780 return matchN(new Object [] { arg1, arg2 }, ctx); 1781 } 1782 1783 public int match3 (Object arg1, Object arg2, Object arg3, CallContext ctx) 1784 { 1785 return matchN(new Object [] { arg1, arg2, arg3 }, ctx); 1786 } 1787 1788 public int match4 (Object arg1, Object arg2, Object arg3, Object arg4, 1789 CallContext ctx) 1790 { 1791 return matchN(new Object [] { arg1, arg2, arg3, arg4 }, ctx); 1792 } 1793 1794 public int matchN (Object [] args, CallContext ctx) 1795 { 1796 int num = numArgs(); 1797 int nargs = args.length; 1798 int min = num & 0xFFF; 1799 if (nargs < min) 1800 return MethodProc.NO_MATCH_TOO_FEW_ARGS|min; 1801 int max = num >> 12; 1802 if (nargs > max && max >= 0) 1803 return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 1804 1805 Object [] evalFrame = new Object [lambda.frameSize]; 1806 int key_args = lambda.keywords == null ? 0 : lambda.keywords.length; 1807 int opt_args = lambda.defaultArgs == null ? 0 1808 : lambda.defaultArgs.length - key_args; 1809 int i = 0; 1810 int opt_i = 0; 1811 int min_args = lambda.min_args; 1812 for (Declaration decl = lambda.firstDecl(); decl != null; 1813 decl = decl.nextDecl()) 1814 { 1815 Object value; 1816 if (i < min_args) 1817 value = args[i++]; 1818 else if (i < min_args + opt_args) 1819 { 1820 if (i < nargs) 1821 value = args[i++]; 1822 else 1823 value = ((QuoteExp) lambda.defaultArgs[opt_i++]).getValue(); 1824 } 1825 else if (lambda.max_args < 0 && i == min_args + opt_args) 1826 { 1827 if (decl.type instanceof ArrayType) 1828 { 1829 int rem = nargs - i; 1830 Type elementType = ((ArrayType) decl.type).getComponentType(); 1831 if (elementType == Type.pointer_type) 1832 { 1833 Object [] rest = new Object [rem]; 1834 System.arraycopy(args, i, rest, 0, rem); 1835 value = rest; 1836 } 1837 else 1838 { 1839 Class elementClass = elementType.getReflectClass(); 1840 value 1841 = java.lang.reflect.Array.newInstance(elementClass, rem); 1842 for (int j = 0; j < rem; j++) 1843 { 1844 Object el; 1845 try 1846 { 1847 el = elementType.coerceFromObject(args[i+j]); 1848 } 1849 catch (ClassCastException ex) 1850 { 1851 return NO_MATCH_BAD_TYPE|(i+j); 1852 } 1853 java.lang.reflect.Array.set(value, j, el); 1854 } 1855 } 1856 } 1857 else 1858 value = LList.makeList(args, i); 1859 } 1860 else return MethodProc.NO_MATCH_TOO_MANY_ARGS|max; 1862 if (decl.type != null) 1863 { 1864 try 1865 { 1866 value = decl.type.coerceFromObject(value); 1867 } 1868 catch (ClassCastException ex) 1869 { 1870 return NO_MATCH_BAD_TYPE|i; 1871 } 1872 } 1873 if (decl.isIndirectBinding()) 1874 { 1875 gnu.mapping.Location loc = decl.makeIndirectLocationFor(); 1876 loc.set(value); 1877 value = loc; 1878 } 1879 evalFrame[decl.evalIndex] = value; 1880 } 1881 ctx.values = evalFrame; 1882 ctx.where = 0; 1883 ctx.next = 0; 1884 ctx.proc = this; 1885 return 0; } 1887 1888 public void apply (CallContext ctx) throws Throwable  1889 { 1890 int level = ScopeExp.nesting(lambda); 1891 Object [] evalFrame = ctx.values; 1892 Object [][] saveFrames = ctx.evalFrames; 1893 1894 int numFrames = evalFrames == null ? 0 : evalFrames.length; 1895 if (level >= numFrames) 1896 numFrames = level; 1897 numFrames += 10; 1898 Object [][] newFrames = new Object [numFrames][]; 1899 if (evalFrames != null) 1900 System.arraycopy(evalFrames, 0, newFrames, 0, evalFrames.length); 1901 newFrames[level] = evalFrame; 1902 ctx.evalFrames = newFrames; 1903 1904 try 1905 { 1906 lambda.body.apply(ctx); 1907 } 1908 finally 1909 { 1910 ctx.evalFrames = saveFrames; 1911 } 1912 } 1913 1914 public Object getProperty(Object key, Object defaultValue) 1915 { 1916 Object value = super.getProperty(key, defaultValue); 1917 if (value == null) 1918 value = lambda.getProperty(key, defaultValue); 1919 return value; 1920 } 1921} 1922 | Popular Tags |