1 16 19 20 package org.apache.xalan.xsltc.compiler; 21 22 import java.util.ArrayList ; 23 24 import org.apache.bcel.classfile.Field; 25 import org.apache.bcel.generic.ASTORE; 26 import org.apache.bcel.generic.CHECKCAST; 27 import org.apache.bcel.generic.ConstantPoolGen; 28 import org.apache.bcel.generic.GETFIELD; 29 import org.apache.bcel.generic.INVOKESPECIAL; 30 import org.apache.bcel.generic.InstructionList; 31 import org.apache.bcel.generic.LocalVariableGen; 32 import org.apache.bcel.generic.NEW; 33 import org.apache.bcel.generic.PUSH; 34 import org.apache.bcel.generic.PUTFIELD; 35 import org.apache.xalan.xsltc.compiler.util.BooleanType; 36 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 37 import org.apache.xalan.xsltc.compiler.util.FilterGenerator; 38 import org.apache.xalan.xsltc.compiler.util.IntType; 39 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 40 import org.apache.xalan.xsltc.compiler.util.NumberType; 41 import org.apache.xalan.xsltc.compiler.util.ReferenceType; 42 import org.apache.xalan.xsltc.compiler.util.ResultTreeType; 43 import org.apache.xalan.xsltc.compiler.util.TestGenerator; 44 import org.apache.xalan.xsltc.compiler.util.Type; 45 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 46 import org.apache.xalan.xsltc.compiler.util.Util; 47 48 53 final class Predicate extends Expression implements Closure { 54 55 58 private Expression _exp = null; 59 60 65 private boolean _canOptimize = true; 66 67 71 private boolean _nthPositionFilter = false; 72 73 77 private boolean _nthDescendant = false; 78 79 82 int _ptype = -1; 83 84 87 private String _className = null; 88 89 92 private ArrayList _closureVars = null; 93 94 97 private Closure _parentClosure = null; 98 99 102 private Expression _value = null; 103 104 107 private Step _step = null; 108 109 112 public Predicate(Expression exp) { 113 _exp = exp; 114 _exp.setParent(this); 115 116 } 117 118 121 public void setParser(Parser parser) { 122 super.setParser(parser); 123 _exp.setParser(parser); 124 } 125 126 130 public boolean isNthPositionFilter() { 131 return _nthPositionFilter; 132 } 133 134 138 public boolean isNthDescendant() { 139 return _nthDescendant; 140 } 141 142 145 public void dontOptimize() { 146 _canOptimize = false; 147 } 148 149 153 public boolean hasPositionCall() { 154 return _exp.hasPositionCall(); 155 } 156 157 161 public boolean hasLastCall() { 162 return _exp.hasLastCall(); 163 } 164 165 167 171 public boolean inInnerClass() { 172 return (_className != null); 173 } 174 175 178 public Closure getParentClosure() { 179 if (_parentClosure == null) { 180 SyntaxTreeNode node = getParent(); 181 do { 182 if (node instanceof Closure) { 183 _parentClosure = (Closure) node; 184 break; 185 } 186 if (node instanceof TopLevelElement) { 187 break; } 189 node = node.getParent(); 190 } while (node != null); 191 } 192 return _parentClosure; 193 } 194 195 199 public String getInnerClassName() { 200 return _className; 201 } 202 203 206 public void addVariable(VariableRefBase variableRef) { 207 if (_closureVars == null) { 208 _closureVars = new ArrayList (); 209 } 210 211 if (!_closureVars.contains(variableRef)) { 213 _closureVars.add(variableRef); 214 215 Closure parentClosure = getParentClosure(); 217 if (parentClosure != null) { 218 parentClosure.addVariable(variableRef); 219 } 220 } 221 } 222 223 225 229 public int getPosType() { 230 if (_ptype == -1) { 231 SyntaxTreeNode parent = getParent(); 232 if (parent instanceof StepPattern) { 233 _ptype = ((StepPattern)parent).getNodeType(); 234 } 235 else if (parent instanceof AbsoluteLocationPath) { 236 AbsoluteLocationPath path = (AbsoluteLocationPath)parent; 237 Expression exp = path.getPath(); 238 if (exp instanceof Step) { 239 _ptype = ((Step)exp).getNodeType(); 240 } 241 } 242 else if (parent instanceof VariableRefBase) { 243 final VariableRefBase ref = (VariableRefBase)parent; 244 final VariableBase var = ref.getVariable(); 245 final Expression exp = var.getExpression(); 246 if (exp instanceof Step) { 247 _ptype = ((Step)exp).getNodeType(); 248 } 249 } 250 else if (parent instanceof Step) { 251 _ptype = ((Step)parent).getNodeType(); 252 } 253 } 254 return _ptype; 255 } 256 257 public boolean parentIsPattern() { 258 return (getParent() instanceof Pattern); 259 } 260 261 public Expression getExpr() { 262 return _exp; 263 } 264 265 public String toString() { 266 return "pred(" + _exp + ')'; 267 } 268 269 280 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 281 Type texp = _exp.typeCheck(stable); 282 283 if (texp instanceof ReferenceType) { 285 _exp = new CastExpr(_exp, texp = Type.Real); 286 } 287 288 if (texp instanceof ResultTreeType) { 292 _exp = new CastExpr(_exp, Type.Boolean); 293 _exp = new CastExpr(_exp, Type.Real); 294 texp = _exp.typeCheck(stable); 295 } 296 297 if (texp instanceof NumberType) { 299 if (texp instanceof IntType == false) { 301 _exp = new CastExpr(_exp, Type.Int); 302 } 303 304 if (_canOptimize) { 305 _nthPositionFilter = 307 !_exp.hasLastCall() && !_exp.hasPositionCall(); 308 309 if (_nthPositionFilter) { 311 SyntaxTreeNode parent = getParent(); 312 _nthDescendant = (parent instanceof Step) && 313 (parent.getParent() instanceof AbsoluteLocationPath); 314 return _type = Type.NodeSet; 315 } 316 } 317 318 _nthPositionFilter = _nthDescendant = false; 320 321 final QName position = 323 getParser().getQNameIgnoreDefaultNs("position"); 324 final PositionCall positionCall = 325 new PositionCall(position); 326 positionCall.setParser(getParser()); 327 positionCall.setParent(this); 328 329 _exp = new EqualityExpr(EqualityExpr.EQ, positionCall, 330 _exp); 331 if (_exp.typeCheck(stable) != Type.Boolean) { 332 _exp = new CastExpr(_exp, Type.Boolean); 333 } 334 return _type = Type.Boolean; 335 } 336 else { 337 if (texp instanceof BooleanType == false) { 339 _exp = new CastExpr(_exp, Type.Boolean); 340 } 341 return _type = Type.Boolean; 342 } 343 } 344 345 351 private void compileFilter(ClassGenerator classGen, 352 MethodGenerator methodGen) { 353 TestGenerator testGen; 354 LocalVariableGen local; 355 FilterGenerator filterGen; 356 357 _className = getXSLTC().getHelperClassName(); 358 filterGen = new FilterGenerator(_className, 359 "java.lang.Object", 360 toString(), 361 ACC_PUBLIC | ACC_SUPER, 362 new String [] { 363 CURRENT_NODE_LIST_FILTER 364 }, 365 classGen.getStylesheet()); 366 367 final ConstantPoolGen cpg = filterGen.getConstantPool(); 368 final int length = (_closureVars == null) ? 0 : _closureVars.size(); 369 370 for (int i = 0; i < length; i++) { 372 VariableBase var = ((VariableRefBase) _closureVars.get(i)).getVariable(); 373 374 filterGen.addField(new Field(ACC_PUBLIC, 375 cpg.addUtf8(var.getEscapedName()), 376 cpg.addUtf8(var.getType().toSignature()), 377 null, cpg.getConstantPool())); 378 } 379 380 final InstructionList il = new InstructionList(); 381 testGen = new TestGenerator(ACC_PUBLIC | ACC_FINAL, 382 org.apache.bcel.generic.Type.BOOLEAN, 383 new org.apache.bcel.generic.Type[] { 384 org.apache.bcel.generic.Type.INT, 385 org.apache.bcel.generic.Type.INT, 386 org.apache.bcel.generic.Type.INT, 387 org.apache.bcel.generic.Type.INT, 388 Util.getJCRefType(TRANSLET_SIG), 389 Util.getJCRefType(NODE_ITERATOR_SIG) 390 }, 391 new String [] { 392 "node", 393 "position", 394 "last", 395 "current", 396 "translet", 397 "iterator" 398 }, 399 "test", _className, il, cpg); 400 401 local = testGen.addLocalVariable("document", 403 Util.getJCRefType(DOM_INTF_SIG), 404 null, null); 405 final String className = classGen.getClassName(); 406 il.append(filterGen.loadTranslet()); 407 il.append(new CHECKCAST(cpg.addClass(className))); 408 il.append(new GETFIELD(cpg.addFieldref(className, 409 DOM_FIELD, DOM_INTF_SIG))); 410 il.append(new ASTORE(local.getIndex())); 411 412 testGen.setDomIndex(local.getIndex()); 414 415 _exp.translate(filterGen, testGen); 416 il.append(IRETURN); 417 418 testGen.stripAttributes(true); 419 testGen.setMaxLocals(); 420 testGen.setMaxStack(); 421 testGen.removeNOPs(); 422 filterGen.addEmptyConstructor(ACC_PUBLIC); 423 filterGen.addMethod(testGen.getMethod()); 424 425 getXSLTC().dumpClass(filterGen.getJavaClass()); 426 } 427 428 433 public boolean isBooleanTest() { 434 return (_exp instanceof BooleanExpr); 435 } 436 437 442 public boolean isNodeValueTest() { 443 if (!_canOptimize) return false; 444 return (getStep() != null && getCompareValue() != null); 445 } 446 447 452 public Step getStep() { 453 if (_step != null) { 455 return _step; 456 } 457 458 if (_exp == null) { 460 return null; 461 } 462 463 if (_exp instanceof EqualityExpr) { 465 EqualityExpr exp = (EqualityExpr)_exp; 466 Expression left = exp.getLeft(); 467 Expression right = exp.getRight(); 468 469 if (left instanceof CastExpr) { 471 left = ((CastExpr) left).getExpr(); 472 } 473 if (left instanceof Step) { 474 _step = (Step) left; 475 } 476 477 if (right instanceof CastExpr) { 479 right = ((CastExpr)right).getExpr(); 480 } 481 if (right instanceof Step) { 482 _step = (Step)right; 483 } 484 } 485 return _step; 486 } 487 488 493 public Expression getCompareValue() { 494 if (_value != null) { 496 return _value; 497 } 498 499 if (_exp == null) { 501 return null; 502 } 503 504 if (_exp instanceof EqualityExpr) { 506 EqualityExpr exp = (EqualityExpr) _exp; 507 Expression left = exp.getLeft(); 508 Expression right = exp.getRight(); 509 510 if (left instanceof LiteralExpr) { 512 _value = left; 513 return _value; 514 } 515 if (left instanceof VariableRefBase && 517 left.getType() == Type.String) 518 { 519 _value = left; 520 return _value; 521 } 522 523 if (right instanceof LiteralExpr) { 525 _value = right; 526 return _value; 527 } 528 if (right instanceof VariableRefBase && 530 right.getType() == Type.String) 531 { 532 _value = right; 533 return _value; 534 } 535 } 536 return null; 537 } 538 539 544 public void translateFilter(ClassGenerator classGen, 545 MethodGenerator methodGen) 546 { 547 final ConstantPoolGen cpg = classGen.getConstantPool(); 548 final InstructionList il = methodGen.getInstructionList(); 549 550 compileFilter(classGen, methodGen); 552 553 il.append(new NEW(cpg.addClass(_className))); 555 il.append(DUP); 556 il.append(new INVOKESPECIAL(cpg.addMethodref(_className, 557 "<init>", "()V"))); 558 559 final int length = (_closureVars == null) ? 0 : _closureVars.size(); 561 562 for (int i = 0; i < length; i++) { 563 VariableRefBase varRef = (VariableRefBase) _closureVars.get(i); 564 VariableBase var = varRef.getVariable(); 565 Type varType = var.getType(); 566 567 il.append(DUP); 568 569 Closure variableClosure = _parentClosure; 571 while (variableClosure != null) { 572 if (variableClosure.inInnerClass()) break; 573 variableClosure = variableClosure.getParentClosure(); 574 } 575 576 if (variableClosure != null) { 578 il.append(ALOAD_0); 579 il.append(new GETFIELD( 580 cpg.addFieldref(variableClosure.getInnerClassName(), 581 var.getEscapedName(), varType.toSignature()))); 582 } 583 else { 584 il.append(var.loadInstruction()); 586 } 587 588 il.append(new PUTFIELD( 590 cpg.addFieldref(_className, var.getEscapedName(), 591 varType.toSignature()))); 592 } 593 } 594 595 601 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 602 603 final ConstantPoolGen cpg = classGen.getConstantPool(); 604 final InstructionList il = methodGen.getInstructionList(); 605 606 if (_nthPositionFilter || _nthDescendant) { 607 _exp.translate(classGen, methodGen); 608 } 609 else if (isNodeValueTest() && (getParent() instanceof Step)) { 610 _value.translate(classGen, methodGen); 611 il.append(new CHECKCAST(cpg.addClass(STRING_CLASS))); 612 il.append(new PUSH(cpg, ((EqualityExpr)_exp).getOp())); 613 } 614 else { 615 translateFilter(classGen, methodGen); 616 } 617 } 618 } 619 | Popular Tags |