001: package gnu.expr;
002:
003: import gnu.bytecode.*;
004:
005: /**
006: * Pre/post incrementation of a local variable.
007: *
008: * @author Daniel Bonniot (bonniot@users.sf.net)
009: */
010:
011: public class IncrementExp extends Expression {
012: /**
013: Increment variable <code>decl</code> by <code>increment<code>,
014: and return its value.
015:
016: The generated code is optimised.
017: For instance, the returned value is not pushed if it is not used.
018:
019: @return the value of <code>decl</code>
020: after incrementation if <code>pre</code> is true (i.e. ++x);
021: the old value if if <code>pre</code> is false (i.e. x++)
022: */
023: public IncrementExp(Declaration decl, short increment, boolean pre) {
024: this .decl = decl;
025: this .increment = increment;
026: this .pre = pre;
027: }
028:
029: Declaration decl;
030: private short increment;
031: private boolean pre;
032:
033: public void compile(Compilation comp, Target target) {
034: CodeAttr code = comp.getCode();
035: boolean needValue = !(target instanceof IgnoreTarget);
036:
037: if (decl.isSimple()) {
038: Variable var = decl.getVariable();
039:
040: if (!pre && needValue)
041: code.emitLoad(var);
042:
043: if (var.getType() == Type.int_type)
044: code.emitInc(var, increment);
045: else
046: // The variable has a non-int type, but we know it must be
047: // convertible to int.
048: {
049: PrimType type = var.getType() == Type.long_ctype ? Type.long_type
050: : Type.int_type;
051:
052: code.emitLoad(var);
053: StackTarget.getInstance(type).compileFromStack(comp,
054: var.getType());
055: code.emitPushConstant(increment, type);
056: code.emitAdd(type);
057: StackTarget.getInstance(var.getType())
058: .compileFromStack(comp, type);
059: code.emitStore(var);
060: }
061:
062: if (pre && needValue)
063: code.emitLoad(var);
064: } else {
065: Field field = decl.field;
066: boolean isStatic = field.getStaticFlag();
067:
068: if (isStatic)
069: code.emitGetStatic(field);
070: else {
071: decl.loadOwningObject(comp);
072: code.emitDup();
073: code.emitGetField(field);
074: }
075:
076: boolean isLong = field.getType().getSize() > 4;
077: PrimType type = isLong ? Type.long_type : Type.int_type;
078:
079: if (!pre && needValue)
080: if (isStatic)
081: code.emitDup();
082: else
083: code.emitDupX();
084:
085: if (isLong)
086: code.emitPushLong(increment);
087: else
088: code.emitPushInt(increment);
089: code.emitAdd(type);
090:
091: if (pre && needValue)
092: if (isStatic)
093: code.emitDup();
094: else
095: code.emitDupX();
096:
097: if (isStatic)
098: code.emitPutStatic(field);
099: else
100: code.emitPutField(field);
101: }
102:
103: if (needValue)
104: target.compileFromStack(comp, getType());
105: }
106:
107: public Type getType() {
108: return decl.getType();
109: }
110:
111: protected Expression walk(ExpWalker w) {
112: return w.walkIncrementExp(this );
113: }
114:
115: public void print(gnu.mapping.OutPort out) {
116: out.startLogicalBlock("(Increment", ")", 2);
117: if (decl == null)
118: out.print("<null declaration>");
119: else
120: out.print(decl.getName());
121: out.endLogicalBlock(")");
122: }
123: }
|