01: /**************************************************************************/
02: /* N I C E */
03: /* A simple imperative object-oriented research language */
04: /* (c) Daniel Bonniot 1999 */
05: /* */
06: /* This program is free software; you can redistribute it and/or modify */
07: /* it under the terms of the GNU General Public License as published by */
08: /* the Free Software Foundation; either version 2 of the License, or */
09: /* (at your option) any later version. */
10: /* */
11: /**************************************************************************/package nice.tools.code;
12:
13: import gnu.expr.*;
14: import gnu.bytecode.*;
15:
16: /**
17: Increment the value of an object field.
18: Returns either the old or the new value.
19:
20: @author Daniel Bonniot
21: */
22:
23: public class IncrementProc extends gnu.mapping.Procedure1 implements
24: Inlineable {
25: /**
26: @param field the field to increment or decrement.
27: @param increment true to increment, false to decrement
28: @param returnOld if true, return value before modification,
29: otherwise value after modification
30: */
31: public IncrementProc(Declaration field, boolean returnOld,
32: boolean increment) {
33: this .fieldDecl = field;
34: this .returnOld = returnOld;
35: this .increment = increment;
36: }
37:
38: private Declaration fieldDecl;
39: private boolean increment;
40: private boolean returnOld;
41:
42: public void compile(ApplyExp exp, Compilation comp, Target target) {
43: Field field = this .fieldDecl.field;
44: CodeAttr code = comp.getCode();
45: ClassType ctype = field.getDeclaringClass();
46: Expression[] args = exp.getArgs();
47:
48: // tells whether we want the value to be returned
49: boolean ignore = target instanceof IgnoreTarget;
50:
51: boolean isLong = field.getType().getSize() > 4;
52: PrimType type = isLong ? Type.long_type : Type.int_type;
53:
54: args[0].compile(comp, ctype);
55: code.emitDup(ctype);
56: code.emitGetField(field);
57:
58: if (!ignore && returnOld)
59: // Place a copy of the old value before the two operands
60: code.emitDup(isLong ? 2 : 1, 1);
61:
62: if (isLong)
63: code.emitPushLong(1);
64: else
65: code.emitPushInt(1);
66: if (increment)
67: code.emitAdd(type);
68: else
69: code.emitSub(type);
70:
71: if (!ignore && !returnOld)
72: // Place a copy of the new value before the two operands
73: code.emitDup(isLong ? 2 : 1, 1);
74:
75: code.emitPutField(field);
76:
77: if (!ignore)
78: target.compileFromStack(comp, field.getType());
79: }
80:
81: public gnu.bytecode.Type getReturnType(Expression[] args) {
82: return fieldDecl.getType();
83: }
84:
85: public Object apply1(Object arg1) {
86: throw new RuntimeException("not implemented");
87: }
88: }
|