1 package kawa.lang; 2 import gnu.mapping.*; 3 import gnu.expr.*; 4 import gnu.lists.*; 5 import gnu.bytecode.Type; 6 import gnu.kawa.functions.Convert; 7 8 12 13 public class Lambda extends Syntax 14 { 15 public Object optionalKeyword; 16 public Object restKeyword; 17 public Object keyKeyword; 18 19 public static final Keyword nameKeyword = Keyword.make("name"); 20 21 public Expression defaultDefault = QuoteExp.falseExp; 22 23 public void setKeywords(Object optional, Object rest, Object key) 24 { 25 optionalKeyword = optional; 26 restKeyword = rest; 27 keyKeyword = key; 28 } 29 30 public Expression rewriteForm (Pair form, Translator tr) 31 { 32 Expression exp = rewrite(form.cdr, tr); 33 Translator.setLine(exp, form); 34 return exp; 35 } 36 37 public Expression rewrite (Object obj, Translator tr) 38 { 39 if (! (obj instanceof Pair)) 40 return tr.syntaxError ("missing formals in lambda"); 41 int old_errors = tr.getMessages().getErrorCount(); 42 LambdaExp lexp = new LambdaExp(); 43 Pair pair = (Pair) obj; 44 Translator.setLine(lexp, pair); 45 rewrite(lexp, pair.car, pair.cdr, tr, null); 46 if (tr.getMessages().getErrorCount() > old_errors) 47 return new ErrorExp("bad lambda expression"); 48 return lexp; 49 } 50 51 57 public void rewrite(LambdaExp lexp, Object formals, Object body, 58 Translator tr, TemplateScope templateScopeRest) 59 { 60 rewriteFormals(lexp, formals, tr, templateScopeRest); 61 if (body instanceof PairWithPosition) 62 lexp.setFile(((PairWithPosition) body).getFileName()); 63 body = rewriteAttrs(lexp, body, tr); 64 rewriteBody(lexp, body, tr); 65 } 66 67 public void rewriteFormals(LambdaExp lexp, Object formals, 68 Translator tr, TemplateScope templateScopeRest) 69 { 70 if (lexp.getSymbol() == null) 71 { 72 String filename = lexp.getFileName(); 73 int line = lexp.getLineNumber(); 74 if (filename != null && line > 0) 75 lexp.setSourceLocation(filename, line); 76 } 77 78 Object bindings = formals; 79 int opt_args = -1; 80 int rest_args = -1; 81 int key_args = -1; 82 Pair pair; 83 for (; ; bindings = pair.cdr) 84 { 85 if (bindings instanceof SyntaxForm) 86 { 87 SyntaxForm sf = (SyntaxForm) bindings; 88 bindings = sf.form; 90 } 91 if (! (bindings instanceof Pair)) 92 break; 93 pair = (Pair) bindings; 94 Object pair_car = pair.car; 96 if (pair_car instanceof SyntaxForm) 97 pair_car = ((SyntaxForm) pair_car).form; 98 if (pair_car == optionalKeyword) 99 { 100 if (opt_args >= 0) 101 { 102 tr.syntaxError ("multiple "+optionalKeyword+" in parameter list"); 103 return; 104 } 105 else if (rest_args >= 0 || key_args >= 0) 106 { 107 tr.syntaxError (optionalKeyword.toString()+" after " + restKeyword + " or " + keyKeyword); 108 return; 109 } 110 opt_args = 0; 111 } 112 else if (pair_car == restKeyword) 113 { 114 if (rest_args >= 0) 115 { 116 tr.syntaxError ("multiple " + restKeyword 117 + " in parameter list"); 118 return; 119 } 120 else if (key_args >= 0) 121 { 122 tr.syntaxError (restKeyword.toString() 123 + " after " + keyKeyword); 124 return; 125 } 126 rest_args = 0; 127 } 128 else if (pair_car == keyKeyword) 129 { 130 if (key_args >= 0) 131 { 132 tr.syntaxError ("multiple " + keyKeyword 133 + " in parameter list"); 134 return; 135 } 136 key_args = 0; 137 } 138 else if (tr.matches(pair.car, "::") && pair.cdr instanceof Pair) 139 pair = (Pair) pair.cdr; 140 else if (key_args >= 0) 141 key_args++; 142 else if (rest_args >= 0) 143 rest_args++; 144 else if (opt_args >= 0) 145 opt_args++; 146 else 147 lexp.min_args++; 148 bindings = pair.cdr; 149 } 150 if (bindings instanceof String || bindings instanceof Symbol) 151 { 152 if (opt_args >= 0 || key_args >= 0 || rest_args >= 0) 153 { 154 tr.syntaxError ("dotted rest-arg after " + optionalKeyword 155 +", " + restKeyword + ", or " + keyKeyword); 156 return; 157 } 158 rest_args = 1; 159 } 160 else if (bindings != LList.Empty) 161 { 162 tr.syntaxError ("misformed formals in lambda"); 163 return; 164 } 165 if (rest_args > 1) 166 { 167 tr.syntaxError ("multiple " + restKeyword + " parameters"); 168 return; 169 } 170 if (opt_args < 0) 171 opt_args = 0; 172 if (rest_args < 0) 173 rest_args = 0; 174 if (key_args < 0) 175 key_args = 0; 176 if (rest_args > 0) 177 lexp.max_args = -1; 178 else lexp.max_args = lexp.min_args + opt_args + 2 * key_args; 180 if (opt_args + key_args > 0) 181 lexp.defaultArgs = new Expression[opt_args + key_args]; 182 if (key_args > 0) 183 lexp.keywords = new Keyword[key_args]; 184 185 bindings = formals; 186 opt_args = 0; 187 key_args = 0; 188 Object mode = null; 189 for (; ; bindings = pair.cdr) 190 { 191 if (bindings instanceof SyntaxForm) 192 { 193 SyntaxForm sf = (SyntaxForm) bindings; 194 bindings = sf.form; 195 templateScopeRest = sf.scope; 198 } 199 TemplateScope templateScope = templateScopeRest; 200 if (! (bindings instanceof Pair)) 201 break; 202 pair = (Pair) bindings; 203 Object pair_car = pair.car; 204 if (pair_car instanceof SyntaxForm) 205 { 206 SyntaxForm sf = (SyntaxForm) pair_car; 207 pair_car = sf.form; 208 templateScope = sf.scope; 209 } 210 if (pair_car == optionalKeyword 211 || pair_car == restKeyword || pair_car == keyKeyword) 212 { 213 mode = pair_car; 214 continue; 215 } 216 Object savePos = tr.pushPositionOf(pair); 217 Object name = null; 218 Object defaultValue = defaultDefault; 219 Pair typeSpecPair = null; 220 Pair p; 221 if (tr.matches(pair_car, "::")) 222 { 223 tr.syntaxError("'::' must follow parameter name"); 224 return; 225 } 226 if (pair_car instanceof String || pair_car instanceof Symbol) 227 { 228 name = pair_car; 229 if (pair.cdr instanceof Pair 230 && tr.matches((p = (Pair) pair.cdr).car, "::")) 231 { 232 if (! (pair.cdr instanceof Pair)) 233 { 234 tr.syntaxError("'::' not followed by a type specifier" 235 + " (for parameter '" + name + "')"); 236 return; 237 } 238 p = (Pair) p.cdr; 239 typeSpecPair = p; 240 pair = p; 241 } 242 } 243 else if (pair_car instanceof Pair) 244 { 245 p = (Pair) pair_car; 246 pair_car = p.car; 247 if (pair_car instanceof SyntaxForm) 248 { 249 SyntaxForm sf = (SyntaxForm) pair_car; 250 pair_car = sf.form; 251 templateScope = sf.scope; 252 } 253 if ((pair_car instanceof String 254 || pair_car instanceof Symbol) 255 && p.cdr instanceof Pair) 256 { 257 name = pair_car; 258 p = (Pair) p.cdr; 259 if (tr.matches(p.car, "::")) 260 { 261 if (! (p.cdr instanceof Pair)) 262 { 263 tr.syntaxError("'::' not followed by a type specifier" 264 + " (for parameter '" + name + "')"); 265 return; 266 } 267 p = (Pair) p.cdr; 268 typeSpecPair = p; 269 if (p.cdr instanceof Pair) 270 p = (Pair) p.cdr; 271 else if (p.cdr == LList.Empty) 272 p = null; 273 else 274 { 275 tr.syntaxError("improper list in specifier for parameter '" 276 + name + "')"); 277 return; 278 } 279 } 280 if (p != null && mode != null) 281 { 282 defaultValue = p.car; 283 if (p.cdr instanceof Pair) 284 p = (Pair) p.cdr; 285 else if (p.cdr == LList.Empty) 286 p = null; 287 else 288 { 289 tr.syntaxError("improper list in specifier for parameter '" 290 + name + "')"); 291 return; 292 } 293 } 294 if (p != null) 295 { 296 if (typeSpecPair != null) 297 { 298 tr.syntaxError("duplicate type specifier for parameter '" 299 + name + '\''); 300 return; 301 } 302 typeSpecPair = p; 303 if (p.cdr != LList.Empty) 304 { 305 tr.syntaxError("junk at end of specifier for parameter '" 306 + name + '\''+" after type "+p.car); 307 return; 308 } 309 } 310 } 311 } 312 if (name == null) 313 { 314 tr.syntaxError ("parameter is neither name nor (name :: type) nor (name default)"+": "+pair); 315 return; 316 } 317 if (mode == optionalKeyword || mode == keyKeyword) 318 lexp.defaultArgs[opt_args++] = new LangExp(defaultValue); 319 if (mode == keyKeyword) 320 lexp.keywords[key_args++] 321 = Keyword.make(name instanceof Symbol ? ((Symbol) name).getName() 322 : name.toString()); 323 Declaration decl = new Declaration(name); 324 Translator.setLine(decl, bindings); 325 if (typeSpecPair != null) 326 { 327 decl.setType(tr.exp2Type(typeSpecPair)); 328 decl.setFlag(Declaration.TYPE_SPECIFIED); 329 } 330 else if (mode == restKeyword) 331 decl.setType(Compilation.scmListType); 332 decl.noteValue(null); addParam(decl, templateScope, lexp, tr); 334 tr.popPositionOf(savePos); 335 } 336 if (bindings instanceof SyntaxForm) 337 { 338 SyntaxForm sf = (SyntaxForm) bindings; 339 bindings = sf.form; 340 templateScopeRest = sf.scope; 341 } 342 if (bindings instanceof String || bindings instanceof Symbol) 343 { 344 Declaration decl = new Declaration(bindings); 345 decl.setType(Compilation.scmListType); 346 decl.noteValue (null); addParam(decl, templateScopeRest, lexp, tr); 348 } 349 } 350 351 private static void addParam (Declaration decl, ScopeExp templateScope, 352 LambdaExp lexp, Translator tr) 353 { 354 if (templateScope != null) 355 decl = tr.makeRenamedAlias(decl, templateScope); 356 lexp.addDeclaration(decl); 357 if (templateScope != null) 358 decl.context = templateScope; 359 } 360 361 public Object rewriteAttrs(LambdaExp lexp, Object body, Translator tr) 362 { 363 String accessFlagName = null; 364 String allocationFlagName = null; 365 int accessFlag = 0; 366 int allocationFlag = 0; 367 SyntaxForm syntax = null; 368 for (;;) 369 { 370 while (body instanceof SyntaxForm) 371 { 372 syntax = (SyntaxForm) body; 373 body = syntax.form; 374 } 375 if (! (body instanceof Pair)) 376 break; 377 Pair pair1 = (Pair) body; 378 Object attrName = Translator.stripSyntax(pair1.car); 379 Object pair1_cdr = pair1.cdr; 380 while (pair1_cdr instanceof SyntaxForm) 381 { 382 syntax = (SyntaxForm) pair1_cdr; 383 pair1_cdr = syntax.form; 384 } 385 if (! (pair1_cdr instanceof Pair)) 386 break; 387 Pair pair2 = (Pair) pair1_cdr; 388 389 Object attrValue; 390 if (tr.matches(attrName, "::")) 391 attrName = null; 392 else if (! (attrName instanceof Keyword)) 393 break; 394 if (attrName == null) 395 { 396 Expression attrExpr = tr.rewrite_car(pair2, syntax); 397 if (lexp.isClassMethod() && "*init*".equals(lexp.getName())) 398 tr.error('e', "explicit return type for '*init*' method"); 399 else 400 { 401 gnu.bytecode.Type rtype = tr.getLanguage().getTypeFor(attrExpr); 402 if (rtype != null) 403 lexp.setReturnType(rtype); 404 } 405 } 406 else if (attrName == kawa.standard.object.accessKeyword) 407 { 408 Expression attrExpr = tr.rewrite_car(pair2, syntax); 409 if (! (attrExpr instanceof QuoteExp) 410 || ! ((attrValue = ((QuoteExp) attrExpr).getValue()) instanceof String 411 || attrValue instanceof FString)) 412 tr.error('e', "access: value not a constant symbol or string"); 413 else if (lexp.nameDecl == null) 414 tr.error('e', "access: not allowed for anonymous function"); 415 else 416 { 417 String value = attrValue.toString(); 418 if ("private".equals(value)) 419 accessFlag = Declaration.PRIVATE_ACCESS; 420 else if ("protected".equals(value)) 421 accessFlag = Declaration.PROTECTED_ACCESS; 422 else if ("public".equals(value)) 423 accessFlag = Declaration.PUBLIC_ACCESS; 424 else if ("package".equals(value)) 425 accessFlag = Declaration.PACKAGE_ACCESS; 426 else 427 tr.error('e', "unknown access specifier"); 428 if (accessFlagName != null && value != null) 429 { 430 tr.error('e', "duplicate access specifiers - " 431 + accessFlagName + " and " 432 + value); 433 } 434 accessFlagName = value; 435 } 436 } 437 else if (attrName == kawa.standard.object.allocationKeyword) 438 { 439 Expression attrExpr = tr.rewrite_car(pair2, syntax); 440 if (! (attrExpr instanceof QuoteExp) 441 || ! ((attrValue = ((QuoteExp) attrExpr).getValue()) instanceof String 442 || attrValue instanceof FString)) 443 tr.error('e', "allocation: value not a constant symbol or string"); 444 else if (lexp.nameDecl == null) 445 tr.error('e', "allocation: not allowed for anonymous function"); 446 else 447 { 448 String value = attrValue.toString(); 449 if ("class".equals(value) || "static".equals(value)) 450 allocationFlag = Declaration.STATIC_SPECIFIED; 451 else if ("instance".equals(value)) 452 allocationFlag = Declaration.NONSTATIC_SPECIFIED; 453 else 454 tr.error('e', "unknown allocation specifier"); 455 if (allocationFlagName != null && value != null) 456 { 457 tr.error('e', "duplicate allocation specifiers - " 458 + allocationFlagName + " and " 459 + value); 460 } 461 allocationFlagName = value; 462 } 463 } 464 else if (attrName == kawa.standard.object.throwsKeyword) 465 { 466 attrValue = pair2.car; 467 int count = Translator.listLength(attrValue); 468 if (count < 0) 469 tr.error('e', "throws: not followed by a list"); 470 else 471 { 472 ReferenceExp[] exps = new ReferenceExp[count]; 473 SyntaxForm syntaxLocal = syntax; 474 for (int i = 0; i < count; i++) 475 { 476 while (attrValue instanceof SyntaxForm) 477 { 478 syntaxLocal = (SyntaxForm) attrValue; 479 attrValue = syntaxLocal.form; 480 } 481 Pair pair3 = (Pair) attrValue; 482 Expression throwsExpr = tr.rewrite_car(pair3, syntaxLocal); 483 if (throwsExpr instanceof ReferenceExp) 484 { 485 exps[i] = (ReferenceExp) throwsExpr; 486 } 487 else 488 { 489 Object savePos = tr.pushPositionOf(pair3); 490 tr.error('e', "throws not followed by a classname"); 491 tr.popPositionOf(savePos); 492 } 493 attrValue = pair3.cdr; 494 } 495 lexp.setExceptions(exps); 496 } 497 } 498 else if (attrName == nameKeyword) 499 { 500 Expression attrExpr = tr.rewrite_car(pair2, syntax); 501 if (attrExpr instanceof QuoteExp) 502 lexp.setName(((QuoteExp) attrExpr).getValue().toString()); 503 } 504 else 505 { 506 tr.error('w', "unknown procedure property "+attrName); 507 } 508 body = pair2.cdr; 509 } 510 accessFlag |= allocationFlag; 511 if (accessFlag != 0) 512 lexp.nameDecl.setFlag(accessFlag); 513 if (syntax != null) 514 body = syntax.fromDatumIfNeeded(body); 515 return body; 516 } 517 518 public Object skipAttrs(LambdaExp lexp, Object body, Translator tr) 519 { 520 while (body instanceof Pair) 521 { 522 Pair pair = (Pair) body; 523 if (! (pair.cdr instanceof Pair)) 524 break; 525 Object attrName = pair.car; 526 if (tr.matches(attrName, "::")) 527 attrName = null; 528 else if (! (attrName instanceof Keyword)) 529 break; 530 body = ((Pair) pair.cdr).cdr; 531 } 532 return body; 533 } 534 535 public void rewriteBody(LambdaExp lexp, Object body, Translator tr) 536 { 537 int numRenamedAlias = 0; 538 if (tr.curMethodLambda == null 541 && lexp.nameDecl != null 542 && tr.getModule().getFlag(ModuleExp.SUPERTYPE_SPECIFIED)) 543 tr.curMethodLambda = lexp; 544 tr.pushScope(lexp); 545 Declaration prev = null; 546 int key_args = lexp.keywords == null ? 0 : lexp.keywords.length; 547 int opt_args = lexp.defaultArgs == null ? 0 548 : lexp.defaultArgs.length - key_args; 549 int arg_i = 0; 550 int opt_i = 0; 551 for (Declaration cur = lexp.firstDecl(); cur != null; cur = cur.nextDecl()) 552 { 553 if (cur.isAlias()) 554 { 555 Declaration param = Translator.getOriginalRef(cur).getBinding(); 556 lexp.replaceFollowing(prev, param); 557 param.context = lexp; 558 tr.pushRenamedAlias(cur); 559 numRenamedAlias++; 560 cur = param; 561 } 562 prev = cur; 563 564 if (arg_i >= lexp.min_args 565 && (arg_i < lexp.min_args + opt_args 566 || lexp.max_args >= 0 567 || arg_i != lexp.min_args + opt_args)) 568 { 569 lexp.defaultArgs[opt_i] = tr.rewrite(lexp.defaultArgs[opt_i]); 570 opt_i++; 571 } 572 arg_i++; 573 574 tr.lexical.push(cur); 575 } 576 577 if (lexp.isClassMethod() 578 && ! lexp.nameDecl.getFlag(Declaration.STATIC_SPECIFIED)) 579 { 580 lexp.add(null, new Declaration(ThisExp.THIS_NAME)); 582 } 583 584 LambdaExp saveLambda = tr.curLambda; 585 tr.curLambda = lexp; 586 lexp.body = tr.rewrite_body (body); 587 tr.curLambda = saveLambda; 588 Expression[] exps; 589 int len; 590 if (lexp.body instanceof BeginExp 591 && (len = (exps = ((BeginExp) lexp.body).getExpressions()).length) > 1 592 && exps[0] instanceof ReferenceExp) 593 { 594 Expression rexp = exps[0]; 596 len--; 597 if (len == 1) 598 lexp.body = exps[1]; 599 else 600 { 601 Expression[] new_body = new Expression[len]; 602 System.arraycopy(exps, 1, new_body, 0, len); 603 lexp.body = new BeginExp(new_body); 604 } 605 Convert.setCoercedReturnValue(lexp, rexp, tr.getLanguage()); 606 } 607 else if (lexp.returnType != null 608 && lexp.returnType != Type.pointer_type 609 && lexp.returnType != Type.void_type) 610 { 611 Expression value = lexp.body; 612 lexp.body = Convert.makeCoercion(value, lexp.returnType); 613 lexp.body.setLine(value); 614 } 615 tr.pop(lexp); 616 lexp.countDecls(); 617 tr.popRenamedAlias(numRenamedAlias); 618 lexp.countDecls(); 619 if (tr.curMethodLambda == lexp) 620 tr.curMethodLambda = null; 621 } 622 623 public void print (Consumer out) 624 { 625 out.write("#<builtin lambda>"); 626 } 627 } 628 | Popular Tags |