1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Licensed to the Apache Software Foundation (ASF) under one or more
   7  * contributor license agreements.  See the NOTICE file distributed with
   8  * this work for additional information regarding copyright ownership.
   9  * The ASF licenses this file to You under the Apache License, Version 2.0
  10  * (the "License"); you may not use this file except in compliance with
  11  * the License.  You may obtain a copy of the License at
  12  *
  13  *      http://www.apache.org/licenses/LICENSE-2.0
  14  *
  15  * Unless required by applicable law or agreed to in writing, software
  16  * distributed under the License is distributed on an "AS IS" BASIS,
  17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  18  * See the License for the specific language governing permissions and
  19  * limitations under the License.
  20  */
  21 
  22 package com.sun.org.apache.xalan.internal.xsltc.compiler;
  23 
  24 import com.sun.org.apache.bcel.internal.generic.InstructionHandle;
  25 import com.sun.org.apache.bcel.internal.generic.InstructionList;
  26 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.BooleanType;
  27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  30 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  31 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  32 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util;
  33 
  34 /**
  35  * @author Jacek Ambroziak
  36  * @author Santiago Pericas-Geertsen
  37  * @author Morten Jorgensen
  38  */
  39 final class If extends Instruction {
  40 
  41     private Expression _test;
  42     private boolean    _ignore = false;
  43 
  44     /**
  45      * Display the contents of this element
  46      */
  47     public void display(int indent) {
  48         indent(indent);
  49         Util.println("If");
  50         indent(indent + IndentIncrement);
  51         System.out.print("test ");
  52         Util.println(_test.toString());
  53         displayContents(indent + IndentIncrement);
  54     }
  55 
  56     /**
  57      * Parse the "test" expression and contents of this element.
  58      */
  59     public void parseContents(Parser parser) {
  60         // Parse the "test" expression
  61         _test = parser.parseExpression(this, "test", null);
  62 
  63         // Make sure required attribute(s) have been set
  64         if (_test.isDummy()) {
  65             reportError(this, parser, ErrorMsg.REQUIRED_ATTR_ERR, "test");
  66             return;
  67         }
  68 
  69         // Ignore xsl:if when test is false (function-available() and
  70         // element-available())
  71         Object result = _test.evaluateAtCompileTime();
  72         if (result != null && result instanceof Boolean) {
  73             _ignore = !((Boolean) result).booleanValue();
  74         }
  75 
  76         parseChildren(parser);
  77     }
  78 
  79     /**
  80      * Type-check the "test" expression and contents of this element.
  81      * The contents will be ignored if we know the test will always fail.
  82      */
  83     public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  84         // Type-check the "test" expression
  85         if (_test.typeCheck(stable) instanceof BooleanType == false) {
  86             _test = new CastExpr(_test, Type.Boolean);
  87         }
  88         // Type check the element contents
  89         if (!_ignore) {
  90             typeCheckContents(stable);
  91         }
  92         return Type.Void;
  93     }
  94 
  95     /**
  96      * Translate the "test" expression and contents of this element.
  97      * The contents will be ignored if we know the test will always fail.
  98      */
  99     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 }