001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: If.java 468650 2006-10-28 07:03:30Z minchau $ 020 */ 021 022 package org.apache.xalan.xsltc.compiler; 023 024 import org.apache.bcel.generic.InstructionHandle; 025 import org.apache.bcel.generic.InstructionList; 026 import org.apache.xalan.xsltc.compiler.util.BooleanType; 027 import org.apache.xalan.xsltc.compiler.util.ClassGenerator; 028 import org.apache.xalan.xsltc.compiler.util.ErrorMsg; 029 import org.apache.xalan.xsltc.compiler.util.MethodGenerator; 030 import org.apache.xalan.xsltc.compiler.util.Type; 031 import org.apache.xalan.xsltc.compiler.util.TypeCheckError; 032 import org.apache.xalan.xsltc.compiler.util.Util; 033 034 /** 035 * @author Jacek Ambroziak 036 * @author Santiago Pericas-Geertsen 037 * @author Morten Jorgensen 038 */ 039 final class If extends Instruction { 040 041 private Expression _test; 042 private boolean _ignore = false; 043 044 /** 045 * Display the contents of this element 046 */ 047 public void display(int indent) { 048 indent(indent); 049 Util.println("If"); 050 indent(indent + IndentIncrement); 051 System.out.print("test "); 052 Util.println(_test.toString()); 053 displayContents(indent + IndentIncrement); 054 } 055 056 /** 057 * Parse the "test" expression and contents of this element. 058 */ 059 public void parseContents(Parser parser) { 060 // Parse the "test" expression 061 _test = parser.parseExpression(this, "test", null); 062 063 // Make sure required attribute(s) have been set 064 if (_test.isDummy()) { 065 reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "test"); 066 return; 067 } 068 069 // Ignore xsl:if when test is false (function-available() and 070 // element-available()) 071 Object result = _test.evaluateAtCompileTime(); 072 if (result != null && result instanceof Boolean) { 073 _ignore = !((Boolean) result).booleanValue(); 074 } 075 076 parseChildren(parser); 077 } 078 079 /** 080 * Type-check the "test" expression and contents of this element. 081 * The contents will be ignored if we know the test will always fail. 082 */ 083 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 084 // Type-check the "test" expression 085 if (_test.typeCheck(stable) instanceof BooleanType == false) { 086 _test = new CastExpr(_test, Type.Boolean); 087 } 088 // Type check the element contents 089 if (!_ignore) { 090 typeCheckContents(stable); 091 } 092 return Type.Void; 093 } 094 095 /** 096 * Translate the "test" expression and contents of this element. 097 * The contents will be ignored if we know the test will always fail. 098 */ 099 public void translate(ClassGenerator classGen, MethodGenerator methodGen) { 100 final InstructionList il = methodGen.getInstructionList(); 101 _test.translateDesynthesized(classGen, methodGen); 102 // remember end of condition 103 final InstructionHandle truec = il.getEnd(); 104 if (!_ignore) { 105 translateContents(classGen, methodGen); 106 } 107 _test.backPatchFalseList(il.append(NOP)); 108 _test.backPatchTrueList(truec.getNext()); 109 } 110 }