001: /**************************************************************************/
002: /* N I C E */
003: /* A simple imperative object-oriented research language */
004: /* (c) Daniel Bonniot 2000 */
005: /* */
006: /* This program is free software; you can redistribute it and/or modify */
007: /* it under the terms of the GNU General Public License as published by */
008: /* the Free Software Foundation; either version 2 of the License, or */
009: /* (at your option) any later version. */
010: /* */
011: /**************************************************************************/package nice.lang.inline;
012:
013: import gnu.mapping.Procedure2;
014: import gnu.expr.*;
015: import gnu.bytecode.*;
016:
017: /**
018: Inlining of native numeric types operators.
019:
020: @version $Date: 2003/06/17 12:16:16 $
021: @author Daniel Bonniot
022: */
023: public class NumOp extends Procedure2 implements Inlineable {
024: private final static int error = 0, Sub = 1, Add = 2, Mul = 3,
025: Div = 4, Rem = 5, // remainder (modulus)
026: And = 7, IOr = 8, XOr = 9, Shl = 10, // left shift (<<)
027: Shr = 11, // right shift (>>)
028: uShr = 12; // unsigned right shift (>>>)
029:
030: public static NumOp create(String param) {
031: PrimType type = Tools.numericType(param.charAt(0));
032: if (type == null)
033: bossa.util.User
034: .error("Unknown type in inlined numeric operator: "
035: + param);
036:
037: param = param.substring(1);
038:
039: int kind = error;
040: if ("Sub".equals(param))
041: kind = Sub;
042: else if ("Add".equals(param))
043: kind = Add;
044: else if ("Mul".equals(param))
045: kind = Mul;
046: else if ("Div".equals(param))
047: kind = Div;
048: else if ("Rem".equals(param))
049: kind = Rem;
050: else if ("And".equals(param))
051: kind = And;
052: else if ("IOr".equals(param))
053: kind = IOr;
054: else if ("XOr".equals(param))
055: kind = XOr;
056: else if ("Shl".equals(param))
057: kind = Shl;
058: else if ("Shr".equals(param))
059: kind = Shr;
060: else if ("uShr".equals(param))
061: kind = uShr;
062: else
063: bossa.util.User.error("Unknown inlined numeric operator "
064: + param);
065: return new NumOp(kind, type);
066: }
067:
068: private NumOp(int kind, PrimType type) {
069: this .kind = kind;
070: this .type = type;
071: }
072:
073: private final PrimType type;
074: private final int kind;
075:
076: public void compile(ApplyExp exp, Compilation comp, Target target) {
077: Expression[] args = exp.getArgs();
078: CodeAttr code = comp.getCode();
079: Target stack = new StackTarget(type);
080: args[0].compile(comp, stack);
081:
082: if (kind >= Shl && kind <= uShr) {
083: args[1].compile(comp, Tools.intTarget);
084:
085: switch (kind) {
086: case Shl:
087: code.emitShl();
088: break;
089: case Shr:
090: code.emitShr();
091: break;
092: case uShr:
093: code.emitUshr();
094: break;
095: }
096: } else {
097: args[1].compile(comp, stack);
098:
099: switch (kind) {
100: case Sub:
101: code.emitSub(type);
102: break;
103: case Add:
104: code.emitAdd(type);
105: break;
106: case Mul:
107: code.emitMul();
108: break;
109: case Div:
110: code.emitDiv();
111: break;
112: case Rem:
113: code.emitRem();
114: break;
115: case And:
116: code.emitAnd();
117: break;
118: case IOr:
119: code.emitIOr();
120: break;
121: case XOr:
122: code.emitXOr();
123: break;
124: }
125: }
126:
127: target.compileFromStack(comp, type);
128: }
129:
130: public Type getReturnType(Expression[] args) {
131: return type;
132: }
133:
134: // Interpretation
135:
136: public Object apply2(Object arg1, Object arg2) {
137: throw new Error("Not implemented");
138: }
139: }
|