01: package gnu.kawa.functions;
02:
03: import gnu.math.*;
04: import gnu.mapping.*;
05: import gnu.expr.*;
06: import gnu.bytecode.*;
07:
08: /**
09: * Implement the Scheme standard function "/".
10: * @author Per Bothner
11: */
12:
13: public class DivideOp extends ProcedureN implements CanInline {
14: /** True if result shoudl be cast to integer.
15: * Basically a hack (that should be generalized) for XQuery's
16: * idiv operator. */
17: boolean asInteger;
18:
19: public static final DivideOp $Sl = new DivideOp("/");
20: public static final DivideOp idiv = new DivideOp("idiv");
21: static {
22: idiv.asInteger = true;
23: }
24:
25: public DivideOp(String name) {
26: super (name);
27: }
28:
29: public Object applyN(Object[] args) {
30: Numeric result;
31: int i = 0;
32: if (args.length == 1)
33: result = IntNum.one();
34: else
35: result = (Numeric) (args[i++]);
36: for (; i < args.length; i++)
37: result = result.div(args[i]);
38: if (asInteger)
39: result = ((RealNum) result).toExactInt(Numeric.TRUNCATE);
40: return result;
41: }
42:
43: public Expression inline(ApplyExp exp, ExpWalker walker) {
44: Expression folded = exp.inlineIfConstant(this , walker);
45: if (folded != exp)
46: return folded;
47: if (asInteger)
48: return exp;
49: Expression[] args = exp.getArgs();
50: if (args.length > 2)
51: return AddOp
52: .pairwise(this , exp.getFunction(), args, walker);
53: if (args.length == 2) {
54: Type type0 = args[0].getType();
55: Type type1 = args[1].getType();
56: int kind0 = AddOp.classify(type0);
57: int kind1 = AddOp.classify(type1);
58: if ((kind0 == 4 || type0.isSubtype(typeRatNum))
59: && (kind1 == 4 || type1.isSubtype(typeRatNum)))
60: return new ApplyExp(typeRatNum.getDeclaredMethod(
61: "divide", 2), args);
62: if (kind0 >= 3 && kind1 >= 3) {
63: Expression opt = AddOp.primInline(108, exp);
64: if (opt != exp)
65: return opt;
66: }
67: if (kind0 >= 2 && kind1 >= 2)
68: return new ApplyExp(AddOp.typeRealNum
69: .getDeclaredMethod("divide", 2), args);
70: }
71: return exp;
72: }
73:
74: static ClassType typeRatNum = ClassType.make("gnu.math.RatNum");
75: }
|