1. /*
  2. * Copyright 2001-2004 The Apache Software Foundation.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. /*
  17. * $Id: BinOpExpr.java,v 1.11 2004/02/16 22:24:29 minchau Exp $
  18. */
  19. package com.sun.org.apache.xalan.internal.xsltc.compiler;
  20. import com.sun.org.apache.bcel.internal.generic.InstructionList;
  21. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator;
  22. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg;
  23. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator;
  24. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodType;
  25. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type;
  26. import com.sun.org.apache.xalan.internal.xsltc.compiler.util.TypeCheckError;
  27. /**
  28. * @author Jacek Ambroziak
  29. * @author Santiago Pericas-Geertsen
  30. */
  31. final class BinOpExpr extends Expression {
  32. public static final int PLUS = 0;
  33. public static final int MINUS = 1;
  34. public static final int TIMES = 2;
  35. public static final int DIV = 3;
  36. public static final int MOD = 4;
  37. private static final String[] Ops = {
  38. "+", "-", "*", "/", "%"
  39. };
  40. private int _op;
  41. private Expression _left, _right;
  42. public BinOpExpr(int op, Expression left, Expression right) {
  43. _op = op;
  44. (_left = left).setParent(this);
  45. (_right = right).setParent(this);
  46. }
  47. /**
  48. * Returns true if this expressions contains a call to position(). This is
  49. * needed for context changes in node steps containing multiple predicates.
  50. */
  51. public boolean hasPositionCall() {
  52. if (_left.hasPositionCall()) return true;
  53. if (_right.hasPositionCall()) return true;
  54. return false;
  55. }
  56. /**
  57. * Returns true if this expressions contains a call to last()
  58. */
  59. public boolean hasLastCall() {
  60. return (_left.hasLastCall() || _right.hasLastCall());
  61. }
  62. public void setParser(Parser parser) {
  63. super.setParser(parser);
  64. _left.setParser(parser);
  65. _right.setParser(parser);
  66. }
  67. public Type typeCheck(SymbolTable stable) throws TypeCheckError {
  68. final Type tleft = _left.typeCheck(stable);
  69. final Type tright = _right.typeCheck(stable);
  70. final MethodType ptype = lookupPrimop(stable, Ops[_op],
  71. new MethodType(Type.Void,
  72. tleft, tright));
  73. if (ptype != null) {
  74. final Type arg1 = (Type) ptype.argsType().elementAt(0);
  75. if (!arg1.identicalTo(tleft)) {
  76. _left = new CastExpr(_left, arg1);
  77. }
  78. final Type arg2 = (Type) ptype.argsType().elementAt(1);
  79. if (!arg2.identicalTo(tright)) {
  80. _right = new CastExpr(_right, arg1);
  81. }
  82. return _type = ptype.resultType();
  83. }
  84. throw new TypeCheckError(this);
  85. }
  86. public void translate(ClassGenerator classGen, MethodGenerator methodGen) {
  87. final InstructionList il = methodGen.getInstructionList();
  88. _left.translate(classGen, methodGen);
  89. _right.translate(classGen, methodGen);
  90. switch (_op) {
  91. case PLUS:
  92. il.append(_type.ADD());
  93. break;
  94. case MINUS:
  95. il.append(_type.SUB());
  96. break;
  97. case TIMES:
  98. il.append(_type.MUL());
  99. break;
  100. case DIV:
  101. il.append(_type.DIV());
  102. break;
  103. case MOD:
  104. il.append(_type.REM());
  105. break;
  106. default:
  107. ErrorMsg msg = new ErrorMsg(ErrorMsg.ILLEGAL_BINARY_OP_ERR, this);
  108. getParser().reportError(Constants.ERROR, msg);
  109. }
  110. }
  111. public String toString() {
  112. return Ops[_op] + '(' + _left + ", " + _right + ')';
  113. }
  114. }