001: /**************************************************************************/
002: /* N I C E */
003: /* A high-level object-oriented research language */
004: /* (c) Daniel Bonniot 2003 */
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: /**
014: Bit manipulation for numeric values.
015:
016: @version $Date: 2003/12/08 13:45:21 $
017: @author Daniel Bonniot (bonniot@users.sourceforge.net)
018: */
019:
020: import gnu.mapping.Procedure;
021: import gnu.mapping.Procedure2;
022: import gnu.mapping.Procedure3;
023: import gnu.expr.*;
024: import gnu.bytecode.*;
025:
026: public class BitOp {
027: public static Procedure create(String param) {
028: if (param.equals("get"))
029: return get;
030: else
031: return set;
032: }
033:
034: private static BitOp.Set set = new BitOp.Set();
035: private static BitOp.Get get = new BitOp.Get();
036:
037: // Getting a bit
038: private static class Get extends Procedure2 implements Branchable {
039: public void compile(ApplyExp exp, Compilation comp,
040: Target target) {
041: Expression[] args = exp.getArgs();
042: CodeAttr code = comp.getCode();
043:
044: Type type0 = args[0].getType();
045: boolean isLong = type0 == Type.long_type;
046:
047: Target t0 = Target.pushValue(type0);
048: args[0].compile(comp, t0);
049:
050: if (isLong)
051: code.emitPushLong(1);
052: else
053: code.emitPushInt(1);
054:
055: Target t1 = Target.pushValue(Type.int_type);
056: args[1].compile(comp, t1);
057:
058: code.emitShl();
059:
060: // This is needed for types shorter than int.
061: if (!isLong)
062: t0.compileFromStack(comp, Type.int_type);
063:
064: code.emitAnd();
065:
066: if (isLong) {
067: code.emitPushLong(0);
068: code.emitIfEq();
069: code.emitPushBoolean(false);
070: code.emitElse();
071: code.emitPushBoolean(true);
072: code.emitFi();
073: } else {
074: code.emitIfIntNotZero();
075: code.emitPushBoolean(true);
076: code.emitElse();
077: code.emitPushBoolean(false);
078: code.emitFi();
079: }
080:
081: target.compileFromStack(comp, Type.boolean_type);
082: }
083:
084: public void compileJump(Compilation comp, Expression[] args,
085: Label to) {
086: CodeAttr code = comp.getCode();
087:
088: Type type0 = args[0].getType();
089: boolean isLong = type0 == Type.long_type;
090:
091: Target t0 = Target.pushValue(type0);
092: args[0].compile(comp, t0);
093:
094: if (isLong)
095: code.emitPushLong(1);
096: else
097: code.emitPushInt(1);
098:
099: Target t1 = Target.pushValue(Type.int_type);
100: args[1].compile(comp, t1);
101:
102: code.emitShl();
103:
104: // This is needed for types shorter than int.
105: if (!isLong)
106: t0.compileFromStack(comp, Type.int_type);
107:
108: code.emitAnd();
109: if (isLong) {
110: code.emitPushLong(0);
111: code.emitGotoIfNE(to);
112: } else {
113: code.emitGotoIfIntNeZero(to);
114: }
115: }
116:
117: public void compileJumpNot(Compilation comp, Expression[] args,
118: Label to) {
119: CodeAttr code = comp.getCode();
120:
121: Type type0 = args[0].getType();
122: boolean isLong = type0 == Type.long_type;
123:
124: Target t0 = Target.pushValue(type0);
125: args[0].compile(comp, t0);
126:
127: if (isLong)
128: code.emitPushLong(1);
129: else
130: code.emitPushInt(1);
131:
132: Target t1 = Target.pushValue(Type.int_type);
133: args[1].compile(comp, t1);
134:
135: code.emitShl();
136:
137: // This is needed for types shorter than int.
138: if (!isLong)
139: t0.compileFromStack(comp, Type.int_type);
140:
141: code.emitAnd();
142: if (isLong) {
143: code.emitPushLong(0);
144: code.emitGotoIfEq(to);
145: } else {
146: code.emitGotoIfIntEqZero(to);
147: }
148: }
149:
150: public Type getReturnType(Expression[] args) {
151: return Type.boolean_type;
152: }
153:
154: // Interpretation
155:
156: public Object apply2(Object arg1, Object arg2) {
157: throw new Error("Not implemented");
158: }
159: }
160:
161: // Setting a bit
162: private static class Set extends Procedure3 implements
163: bossa.syntax.Macro {
164: public void compile(ApplyExp exp, Compilation comp,
165: Target target) {
166: Expression[] args = exp.getArgs();
167: CodeAttr code = comp.getCode();
168:
169: Type type0 = args[0].getType();
170: boolean isLong = type0 == Type.long_type;
171:
172: Target t0 = Target.pushValue(type0);
173: args[0].compile(comp, t0);
174:
175: if (isLong)
176: code.emitPushLong(1);
177: else
178: code.emitPushInt(1);
179:
180: Target t1 = Target.pushValue(Type.int_type);
181: args[1].compile(comp, t1);
182:
183: code.emitShl();
184:
185: args[2].compile(comp, Target.pushValue(Type.boolean_type));
186:
187: code.emitIfIntNotZero();
188:
189: code.emitIOr();
190:
191: code.emitElse();
192:
193: if (isLong)
194: code.emitPushLong(-1);
195: else
196: code.emitPushInt(-1);
197: code.emitXOr();
198: code.emitAnd();
199:
200: code.emitFi();
201:
202: t0.compileFromStack(comp, isLong ? Type.long_type
203: : Type.int_type);
204:
205: nice.tools.code.Gen.store(comp, args[0], target);
206: }
207:
208: public Type getReturnType(Expression[] args) {
209: return Type.void_type;
210: }
211:
212: public void checkSpecialRequirements(
213: bossa.syntax.Expression[] arguments) {
214: if (!arguments[0].isAssignable())
215: bossa.util.User.error(arguments[0],
216: "This value cannot be modified.");
217: }
218:
219: // Interpretation
220:
221: public Object apply3(Object arg1, Object arg2, Object arg3) {
222: throw new Error("Not implemented");
223: }
224: }
225: }
|