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 comparison operators.
019:
020: @author Daniel Bonniot
021: */
022: public class CompOp extends Procedure2 implements Branchable,
023: bossa.syntax.Macro {
024: private final static int error = 0, Eq = 1, Ge = 2, Le = 3, Lt = 4,
025: Gt = 5, Ne = 6;
026:
027: public static CompOp create(String param) {
028: PrimType argType = Tools.numericType(param.charAt(0));
029: if (argType == null)
030: bossa.util.User
031: .error("Unknown type in inlined comparison operator: "
032: + param);
033:
034: param = param.substring(1);
035:
036: int kind = error;
037: if ("Eq".equals(param))
038: kind = Eq;
039: else if ("Ge".equals(param))
040: kind = Ge;
041: else if ("Le".equals(param))
042: kind = Le;
043: else if ("Lt".equals(param))
044: kind = Lt;
045: else if ("Gt".equals(param))
046: kind = Gt;
047: else if ("Ne".equals(param))
048: kind = Ne;
049: else
050: bossa.util.User.error("Unknown inlined numeric operator "
051: + param);
052: return new CompOp(kind, argType);
053: }
054:
055: private CompOp(int kind, PrimType argType) {
056: this .kind = kind;
057: this .argType = argType;
058: }
059:
060: private final int kind;
061:
062: public void compile(ApplyExp exp, Compilation comp, Target target) {
063: Expression[] args = exp.getArgs();
064: CodeAttr code = comp.getCode();
065: Target stack = new StackTarget(argType);
066:
067: args[0].compile(comp, stack);
068: args[1].compile(comp, stack);
069:
070: switch (kind) {
071: case Eq:
072: code.emitIfEq();
073: break;
074: case Le:
075: code.emitIfLe();
076: break;
077: case Ge:
078: code.emitIfGe();
079: break;
080: case Lt:
081: code.emitIfLt();
082: break;
083: case Gt:
084: code.emitIfGt();
085: break;
086: case Ne:
087: code.emitIfNEq();
088: break;
089: }
090:
091: code.emitPushBoolean(true);
092: code.emitElse();
093: code.emitPushBoolean(false);
094: code.emitFi();
095:
096: target.compileFromStack(comp, retType);
097: }
098:
099: /**
100: Jump to label <code>to</code> if the comparison is true.
101: */
102: public void compileJump(Compilation comp, Expression[] args,
103: Label to) {
104: CodeAttr code = comp.getCode();
105: Target stack = new StackTarget(argType);
106:
107: args[0].compile(comp, stack);
108: args[1].compile(comp, stack);
109:
110: switch (kind) {
111: case Eq:
112: code.emitGotoIfEq(to);
113: break;
114: case Le:
115: code.emitGotoIfLe(to);
116: break;
117: case Ge:
118: code.emitGotoIfGe(to);
119: break;
120: case Lt:
121: code.emitGotoIfLt(to);
122: break;
123: case Gt:
124: code.emitGotoIfGt(to);
125: break;
126: case Ne:
127: code.emitGotoIfNE(to);
128: break;
129: }
130: }
131:
132: /**
133: Jump to label <code>to</code> if the comparison is false.
134: */
135: public void compileJumpNot(Compilation comp, Expression[] args,
136: Label to) {
137: CodeAttr code = comp.getCode();
138: Target stack = new StackTarget(argType);
139:
140: args[0].compile(comp, stack);
141: args[1].compile(comp, stack);
142:
143: switch (kind) {
144: case Eq:
145: code.emitGotoIfNE(to);
146: break;
147: case Le:
148: code.emitGotoIfGt(to);
149: break;
150: case Ge:
151: code.emitGotoIfLt(to);
152: break;
153: case Lt:
154: code.emitGotoIfGe(to);
155: break;
156: case Gt:
157: code.emitGotoIfLe(to);
158: break;
159: case Ne:
160: code.emitGotoIfEq(to);
161: break;
162: }
163: }
164:
165: private final PrimType argType;
166: private final Type retType = Type.boolean_type;
167:
168: public Type getReturnType(Expression[] args) {
169: return retType;
170: }
171:
172: public void checkSpecialRequirements(
173: bossa.syntax.Expression[] arguments) {
174: /* TODO: make this work again
175: bossa.syntax.ConstantExp literalexp = null;
176: bossa.syntax.Expression otherexp = null;
177: if (arguments[0] instanceof bossa.syntax.ConstantExp &&
178: ! (arguments[1] instanceof bossa.syntax.ConstantExp))
179: {
180: literalexp = (bossa.syntax.ConstantExp)arguments[0];
181: otherexp = arguments[1];
182: }
183: else if (arguments[1] instanceof bossa.syntax.ConstantExp &&
184: ! (arguments[0] instanceof bossa.syntax.ConstantExp))
185: {
186: literalexp = (bossa.syntax.ConstantExp)arguments[1];
187: otherexp = arguments[0];
188: }
189:
190: if (literalexp != null)
191: {
192: mlsub.typing.TypeConstructor tc = nice.tools.typing.Types.equivalent(otherexp.getType().getMonotype()).head();
193: if (mlsub.typing.Typing.testRigidLeq(tc, literalexp.tc) &&
194: ! (mlsub.typing.Typing.testRigidLeq(literalexp.tc, tc)))
195: bossa.util.User.warning(otherexp, "Comparing a value with a constant outside the range of that value");
196: }
197: */
198: }
199:
200: // Interpretation
201:
202: public Object apply2(Object arg1, Object arg2) {
203: throw new Error("Not implemented");
204: }
205: }
|