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