1 4 package gnu.xquery.lang; 5 import gnu.expr.*; 6 import gnu.kawa.xml.*; 7 import gnu.xml.*; 8 import gnu.mapping.*; 9 import gnu.bytecode.*; 10 import gnu.kawa.reflect.StaticFieldLocation; 11 import gnu.kawa.functions.GetNamedPart; 12 import gnu.xquery.util.NamedCollator; 13 import gnu.xquery.util.QNameUtils; 14 import java.util.Vector ; 15 import gnu.math.DateTime; 16 import gnu.math.IntNum; 17 18 public class XQResolveNames extends ResolveNames 19 { 20 XQParser parser; 21 22 23 public static final int LAST_BUILTIN = -1; 24 25 26 public static final int POSITION_BUILTIN = -2; 27 28 29 public static final int XS_QNAME_BUILTIN = -3; 30 31 32 public static final int COMPARE_BUILTIN = -4; 33 34 35 public static final int DISTINCT_VALUES_BUILTIN = -5; 36 37 38 public static final int LOCAL_NAME_BUILTIN = -6; 39 40 41 public static final int NAMESPACE_URI_BUILTIN = -7; 42 43 44 public static final int COLLECTION_BUILTIN = -8; 45 46 47 public static final int DOC_BUILTIN = -9; 48 49 50 public static final int DOC_AVAILABLE_BUILTIN = -10; 51 52 53 public static final int BASE_URI_BUILTIN = -11; 54 55 56 public static final int RESOLVE_URI_BUILTIN = -12; 57 58 59 public static final int RESOLVE_PREFIX_BUILTIN = -13; 60 61 62 public static final int STATIC_BASE_URI_BUILTIN = -14; 63 64 65 public static final int INDEX_OF_BUILTIN = -15; 66 67 68 public static final int STRING_BUILTIN = -16; 69 70 71 public static final int NORMALIZE_SPACE_BUILTIN = -17; 72 73 74 public static final int UNORDERED_BUILTIN = -18; 75 76 77 public static final int CURRENT_DATETIME_BUILTIN = -19; 78 79 80 public static final int CURRENT_DATE_BUILTIN = -20; 81 82 83 public static final int CURRENT_TIME_BUILTIN = -21; 84 85 86 public static final int IMPLICIT_TIMEZONE_BUILTIN = -22; 87 88 89 public static final int LANG_BUILTIN = -23; 90 91 92 public static final int NAME_BUILTIN = -24; 93 94 95 public static final int DEEP_EQUAL_BUILTIN = -25; 96 97 98 public static final int MIN_BUILTIN = -26; 99 100 101 public static final int MAX_BUILTIN = -27; 102 103 104 public static final int NUMBER_BUILTIN = -28; 105 106 107 public static final int DEFAULT_COLLATION_BUILTIN = -29; 108 109 110 public static final int ID_BUILTIN = -30; 111 112 113 public static final int IDREF_BUILTIN = -31; 114 115 116 public static final int ROOT_BUILTIN = -32; 117 118 public static final int CAST_AS_BUILTIN = -33; 119 public static final int CASTABLE_AS_BUILTIN = -34; 120 121 122 public static final int HANDLE_EXTENSION_BUILTIN = -35; 123 124 public static final Declaration handleExtensionDecl 125 = makeBuiltin("(extension)", HANDLE_EXTENSION_BUILTIN); 126 127 public static final Declaration castAsDecl 128 = makeBuiltin("(cast as)", CAST_AS_BUILTIN); 129 130 public static final Declaration castableAsDecl 131 = makeBuiltin("(castable as)", CASTABLE_AS_BUILTIN); 132 133 134 public static final Declaration lastDecl 135 = makeBuiltin("last", LAST_BUILTIN); 136 137 public Declaration currentDateTimeDecl; 138 public Declaration currentDateDecl; 139 public Declaration currentTimeDecl; 140 public Declaration currentTimezoneDecl; 141 142 public static final Declaration xsQNameDecl 143 = makeBuiltin(Symbol.make(XQuery.SCHEMA_NAMESPACE, "QName"), XS_QNAME_BUILTIN); 144 145 public static final Declaration staticBaseUriDecl 146 = makeBuiltin("static-base-uri", STATIC_BASE_URI_BUILTIN); 147 148 public static final Declaration resolvePrefixDecl 149 = makeBuiltin(Symbol.make(XQuery.SCHEMA_NAMESPACE, "(resolve-prefix)"), 150 RESOLVE_PREFIX_BUILTIN); 151 152 153 public static Declaration makeBuiltin (String name, int code) 154 { 155 return makeBuiltin (Symbol.make(XQuery.XQUERY_FUNCTION_NAMESPACE, name, "fn"), 156 code); 157 } 158 159 160 public static Declaration makeBuiltin (Symbol name, int code) 161 { 162 Declaration decl = new Declaration(name); 163 decl.setProcedureDecl(true); 164 decl.setCode(code); 165 return decl; 166 } 167 168 public XQResolveNames () 169 { 170 this(null); 171 } 172 173 void pushBuiltin (String name, int code) 174 { 175 lookup.push(makeBuiltin(name, code)); 176 } 177 178 public XQResolveNames (Compilation comp) 179 { 180 super(comp); 181 lookup.push(lastDecl); 182 lookup.push(xsQNameDecl); 183 lookup.push(staticBaseUriDecl); 184 pushBuiltin("position", POSITION_BUILTIN); 185 pushBuiltin("compare", COMPARE_BUILTIN); 186 pushBuiltin("distinct-values", DISTINCT_VALUES_BUILTIN); 187 pushBuiltin("local-name", LOCAL_NAME_BUILTIN); 188 pushBuiltin("name", NAME_BUILTIN); 189 pushBuiltin("namespace-uri", NAMESPACE_URI_BUILTIN); 190 pushBuiltin("root", ROOT_BUILTIN); 191 pushBuiltin("base-uri", BASE_URI_BUILTIN); 192 pushBuiltin("lang", LANG_BUILTIN); 193 pushBuiltin("resolve-uri", RESOLVE_URI_BUILTIN); 194 pushBuiltin("collection", COLLECTION_BUILTIN); 195 pushBuiltin("doc", DOC_BUILTIN); 196 pushBuiltin("document", DOC_BUILTIN); pushBuiltin("doc-available", DOC_AVAILABLE_BUILTIN); 198 pushBuiltin("index-of", INDEX_OF_BUILTIN); 199 pushBuiltin("string", STRING_BUILTIN); 200 pushBuiltin("normalize-space", NORMALIZE_SPACE_BUILTIN); 201 pushBuiltin("unordered", UNORDERED_BUILTIN); 202 pushBuiltin("current-dateTime", CURRENT_DATETIME_BUILTIN); 203 pushBuiltin("current-date", CURRENT_DATE_BUILTIN); 204 pushBuiltin("current-time", CURRENT_TIME_BUILTIN); 205 pushBuiltin("implicit-timezone", IMPLICIT_TIMEZONE_BUILTIN); 206 pushBuiltin("deep-equal", DEEP_EQUAL_BUILTIN); 207 pushBuiltin("min", MIN_BUILTIN); 208 pushBuiltin("max", MAX_BUILTIN); 209 pushBuiltin("number", NUMBER_BUILTIN); 210 pushBuiltin("default-collation", DEFAULT_COLLATION_BUILTIN); 211 pushBuiltin("id", ID_BUILTIN); 212 pushBuiltin("idref", IDREF_BUILTIN); 213 } 214 215 public Namespace[] functionNamespacePath 216 = XQuery.defaultFunctionNamespacePath; 217 218 protected void push (ScopeExp exp) 219 { 220 for (Declaration decl = exp.firstDecl(); 221 decl != null; decl = decl.nextDecl()) 222 { 223 push(decl); 224 } 225 } 226 227 void push (Declaration decl) 228 { 229 Compilation comp = getCompilation(); 230 Object name = decl.getSymbol(); 231 boolean function = decl.isProcedureDecl(); 232 if (name instanceof String ) 233 { 234 int line = decl.getLineNumber(); 235 if (line > 0 && comp != null) 236 { 237 String saveFilename = comp.getFileName(); 238 int saveLine = comp.getLineNumber(); 239 int saveColumn = comp.getColumnNumber(); 240 comp.setLocation(decl); 241 name = parser.namespaceResolve((String ) name, function); 242 comp.setLine(saveFilename, saveLine, saveColumn); 243 } 244 else 245 name = parser.namespaceResolve((String ) name, function); 246 if (name == null) 247 return; 248 decl.setName(name); 249 } 250 251 Declaration old = lookup.lookup(name, XQuery.instance.getNamespaceOf(decl)); 252 if (old != null) 253 { 254 if (decl.context == old.context) 255 ScopeExp.duplicateDeclarationError(old, decl, comp); 256 else if (XQParser.warnHidePreviousDeclaration 257 && (! (name instanceof Symbol) 258 || ((Symbol) name).getNamespace() != null)) 259 comp.error('w', decl, "declaration ", 260 " hides previous declaration"); 261 } 262 lookup.push(decl); 263 } 264 265 Declaration flookup (Symbol sym) 266 { 267 Environment env = XQuery.xqEnvironment; 268 gnu.mapping.Location loc = env.lookup(sym, EnvironmentKey.FUNCTION); 269 if (loc == null) 270 return null; 271 loc = loc.getBase(); 272 if (loc instanceof StaticFieldLocation) 273 { 274 Declaration decl = ((StaticFieldLocation) loc).getDeclaration(); 275 if (decl != null) 276 return decl; 277 } 278 Object val = loc.get(null); 279 if (val != null) 280 return procToDecl(sym, val); 281 return null; 282 } 283 284 protected Expression walkReferenceExp (ReferenceExp exp) 285 { 286 return walkReferenceExp(exp, null); 287 } 288 289 protected Expression walkReferenceExp (ReferenceExp exp, ApplyExp call) 290 { 291 if (exp.getBinding() == null) 292 { 293 Object symbol = exp.getSymbol(); 294 boolean function = exp.isProcedureName(); 295 int namespace = call == null ? XQuery.VALUE_NAMESPACE 296 : XQuery.namespaceForFunctions(call.getArgCount()); 297 Declaration decl = lookup.lookup(symbol, namespace); 298 Symbol sym; 299 if (decl != null) 300 ; 301 else if (symbol instanceof Symbol 302 && "".equals((sym = (Symbol) symbol).getNamespaceURI())) 303 { 304 String name = sym.getLocalName(); 306 Expression f; 307 if ("request".equals(name)) 308 f = XQParser.makeFunctionExp("gnu.kawa.servlet.GetRequest", 309 "getRequest"); 310 else if ("response".equals(name)) 311 f = XQParser.makeFunctionExp("gnu.kawa.servlet.GetResponse", 312 "getResponse"); 313 else 314 f = null; 315 if (f != null) 316 return new ApplyExp(f, Expression.noExpressions); 317 } 318 else if (symbol instanceof Symbol) 319 { 320 decl = flookup((Symbol) symbol); 322 } 323 else { 325 String name = (String ) symbol; 326 if (name.indexOf(':') < 0) 327 { 328 name = name.intern(); 329 if (function) 330 { 331 for (int i = 0; i < functionNamespacePath.length; i++) 332 { 333 sym = functionNamespacePath[i].getSymbol(name); 334 decl = lookup.lookup(sym, function); 335 if (decl != null) 336 break; 337 if (! function) 338 continue; 339 decl = flookup(sym); 340 if (decl != null) 341 break; 342 } 343 } 344 } 345 if (decl == null) 346 { 347 sym = parser.namespaceResolve(name, function); 348 if (sym != null) 349 { 350 decl = lookup.lookup(sym, namespace); 351 if (decl == null && function) 352 { 353 String uri = sym.getNamespaceURI(); 354 if (XQuery.SCHEMA_NAMESPACE.equals(uri)) 355 { 356 Type type = 357 XQuery.getStandardType(sym.getName()); 358 if (type != null) 359 return QuoteExp.getInstance(type); 360 } 361 if (uri != null && uri.length() > 6 && 362 uri.startsWith("class:")) 363 { 364 ClassType ctype = ClassType.make(uri.substring(6)); 365 return GetNamedPart.makeExp(ctype, sym.getName()); 366 } 367 decl = flookup(sym); 368 } 369 } 370 } 371 } 372 if (decl != null) 373 exp.setBinding(decl); 374 else if (function) 375 error('e', "unknown function "+symbol); 376 else 377 messages.error('e',"unknown variable $"+symbol, "XPST0008"); 378 } 379 return exp; 380 } 381 382 protected Expression walkSetExp (SetExp exp) 383 { 384 Expression result = super.walkSetExp(exp); 385 Declaration decl = exp.getBinding(); 386 Object name; 387 Expression new_value; 388 if (decl != null && ! getCompilation().immediate 389 && (name = decl.getSymbol()) instanceof Symbol 390 && XQuery.LOCAL_NAMESPACE.equals(((Symbol) name).getNamespaceURI()) 391 && (! ((new_value = exp.getNewValue()) instanceof ApplyExp) 392 || ((ApplyExp) new_value).getFunction() != XQParser.getExternalFunction)) 393 { 394 decl.setFlag(Declaration.PRIVATE_SPECIFIED); 395 decl.setPrivate(true); 396 } 397 return result; 398 } 399 400 private Declaration moduleDecl; 401 private Expression walkStatements (Expression exp) 402 { 403 if (exp instanceof BeginExp) 407 { 408 BeginExp bbody = (BeginExp) exp; 409 Expression[] exps = bbody.getExpressions(); 410 int nexps = bbody.getExpressionCount(); 411 for (int i = 0; i < nexps; i++) 412 { 413 exps[i] = walkStatements(exps[i]); 414 } 415 } 416 else if (exp instanceof SetExp) 417 { 418 Declaration decl = moduleDecl; 419 while (decl != null && decl.isNamespaceDecl()) 420 decl = decl.nextDecl(); 421 SetExp sexp = (SetExp) exp; 422 exp = walkSetExp(sexp); 423 if (sexp.isDefining() && sexp.getBinding() == decl) 424 { 425 if (! decl.isProcedureDecl() && ! decl.isNamespaceDecl()) 426 push(decl); 427 decl = decl.nextDecl(); 428 } 429 moduleDecl = decl; 430 } 431 else 432 exp = walk(exp); 433 return exp; 434 } 435 436 public void resolveModule(ModuleExp exp) 437 { 438 currentLambda = exp; 439 for (Declaration decl = exp.firstDecl(); 440 decl != null; decl = decl.nextDecl()) 441 { 442 if (decl.isProcedureDecl()) 443 push(decl); 444 else if (decl.isNamespaceDecl()) 445 lookup.push(decl); 446 } 447 moduleDecl = exp.firstDecl(); 448 exp.body = walkStatements(exp.body); 449 450 Expression[] exps; 451 if (currentDateTimeDecl != null) 452 { 453 Vector vec = new Vector (); 460 vec.addElement(new SetExp(currentDateTimeDecl, 461 new ApplyExp(ClassType.make("gnu.xquery.util.TimeUtils").getDeclaredMethod("now", 0), 462 Expression.noExpressions))); 463 Method cast = ClassType.make("gnu.math.DateTime").getDeclaredMethod("cast", 1); 464 if (currentDateDecl != null) 465 { 466 Expression[] args = { new ReferenceExp(currentDateTimeDecl), 467 new QuoteExp(IntNum.make(DateTime.DATE_MASK)) }; 468 vec.addElement(new SetExp(currentDateDecl, 469 new ApplyExp(cast, args))); 470 } 471 if (currentTimeDecl != null) 472 { 473 Expression[] args = { new ReferenceExp(currentDateTimeDecl), 474 new QuoteExp(IntNum.make(DateTime.TIME_MASK)) }; 475 vec.addElement(new SetExp(currentTimeDecl, 476 new ApplyExp(cast, args))); 477 } 478 if (currentTimezoneDecl != null) 479 { 480 Expression[] args = { new ReferenceExp(currentDateTimeDecl) }; 481 vec.addElement(new SetExp(currentTimezoneDecl, 482 new ApplyExp(ClassType.make("gnu.xquery.util.TimeUtils").getDeclaredMethod("timezoneFromDateTime", 1), args))); 483 } 484 Expression body = exp.body; 485 if (body instanceof BeginExp) 486 { 487 BeginExp bexp = (BeginExp) body; 488 int blen = bexp.getExpressionCount(); 489 exps = bexp.getExpressions(); 490 for (int i = 0; i < blen; i++) 491 vec.addElement(exps[i]); 492 } 493 else 494 vec.addElement(body); 495 exps = new Expression[vec.size()]; 496 vec.copyInto(exps); 497 exp.body = new BeginExp(exps); 498 } 499 } 500 501 506 Expression getCollator (Expression[] args, int argno) 507 { 508 if (args != null && args.length > argno) 509 return new ApplyExp(ClassType.make("gnu.xquery.util.NamedCollator") 510 .getDeclaredMethod("find", 1), 511 new Expression[] { args[argno] }); 512 NamedCollator coll = parser.defaultCollator; 513 return coll == null ? QuoteExp.nullExp : new QuoteExp(coll); 514 } 515 516 Expression withCollator (Method method, Expression[] args, 517 String name, int minArgs) 518 { 519 return withCollator(new QuoteExp(new PrimProcedure(method)), 520 args, name, minArgs); 521 } 522 523 524 Expression withCollator (Expression function, Expression[] args, 525 String name, int minArgs) 526 { 527 String err = WrongArguments.checkArgCount(name, minArgs, minArgs+1, args.length); 528 if (err != null) 529 return getCompilation().syntaxError(err); 530 Expression[] xargs = new Expression[minArgs+1]; 531 System.arraycopy(args, 0, xargs, 0, minArgs); 532 xargs[minArgs] = getCollator(args, minArgs); 533 return new ApplyExp(function, xargs); 534 } 535 536 537 Expression withContext (Method method, Expression[] args, 538 String name, int minArgs) 539 { 540 String err = WrongArguments.checkArgCount(name, minArgs, minArgs+1, 541 args.length); 542 if (err != null) 543 return getCompilation().syntaxError(err); 544 if (args.length == minArgs) 545 { 546 Expression[] xargs = new Expression[minArgs+1]; 547 System.arraycopy(args, 0, xargs, 0, minArgs); 548 Declaration dot = lookup.lookup(XQParser.DOT_VARNAME, false); 549 if (dot == null) 550 { 551 String message = "undefined context for " + name; 552 messages.error('e', message, "XPDY0002"); 553 return new ErrorExp(message); 554 } 555 xargs[minArgs] = new ReferenceExp(dot); 556 args = xargs; 557 } 558 return new ApplyExp(method, args); 559 } 560 561 private Expression checkArgCount (Expression[] args, Declaration decl, 562 int min, int max) 563 { 564 String err = WrongArguments.checkArgCount("fn:"+decl.getName(), 565 min, max, args.length); 566 if (err == null) 567 return null; 568 else 569 return getCompilation().syntaxError(err); 570 } 571 572 protected Expression walkApplyExp (ApplyExp exp) 573 { 574 Expression func = exp.getFunction(); 575 NamespaceBinding namespaceSave = parser.constructorNamespaces; 576 Object proc = exp.getFunctionValue(); 577 if (proc instanceof MakeElement) 578 { 579 MakeElement mk = (MakeElement) proc; 580 NamespaceBinding nschain 581 = NamespaceBinding.nconc(mk.getNamespaceNodes(), namespaceSave); 582 mk.setNamespaceNodes(nschain); 583 parser.constructorNamespaces = nschain; 584 } 585 if (func instanceof ReferenceExp) 586 func = walkReferenceExp((ReferenceExp) func, exp); 587 else 588 func = walk(func); 589 exp.setFunction(func); 590 walkExps(exp.getArgs()); 591 parser.constructorNamespaces = namespaceSave; 592 func = exp.getFunction(); 593 if (func instanceof ReferenceExp) 594 { 595 Declaration decl = ((ReferenceExp) func).getBinding(); 596 int code; 597 Expression err; 598 ModuleExp mexp; 599 if (decl != null && (code = decl.getCode()) < 0) 600 { 601 switch (code) 602 { 603 case POSITION_BUILTIN: 604 case LAST_BUILTIN: 605 Symbol sym = code == LAST_BUILTIN ? XQParser.LAST_VARNAME 606 : XQParser.POSITION_VARNAME; 607 decl = lookup.lookup(sym, false); 608 if (decl == null) 609 error('e', "undefined context for " + sym.getName()); 610 else 611 decl.setCanRead(true); 613 return new ReferenceExp(sym, decl); 614 case CAST_AS_BUILTIN: 615 { 616 Expression[] args = exp.getArgs(); 617 if (args[0].valueIfConstant() == Compilation.typeSymbol) 618 return walkApplyExp(XQParser.castQName(args[1])); 619 func 620 = XQParser.makeFunctionExp("gnu.xquery.util.CastAs", "castAs"); 621 return new ApplyExp(func, args); 622 } 623 case CASTABLE_AS_BUILTIN: 624 { 625 Expression[] args = exp.getArgs(); 626 if (args[1].valueIfConstant() == Compilation.typeSymbol 627 && args[0] instanceof QuoteExp) 628 { 629 Object value = ((QuoteExp) args[0]).getValue(); 630 try 631 { 632 QNameUtils.resolveQName(value, 633 parser.constructorNamespaces, 634 parser.prologNamespaces); 635 return XQuery.trueExp; 636 } 637 catch (RuntimeException ex) 638 { 639 return XQuery.falseExp; 640 } 641 } 642 func = XQParser.makeFunctionExp("gnu.xquery.lang.XQParser", "castableAs"); 643 return new ApplyExp(func, args); 644 } 645 case XS_QNAME_BUILTIN: 646 { 647 Expression[] args = exp.getArgs(); 648 if ((err = checkArgCount(args, decl, 1, 1)) != null) 649 return err; 650 if (args[0] instanceof QuoteExp) 651 { 652 try 653 { 654 Object val = ((QuoteExp) args[0]).getValue(); 655 val = QNameUtils.resolveQName(val, 656 parser.constructorNamespaces, 657 parser.prologNamespaces); 658 return new QuoteExp(val); 659 } 660 catch (RuntimeException ex) 661 { 662 return getCompilation().syntaxError(ex.getMessage()); 663 } 664 } 665 Expression[] xargs = { 666 args[0], 667 new QuoteExp(parser.constructorNamespaces), 668 new QuoteExp(parser.prologNamespaces) }; 669 Method meth 670 = (ClassType.make("gnu.xquery.util.QNameUtils") 671 .getDeclaredMethod("resolveQName", 3)); 672 ApplyExp app = new ApplyExp(meth, xargs); 673 app.setFlag(ApplyExp.INLINE_IF_CONSTANT); 674 return app; 675 } 676 case RESOLVE_PREFIX_BUILTIN: 677 { 678 Expression[] args = exp.getArgs(); 679 if ((err = checkArgCount(args, decl, 1, 1)) != null) 680 return err; 681 if (args[0] instanceof QuoteExp) 682 { 683 Object val = ((QuoteExp) args[0]).getValue(); 684 String prefix = val == null ? null : val.toString(); 685 val = QNameUtils.lookupPrefix(prefix, 686 parser.constructorNamespaces, 687 parser.prologNamespaces); 688 if (val == null) 689 return getCompilation() 690 .syntaxError("unknown namespace prefix '" 691 +prefix+"'"); 692 return new QuoteExp(val); 693 } 694 Expression[] xargs = { 695 args[0], 696 new QuoteExp(parser.constructorNamespaces), 697 new QuoteExp(parser.prologNamespaces) }; 698 PrimProcedure pproc 699 = new PrimProcedure(ClassType.make("gnu.xquery.util.QNameUtils") 700 .getDeclaredMethod("resolvePrefix", 3)); 701 ApplyExp app = new ApplyExp(pproc, xargs); 702 app.setFlag(ApplyExp.INLINE_IF_CONSTANT); 703 return app; 704 } 705 case LOCAL_NAME_BUILTIN: 706 { 707 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 708 .getDeclaredMethod("localName", 1); 709 return withContext(meth, exp.getArgs(), "fn:local-name", 0); 710 } 711 case NAME_BUILTIN: 712 { 713 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 714 .getDeclaredMethod("name", 1); 715 return withContext(meth, exp.getArgs(), "fn:name", 0); 716 } 717 case NUMBER_BUILTIN: 718 { 719 Method meth = ClassType.make("gnu.xquery.util.NumberValue") 720 .getDeclaredMethod("numberValue", 1); 721 return withContext(meth, exp.getArgs(), "fn:number", 0); 722 } 723 case ROOT_BUILTIN: 724 { 725 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 726 .getDeclaredMethod("root", 1); 727 return withContext(meth, exp.getArgs(), "fn:root", 0); 728 } 729 case BASE_URI_BUILTIN: 730 { 731 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 732 .getDeclaredMethod("baseUri", 1); 733 return withContext(meth, exp.getArgs(), "fn:base-uri", 0); 734 } 735 case LANG_BUILTIN: 736 { 737 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 738 .getDeclaredMethod("lang", 2); 739 return withContext(meth, exp.getArgs(), "fn:lang", 1); 740 } 741 case ID_BUILTIN: 742 { 743 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 744 .getDeclaredMethod("id$X", 3); 745 return withContext(meth, exp.getArgs(), "fn:id", 1); 746 } 747 case IDREF_BUILTIN: 748 { 749 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 750 .getDeclaredMethod("idref", 2); 751 return withContext(meth, exp.getArgs(), "fn:idref", 1); 752 } 753 754 case STATIC_BASE_URI_BUILTIN: 755 { 756 Expression[] args = exp.getArgs(); 757 if ((err = checkArgCount(args, decl, 0, 0)) != null) 758 return err; 759 return getBaseUriExpr(); 760 } 761 case NAMESPACE_URI_BUILTIN: 762 { 763 Method meth = ClassType.make("gnu.xquery.util.NodeUtils") 764 .getDeclaredMethod("namespaceURI", 1); 765 return withContext(meth, exp.getArgs(), 766 "fn:namespace-uri", 0); 767 } 768 769 case NORMALIZE_SPACE_BUILTIN: 770 { 771 Method meth = ClassType.make("gnu.xquery.util.StringUtils") 772 .getDeclaredMethod("normalizeSpace", 1); 773 return withContext(meth, exp.getArgs(), 774 "fn:normalize-space", 0); 775 } 776 777 case UNORDERED_BUILTIN: 778 { 779 Expression[] args = exp.getArgs(); 780 if ((err = checkArgCount(args, decl, 1, 1)) != null) 781 return err; 782 return args[0]; 783 } 784 785 case COMPARE_BUILTIN: 786 { 787 Method meth = ClassType.make("gnu.xquery.util.StringUtils") 788 .getDeclaredMethod("compare", 3); 789 return withCollator(meth, exp.getArgs(), "fn:compare", 2); 790 } 791 792 case STRING_BUILTIN: 793 return withContext(ClassType.make("gnu.xml.TextUtils") 794 .getDeclaredMethod("asString", 1), 795 exp.getArgs(), "fn:string", 0); 796 797 case INDEX_OF_BUILTIN: 798 { 799 Method meth = ClassType.make("gnu.xquery.util.SequenceUtils") 800 .getDeclaredMethod("indexOf$X", 4); 801 return withCollator(meth, exp.getArgs(), "fn:index-of", 2); 802 } 803 case COLLECTION_BUILTIN: 804 { 805 Expression[] args = exp.getArgs(); 806 ClassType cl = ClassType.make("gnu.xquery.util.NodeUtils"); 807 Method meth = cl.getDeclaredMethod("collection", 2); 808 if ((err = checkArgCount(args, decl, 0, 1)) != null) 809 return err; 810 Expression base = getBaseUriExpr(); 811 Expression uri = args.length > 0 ? args[0] 812 : QuoteExp.voidExp; 813 ApplyExp aexp 814 = new ApplyExp(meth, new Expression[]{ uri, base }); 815 if (code == DOC_BUILTIN) 816 aexp.setType(NodeType.documentNodeTest); 817 else 818 aexp.setType(XDataType.booleanType); 819 return aexp; 820 } 821 case DOC_BUILTIN: 822 case DOC_AVAILABLE_BUILTIN: 823 { 824 Expression[] args = exp.getArgs(); 825 ClassType cl = ClassType.make("gnu.xquery.util.NodeUtils"); 826 String mname; 827 if (code == DOC_BUILTIN) 828 { 829 mname = "docCached"; 830 if (parser.warnOldVersion 831 && "document".equals(decl.getName())) 832 getCompilation() 833 .error('w', "replace 'document' by 'doc'"); 834 } 835 else 836 mname = "availableCached"; 837 Method meth = cl.getDeclaredMethod(mname, 2); 838 if ((err = checkArgCount(args, decl, 1, 1)) != null) 839 return err; 840 Expression base = getBaseUriExpr(); 841 ApplyExp aexp 842 = new ApplyExp(meth, new Expression[]{ args[0], base }); 843 if (code == DOC_BUILTIN) 844 aexp.setType(NodeType.documentNodeTest); 845 else 846 aexp.setType(XDataType.booleanType); 847 return aexp; 848 } 849 case RESOLVE_URI_BUILTIN: 850 { 851 Expression[] args = exp.getArgs(); 852 if ((err = checkArgCount(args, decl, 1, 2)) != null) 853 return err; 854 Expression[] margs = new Expression[2]; 855 margs[0] = args[0]; 856 if (args.length == 1) 857 margs[1] = getBaseUriExpr(); 858 else 859 margs[1] = args[1]; 860 Method meth = ClassType.make("gnu.xquery.util.QNameUtils") 861 .getDeclaredMethod("resolveURI", 2); 862 return new ApplyExp(meth, margs); 863 } 864 case DISTINCT_VALUES_BUILTIN: 865 { 866 Method meth = ClassType.make("gnu.xquery.util.DistinctValues") 867 .getDeclaredMethod("distinctValues$X", 3); 868 return withCollator(meth, exp.getArgs(), 869 "fn:distinct-values", 1); 870 871 } 872 case DEEP_EQUAL_BUILTIN: 873 { 874 Method meth = ClassType.make("gnu.xquery.util.SequenceUtils") 875 .getDeclaredMethod("deepEqual", 3); 876 return withCollator(meth, exp.getArgs(), 877 "fn:deep-equal", 2); 878 } 879 case MIN_BUILTIN: 880 { 881 Method meth = ClassType.make("gnu.xquery.util.MinMax") 882 .getDeclaredMethod("min", 2); 883 return withCollator(meth, exp.getArgs(), 884 "fn:min", 1); 885 } 886 case MAX_BUILTIN: 887 { 888 Method meth = ClassType.make("gnu.xquery.util.MinMax") 889 .getDeclaredMethod("max", 2); 890 return withCollator(meth, exp.getArgs(), 891 "fn:max", 1); 892 } 893 case DEFAULT_COLLATION_BUILTIN: 894 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null) 895 return err; 896 NamedCollator coll = parser.defaultCollator; 897 return QuoteExp.getInstance(coll != null ? coll.getName() 898 : NamedCollator.UNICODE_CODEPOINT_COLLATION); 899 case CURRENT_DATETIME_BUILTIN: 900 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null) 901 return err; 902 mexp = getCompilation().mainLambda; 903 if (currentDateTimeDecl == null) 904 currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType); 905 return new ReferenceExp(currentDateTimeDecl); 906 case CURRENT_DATE_BUILTIN: 907 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null) 908 return err; 909 mexp = getCompilation().mainLambda; 910 if (currentDateTimeDecl == null) 911 currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType); 912 if (currentDateDecl == null) 913 currentDateDecl = mexp.addDeclaration("date", XTimeType.dateType); 914 return new ReferenceExp(currentDateDecl); 915 case CURRENT_TIME_BUILTIN: 916 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null) 917 return err; 918 mexp = getCompilation().mainLambda; 919 if (currentDateTimeDecl == null) 920 currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType); 921 if (currentTimeDecl == null) 922 currentTimeDecl = mexp.addDeclaration("time", XTimeType.timeType); 923 return new ReferenceExp(currentTimeDecl); 924 case IMPLICIT_TIMEZONE_BUILTIN: 925 if ((err = checkArgCount(exp.getArgs(), decl, 0, 0)) != null) 926 return err; 927 mexp = getCompilation().mainLambda; 928 if (currentDateTimeDecl == null) 929 currentDateTimeDecl = mexp.addDeclaration("dateTime", XTimeType.dateTimeType); 930 if (currentTimezoneDecl == null) 931 currentTimezoneDecl = mexp.addDeclaration("timezone", XTimeType.dayTimeDurationType); 932 return new ReferenceExp(currentTimezoneDecl); 933 case HANDLE_EXTENSION_BUILTIN: 934 { 935 Compilation comp = getCompilation(); 936 Expression[] args = exp.getArgs(); 937 int i = 0; 938 for (; i < args.length - 1; i += 2) 939 { 940 Expression pname = args[i]; 941 String qname = (String ) ((QuoteExp) pname).getValue(); 942 Symbol psymbol = parser.namespaceResolve(qname, false); 943 if (psymbol == null) 944 ; else if (psymbol.getNamespaceURI().length() == 0) 946 comp.error('e', "pragma name cannot be in the empty namespace"); 947 else 948 { 949 Expression replacement 950 = checkPragma(psymbol, args[i+1]); 951 if (replacement != null) 952 return replacement; 953 } 954 } 955 if (i < args.length) 956 return args[args.length-1]; 957 String msg = "no recognized pragma or default in extension expression"; 958 getMessages().error('e', msg, "XQST0079"); 959 return new ErrorExp(msg); 960 } 961 } 962 } 963 } 964 proc = exp.getFunctionValue(); 965 if (proc instanceof Type) 966 { 967 Expression[] args = exp.getArgs(); 968 if (args.length != 1) 969 { 970 messages.error('e', "type constructor requires a single argument"); 971 return exp; 972 } 973 return new ApplyExp(XQParser.makeFunctionExp("gnu.xquery.util.CastAs", "castAs"), 974 new Expression[] { exp.getFunction(), args[0] }); 975 } 976 if (proc instanceof MakeElement) 977 { 978 MakeElement make = (MakeElement) proc; 979 980 NamespaceBinding nsBindings = make.getNamespaceNodes(); 982 nsBindings = maybeAddNamespace(MakeElement.getTagName(exp), 983 nsBindings); 984 Expression[] args = exp.getArgs(); 985 Symbol[] attrSyms = new Symbol[args.length]; 986 int nattrSyms = 0; 987 for (int i = 0; i < args.length; i++) 988 { 989 Expression arg = args[i]; 990 if (arg instanceof ApplyExp) 991 { 992 ApplyExp app = (ApplyExp) arg; 993 if (app.getFunction() == MakeAttribute.makeAttributeExp) 994 { 995 Symbol sym = MakeElement.getTagName(app); 996 if (sym != null) 997 { 998 for (int j = 0; ; j++) 999 { 1000 if (j == nattrSyms) 1001 { 1002 attrSyms[nattrSyms++] = sym; 1003 break; 1004 } 1005 if (sym.equals(attrSyms[j])) 1006 { 1007 getCompilation().setLine(app); 1008 Symbol groupSym = MakeElement.getTagName(exp); 1009 String groupName = groupSym == null ? null 1010 : groupSym.toString(); 1011 messages.error('e', XMLFilter.duplicateAttributeMessage(sym, groupName), "XQST0040"); 1012 } 1013 } 1014 } 1015 nsBindings = maybeAddNamespace(sym, nsBindings); 1016 } 1017 } 1018 } 1019 if (nsBindings != null) 1020 make.setNamespaceNodes(nsBindings); 1021 } 1022 return exp; 1023 } 1024 1025 public Expression 1026 checkPragma (Symbol name, Expression contents) 1027 { 1028 return null; 1029 } 1030 1031 Expression getBaseUriExpr () 1032 { 1033 Compilation comp = getCompilation(); 1034 String staticBaseUri = parser.getStaticBaseUri(); 1035 if (staticBaseUri != null) 1036 return QuoteExp.getInstance(staticBaseUri); 1037 else 1038 return gnu.kawa.functions.GetModuleClass.getModuleClassURI(comp); 1039 } 1040 1041 static NamespaceBinding maybeAddNamespace(Symbol qname, 1042 NamespaceBinding bindings) 1043 { 1044 if (qname == null) return bindings; 1046 String prefix = qname.getPrefix(); 1047 String uri = qname.getNamespaceURI(); 1048 return NamespaceBinding.maybeAdd(prefix == "" ? null : prefix, 1049 uri == "" ? null : uri, 1050 bindings); 1051 } 1052 1053 1054 static Declaration procToDecl (Object symbol, Object val) 1055 { 1056 Declaration decl = new Declaration(symbol); 1057 decl.setProcedureDecl(true); 1058 decl.noteValue(new QuoteExp(val)); 1059 decl.setFlag(Declaration.IS_CONSTANT); 1060 return decl; 1061 } 1062} 1063 | Popular Tags |