1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4 /* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21 package com.sun.org.apache.xalan.internal.xsltc.compiler; 22 23 import com.sun.org.apache.bcel.internal.generic.InstructionList; 24 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; 25 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; 26 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; 27 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType; 28 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; 29 import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError; 30 31 /** 32 * @author Jacek Ambroziak 33 * @author Santiago Pericas-Geertsen 34 * @LastModified: Nov 2017 35 */ 36 final class BinOpExpr extends Expression { 37 public static final int PLUS = 0; 38 public static final int MINUS = 1; 39 public static final int TIMES = 2; 40 public static final int DIV = 3; 41 public static final int MOD = 4; 42 43 private static final String[] Ops = { 44 "+", "-", "*", "/", "%" 45 }; 46 47 private int _op; 48 private Expression _left, _right; 49 50 public BinOpExpr(int op, Expression left, Expression right) { 51 _op = op; 52 (_left = left).setParent(this); 53 (_right = right).setParent(this); 54 } 55 56 /** 57 * Returns true if this expressions contains a call to position(). This is 58 * needed for context changes in node steps containing multiple predicates. 59 */ 60 public boolean hasPositionCall() { 61 if (_left.hasPositionCall()) return true; 62 if (_right.hasPositionCall()) return true; 63 return false; 64 } 65 66 /** 67 * Returns true if this expressions contains a call to last() 68 */ 69 public boolean hasLastCall() { 70 return (_left.hasLastCall() || _right.hasLastCall()); 71 } 72 73 public void setParser(Parser parser) { 74 super.setParser(parser); 75 _left.setParser(parser); 76 _right.setParser(parser); 77 } 78 79 public Type typeCheck(SymbolTable stable) throws TypeCheckError { 80 final Type tleft = _left.typeCheck(stable); 81 final Type tright = _right.typeCheck(stable); 82 final MethodType ptype = lookupPrimop(stable, Ops[_op], 83 new MethodType(Type.Void, 84 tleft, tright)); 85 if (ptype != null) { 86 final Type arg1 = ptype.argsType().get(0); 87 if (!arg1.identicalTo(tleft)) { 88 _left = new CastExpr(_left, arg1); 89 } 90 final Type arg2 = ptype.argsType().get(1); 91 if (!arg2.identicalTo(tright)) { 92 _right = new CastExpr(_right, arg1); 93 } 94 return _type = ptype.resultType(); 95 } 96 throw new TypeCheckError(this); 97 } 98 99 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 }