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: BinOpExpr.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.InstructionList;
025 import org.apache.xalan.xsltc.compiler.util.ClassGenerator;
026 import org.apache.xalan.xsltc.compiler.util.ErrorMsg;
027 import org.apache.xalan.xsltc.compiler.util.MethodGenerator;
028 import org.apache.xalan.xsltc.compiler.util.MethodType;
029 import org.apache.xalan.xsltc.compiler.util.Type;
030 import org.apache.xalan.xsltc.compiler.util.TypeCheckError;
031
032 /**
033 * @author Jacek Ambroziak
034 * @author Santiago Pericas-Geertsen
035 */
036 final class BinOpExpr extends Expression {
037 public static final int PLUS = 0;
038 public static final int MINUS = 1;
039 public static final int TIMES = 2;
040 public static final int DIV = 3;
041 public static final int MOD = 4;
042
043 private static final String[] Ops = {
044 "+", "-", "*", "/", "%"
045 };
046
047 private int _op;
048 private Expression _left, _right;
049
050 public BinOpExpr(int op, Expression left, Expression right) {
051 _op = op;
052 (_left = left).setParent(this);
053 (_right = right).setParent(this);
054 }
055
056 /**
057 * Returns true if this expressions contains a call to position(). This is
058 * needed for context changes in node steps containing multiple predicates.
059 */
060 public boolean hasPositionCall() {
061 if (_left.hasPositionCall()) return true;
062 if (_right.hasPositionCall()) return true;
063 return false;
064 }
065
066 /**
067 * Returns true if this expressions contains a call to last()
068 */
069 public boolean hasLastCall() {
070 return (_left.hasLastCall() || _right.hasLastCall());
071 }
072
073 public void setParser(Parser parser) {
074 super.setParser(parser);
075 _left.setParser(parser);
076 _right.setParser(parser);
077 }
078
079 public Type typeCheck(SymbolTable stable) throws TypeCheckError {
080 final Type tleft = _left.typeCheck(stable);
081 final Type tright = _right.typeCheck(stable);
082 final MethodType ptype = lookupPrimop(stable, Ops[_op],
083 new MethodType(Type.Void,
084 tleft, tright));
085 if (ptype != null) {
086 final Type arg1 = (Type) ptype.argsType().elementAt(0);
087 if (!arg1.identicalTo(tleft)) {
088 _left = new CastExpr(_left, arg1);
089 }
090 final Type arg2 = (Type) ptype.argsType().elementAt(1);
091 if (!arg2.identicalTo(tright)) {
092 _right = new CastExpr(_right, arg1);
093 }
094 return _type = ptype.resultType();
095 }
096 throw new TypeCheckError(this);
097 }
098
099 public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
100 final InstructionList il = methodGen.getInstructionList();
101
102 _left.translate(classGen, methodGen);
103 _right.translate(classGen, methodGen);
104
105 switch (_op) {
106 case PLUS:
107 il.append(_type.ADD());
108 break;
109 case MINUS:
110 il.append(_type.SUB());
111 break;
112 case TIMES:
113 il.append(_type.MUL());
114 break;
115 case DIV:
116 il.append(_type.DIV());
117 break;
118 case MOD:
119 il.append(_type.REM());
120 break;
121 default:
122 ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_BINARY_OP_ERR, this);
123 getParser().reportError(Constants.ERROR, msg);
124 }
125 }
126
127 public String toString() {
128 return Ops[_op] + '(' + _left + ", " + _right + ')';
129 }
130 }