better error reporting on invalid instructions
[fleet.git] / src / edu / berkeley / fleet / api / Instruction.java
1 package edu.berkeley.fleet.api;
2
3 public abstract class Instruction {
4
5     public final Pump pump;
6     public Instruction(Pump pump) { this.pump = pump; }
7     public String toString() { return pump+": "; }
8
9     public static abstract class CountingInstruction extends Instruction {
10         public final int count;
11         public CountingInstruction(Pump pump, int count) {
12             super(pump);
13             this.count = count;
14         }
15         protected abstract boolean isRequeueing();
16         public String toString() { return super.toString()+(count==1?"":(isRequeueing()?("("+(count==0?"*":(count+""))+")"):("["+(count==0?"*":(count+""))+"]")))+" "; }
17     }
18
19     public static class UnClog extends Instruction {
20         public UnClog(Pump pump) { super(pump); }
21         public String toString() { return super.toString() + "unclog;"; }
22     }
23
24     public static class Clog extends Instruction {
25         public Clog(Pump pump) { super(pump); }
26         public String toString() { return super.toString() + "clog;"; }
27     }
28
29     public static class Kill extends CountingInstruction {
30         public Kill(Pump pump, int count) { super(pump, count); }
31         protected boolean isRequeueing() { return false; }
32         public String toString() { return super.toString() + "kill;"; }
33     }
34
35     public static class Executable extends Instruction {
36
37         public final Destination dest;
38         public final int         count;
39
40         public final boolean     tokenIn;
41         public final boolean     dataIn;
42         public final boolean     latch;
43         public final boolean     dataOutDest;
44         public final boolean     dataOut;
45         public final boolean     tokenOut;
46         public final boolean     requeue;
47         public final boolean     ignoreUntilLast;
48
49         protected boolean isRequeueing() { return requeue; }
50
51         /** count=0 denotes a standing move */
52         public Executable(Pump        pump,
53                           Destination dest,
54                           int         count,
55                           boolean     tokenIn,
56                           boolean     dataIn,
57                           boolean     latch,
58                           boolean     dataOutDest,
59                           boolean     dataOut,
60                           boolean     tokenOut,
61                           boolean     requeue,
62                           boolean     ignoreUntilLast) {
63             super(pump);
64             this.dest = dest;
65             this.count = count;
66             this.tokenIn = tokenIn;
67             this.dataIn = dataIn;
68             this.latch = latch;
69             this.dataOutDest = dataOutDest;
70             this.dataOut = dataOut;
71             this.tokenOut = tokenOut;
72             this.requeue = requeue;
73             this.ignoreUntilLast = ignoreUntilLast;
74             if (count < 0)
75                 throw new RuntimeException("count field of an instruction must be >=0");
76             if (pump.isInbox() && tokenIn && dataIn)
77                 throw new RuntimeException("cannot have both \"wait\" and \"take\"/\"recieve\" on an inbox: " + this);
78             if (pump.isOutbox() && tokenOut && dataOut)
79                 throw new RuntimeException("cannot have both \"sendto\" and \"notify\" on an outbox: " + this);
80             if (latch && !dataIn)
81                 throw new RuntimeException("cannot have latch bit set without dataIn bit: " + this);
82         }
83
84         public boolean isStanding() {
85             return count==0;
86         }
87
88         public Instruction.Executable decrementCount() {
89             if (count==1) return null;
90             return new Executable(pump, dest, count==0 ? 0 : count-1,
91                                   tokenIn, dataIn, latch, dataOutDest, dataOut, tokenOut, requeue, ignoreUntilLast);
92         }
93
94         public String toString() {
95             // FIXME
96             String ret = super.toString();
97             boolean needcomma = false;
98             if (tokenIn)           { ret += (needcomma ? ", " : "") + "wait";    needcomma = true; }
99             if (dataIn && latch)  {
100                 if (pump.isInbox())
101                     ret += (needcomma ? ", " : "") + "receive";
102                 else
103                     ret += (needcomma ? ", " : "") + "take";
104                 needcomma = true;
105             }
106             if (dataIn && !latch)  { ret += (needcomma ? ", " : "") + "dismiss"; needcomma = true; }
107             if (dataOut)  {
108                 if (pump.isInbox() || dest==null)
109                     ret += (needcomma ? ", " : "") + "deliver";
110                 else
111                     ret += (needcomma ? ", " : "") + "sendto "+dest;
112                 needcomma = true;
113             }
114             if (tokenOut) { ret += (needcomma ? ", " : "") + "notify "+dest; needcomma = true; }
115             return ret;
116         }
117
118     }
119
120     public static class LocalLiteral extends CountingInstruction {
121         public final long literal;
122         public boolean isRequeueing() { return true; }
123         public LocalLiteral(Pump pump, long literal, int count) {
124             super(pump, count);
125             this.literal = literal;
126         }
127     }
128
129     public static class CodeBagDescriptor extends Instruction {
130         /** address of CBD, relative to address that this instruction was loaded from */
131         public final long offset;
132         public final long size;
133         public CodeBagDescriptor(Pump pump, long offset, long size) {
134             super(pump);
135             this.offset = offset;
136             this.size = size;
137         }
138         public String toString() {
139             String off = ""+offset;
140             if (offset > 0) off = "+"+off;
141             return "(CBD @"+off+"+"+size+"): sendto " + pump;
142         }
143     }
144
145 }