gnu.jel.OPbinary Maven / Gradle / Ivy
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* $Id: OPbinary.java 490 2006-10-01 16:08:04Z metlov $
*
* This file is part of the Java Expressions Library (JEL).
* For more information about JEL visit :
* http://kinetic.ac.donetsk.ua/JEL/
*
* (c) 1998 -- 2007 by Konstantin Metlov([email protected]);
*
* JEL is Distributed under the terms of GNU General Public License.
* This code comes with ABSOLUTELY NO WARRANTY.
* For license details see COPYING file in this directory.
*/
package gnu.jel;
import gnu.jel.debug.Debug;
import java.util.Stack;
/**
* A tree node, representing binary operation.
*/
public class OPbinary extends OP {
/** code of this operation */
public int code;
/** index into ops array to get code for this op. */
private int opsIDX;
// Names of binary operations by ID in the readable form.
private final static String[] opNames;
/** binary promotions of base types */
protected final static byte[][] promotions;
// code chunks to implement the ops
private final static int[][] ops;
// type of operands promotion by the opcode
private static final byte[] promotionTypes;
static {
promotions=(byte[][])TableKeeper.getTable("promotions");
ops=(int[][])TableKeeper.getTable("ops");
promotionTypes=(byte[])TableKeeper.getTable("promotionTypes");
opNames=(String[])TableKeeper.getTable("binOpNames");
};
/**
* Constructs a new binary operation.
* Codes are following:
*
* 0 -- addition
* 1 -- substraction
* 2 -- multiplication
* 3 -- division
* 4 -- remainder
* 5 -- bitwise AND
* 6 -- bitwise OR
* 7 -- bitwise and logical XOR
* 8 -- comparizon for equality
* 9 -- comparizon for non-equality
* 10 -- comparizon for "less" <
* 11 -- comparizon for "greater or equal" >=
* 12 -- comparizon for "greater" >
* 13 -- comparizon for "less or equal" <=
* 14 -- bitwise left shift <<
* 15 -- bitwise right signed shift >>
* 16 -- bitwise right unsigned shift >>>
* 17 -- logical conjunction operator (AND)
* 18 -- logical disjunction operator (OR)
* 19 -- array element access operation
* 20 -- reserved (used internally for string concatenation)
*
* @param paramOPs stack holding the operands
* @param opcode is the operation code
*/
public OPbinary(Stack paramOPs, int opcode) throws CompilationException {
if (Debug.enabled)
Debug.check((opcode>=0) && (opcode=8) || (c2ID>=8)) {
// the only way the objects appear in this context
// are the comparisons
if (Debug.enabled) {
Debug.check((code>=8)||(code<=13),
"only comparisons and concatenation binops can "+
"operate on objects.");
Debug.check(c1ID!=10, "No TSB in this context 1");
Debug.check(c1ID!=10, "No TSB in this context 2");
};
// only string literal comparisons are interpreted
if ((c1ID!=11) || (c2ID!=11))
throw new Exception();
// compare the strings
int res=CompiledExpression.compare((String)c1w,(String)c2w);
c1w=((0x3172A>>>(3*(code-8)))&((res>0)?1:((res<0)?4:2)))>0
?Boolean.TRUE:Boolean.FALSE;
} else { // binary on primitive types
// Widen
Number n1=widen(c1w,c1ID);
Number n2=widen(c2w,c2ID);
// Perform
boolean boolres=false;
boolean resbool=false;
if ((opsIDX>=6) && (opsIDX<=7)) { // operations on floating point
double d1=n1.doubleValue(),d2=n2.doubleValue();
boolean wrop=false;
switch (code) {
case 0 : d1=d1+d2; break; //PL
case 1 : d1=d1-d2; break; //MI
case 2 : d1=d1*d2; break; //MU
case 3 : d1=d1/d2; break; //DI
case 4 : d1=d1%d2; break; //RE
case 5 : wrop=true;break; //AN
case 6 : wrop=true;break; //OR
case 7 : wrop=true;break; //XO
case 8 : boolres=true; resbool=(d1==d2); break; //EQ
case 9 : boolres=true; resbool=(d1!=d2); break; //NE
case 10: boolres=true; resbool=(d1=d2); break; //GE
case 12: boolres=true; resbool=(d1>d2); break; //GT
case 13: boolres=true; resbool=(d1<=d2); break; //LE
default :
wrop=true;
};
if (Debug.enabled && wrop)
Debug.println("Wrong operation on float ("+code+").");
if (!boolres) n1=new Double(d1);
else { // booleans are represented by longs temporarily
if (resbool) n1=new Long(1L); else n1=new Long(0);
};
} else { // operations on integers
long l1=n1.longValue(),l2=n2.longValue();
switch (code) {
case 0: l1=l1+l2;break; //PL
case 1: l1=l1-l2;break; //MI
case 2: l1=l1*l2; break; //MU
case 3: l1=l1/l2; break; //DI
case 4: l1=l1%l2; break; //RE
case 17:
case 5: l1=l1&l2; break; //AN
case 18:
case 6: l1=l1|l2; break; //OR
case 7: l1=l1^l2; break; //XO
case 8 : boolres=true; l1=(l1==l2?1L:0L); break; //EQ
case 9 : boolres=true; l1=(l1!=l2?1L:0L); break; //NE
case 10: boolres=true; l1=(l1< l2?1L:0L); break; //LT
case 11: boolres=true; l1=(l1>=l2?1L:0L); break; //GE
case 12: boolres=true; l1=(l1> l2?1L:0L); break; //GT
case 13: boolres=true; l1=(l1<=l2?1L:0L); break; //LE
case 14: l1=l1<>l2; break; // RS
case 16: { // for this kind of shifts the bit width of variable is
// important
if (resID==4) //=because there is unary numeric promotion before op
l1=(int)l1>>>l2;
else
l1=l1>>>l2;
break;
} // RUS
default :
if (Debug.enabled)
Debug.println("Wrong operation on integer ("+code+").");
};
n1=new Long(l1);
};
// Narrow
if (boolres) {
c1w=narrow(n1,0);
} else c1w=narrow(n1,resID);
};
return c1w;
} catch (Exception thr) {
// if can't evaluate -- replace operands at least
if (!ep1)
chi[0]=new OPload(chi[0],c1w);
if (!ep2)
chi[1]=new OPload(chi[1],c2w);
throw thr;
// Debug.reportThrowable(thr);
// IGNORE
}
};
};
© 2015 - 2024 Weber Informatics LLC | Privacy Policy