001 package toolbus.process;
002
003 import java.util.ArrayList;
004 import java.util.List;
005 import java.util.Random;
006 import java.util.Stack;
007 import toolbus.AtomList;
008 import toolbus.State;
009 import toolbus.StateElement;
010 import toolbus.TBTermFactory;
011 import toolbus.environment.Environment;
012 import toolbus.exceptions.ToolBusException;
013 import toolbus.parsercup.PositionInformation;
014 import toolbus.process.debug.ExecutionResult;
015 import aterm.ATerm;
016
017 /**
018 * @author paulk, Aug 7, 2002 Merge implements the parallell composition operator || It maintains
019 * its two arguments and randomly selects in which argument the next atom will be executed.
020 * When both arguments are exhausted, execution continues with the followSet of the merge.
021 */
022 public class Merge extends ProcessExpression implements StateElement{
023 private final static Random rand = new Random();
024
025 private final int LEFT = 0;
026 private final int RIGHT = 1;
027
028 private ProcessInstance processInstance;
029
030 private final ProcessExpression[] expr;
031
032 private final State[] state;
033 private final State[] initialState;
034 private final State mergeState;
035
036 private boolean leftLast = false;
037
038 public Merge(ProcessExpression left, ProcessExpression right, TBTermFactory tbfactory, PositionInformation posInfo){
039 super(tbfactory, posInfo);
040
041 state = new State[2];
042 initialState = new State[2];
043
044 expr = new ProcessExpression[2];
045 expr[LEFT] = left;
046 expr[RIGHT] = right;
047
048 mergeState = new State();
049 mergeState.addElement(this);
050 }
051
052 protected void computeFirst(){
053 expr[LEFT].computeFirst();
054 expr[RIGHT].computeFirst();
055 }
056
057 protected void compile(ProcessInstance processInstance, Stack<String> calls, State follows) throws ToolBusException{
058 this.processInstance = processInstance;
059
060 expr[LEFT].compile(processInstance, calls, follows);
061 initialState[LEFT] = state[LEFT] = expr[LEFT].getFirst();
062
063 expr[RIGHT].compile(processInstance, calls, follows);
064 initialState[RIGHT] = state[RIGHT] = expr[RIGHT].getFirst();
065 setFollow(follows);
066 }
067
068 protected void replaceFormals(Environment env) throws ToolBusException{
069 expr[LEFT].replaceFormals(env);
070 expr[RIGHT].replaceFormals(env);
071 }
072
073 protected ProcessExpression copy(){
074 return new Merge(expr[LEFT].copy(), expr[RIGHT].copy(), tbfactory, getPosInfo());
075 }
076
077 public AtomList getAtoms(){
078 return expr[LEFT].getAtoms().union(expr[RIGHT].getAtoms());
079 }
080
081 public State getFirst(){
082 return mergeState;
083 }
084
085 // Implementation of the StateElement interface
086
087 public boolean contains(StateElement a){
088 return state[LEFT].contains(a) || state[RIGHT].contains(a);
089 }
090
091 public ProcessInstance getProcess(){
092 return processInstance;
093 }
094
095 public void setTest(ATerm test, Environment env) throws ToolBusException{
096 state[LEFT].setTest(test, env);
097 state[RIGHT].setTest(test, env);
098 }
099
100 public List<ATerm> getTests(){
101 return new ArrayList<ATerm>(0);
102 }
103
104 public boolean isEnabled(){
105 return state[LEFT].isEnabled() || state[RIGHT].isEnabled();
106 }
107
108 private void initState(){
109 state[LEFT] = initialState[LEFT];
110 state[RIGHT] = initialState[RIGHT];
111 }
112
113 public State gotoNextStateAndActivate(){
114 State follow = getFollow();
115
116 // System.err.println("Merge.getNextState: " + leftLast + " ; follow = " + follow);
117 // System.err.println("state[LEFT] =" + state[LEFT]);
118 // System.err.println("state[RIGHT] =" + state[RIGHT]);
119
120 if(state[LEFT] == follow || state[RIGHT] == follow){
121 // TODO put the line below in comment since it will throw an exception and X isn't used.
122 // int x = 3 / 0;
123 }
124
125 if(leftLast){
126 State ns = state[LEFT].gotoNextStateAndActivate();
127 if(ns == follow){
128 State r = state[RIGHT];
129 // System.err.println("state[LEFT] == follow");
130 // System.err.println("returning " + r);
131 initState();
132 return r;
133 }
134 // System.err.println("returning " + mergeState);
135 state[LEFT] = ns;
136 return mergeState;
137
138 }
139
140 State ns = state[RIGHT].gotoNextStateAndActivate();
141 if(ns == follow){
142 State l = state[LEFT];
143 // System.err.println("state[RIGHT] == follow");
144 // System.err.println("returning " + l);
145 initState();
146 return l;
147 }
148
149 // System.err.println("returning " + mergeState);
150 state[RIGHT] = ns;
151 return mergeState;
152 }
153
154 public State gotoNextStateAndActivate(StateElement se){
155 State follow = getFollow();
156
157 // System.err.println("Merge.getNextState2: " + leftLast + "; " + se + " ; follow = " +
158 // follow);
159 // System.err.println("state[LEFT] =" + state[LEFT]);
160 // System.err.println("state[RIGHT] =" + state[RIGHT]);
161
162 if(state[LEFT].contains(se)){
163 State ns = state[LEFT].gotoNextStateAndActivate(se);
164 if(ns == follow){
165 State r = state[RIGHT];
166 // System.err.println("state[LEFT] == follow");
167 // System.err.println("returning " + r);
168 initState();
169 return r;
170 }
171
172 // System.err.println("returning " + mergeState);
173 state[LEFT] = ns;
174 return mergeState;
175 }else if(state[RIGHT].contains(se)){
176 State ns = state[RIGHT].gotoNextStateAndActivate(se);
177 if(ns == follow){
178 State l = state[LEFT];
179 // System.err.println("state[RIGHT] == follow");
180 // System.err.println("returning " + l);
181 initState();
182 return l;
183 }
184
185 // System.err.println("returning " + mergeState);
186 state[RIGHT] = ns;
187 return mergeState;
188 }else{
189 System.err.println("Merge.getNextState2 wrong!");
190 return null;
191 }
192 }
193
194 public void activate(){
195 state[LEFT].activate();
196 state[RIGHT].activate();
197 }
198
199 /**
200 * Generate next random boolean.
201 */
202 public static boolean nextBoolean(){
203 return rand.nextBoolean();
204 }
205
206 public boolean execute() throws ToolBusException{
207 int l, r;
208 if(nextBoolean()){
209 l = LEFT;
210 r = RIGHT;
211 }else{
212 l = RIGHT;
213 r = LEFT;
214 }
215
216 if(state[l].execute()){
217 leftLast = (l == LEFT);
218 return true;
219 }else if(state[r].execute()){
220 leftLast = (r == LEFT);
221 return true;
222 }else return false;
223 }
224
225 public ProcessInstance[] debugExecute() throws ToolBusException{
226 int l, r;
227 if(nextBoolean()){
228 l = LEFT;
229 r = RIGHT;
230 }else{
231 l = RIGHT;
232 r = LEFT;
233 }
234
235 ExecutionResult er;
236 if((er = state[l].debugExecute()) != null){
237 leftLast = (l == LEFT);
238 return er.partners;
239 }else if((er = state[r].debugExecute()) != null){
240 leftLast = (r == LEFT);
241 return er.partners;
242 }
243
244 return null;
245 }
246
247 public String toString(){
248 return "Merge(" + state[LEFT] + "; " + state[RIGHT] + ")";
249 }
250
251 /*public void addPartners(AtomSet s) throws ToolBusException{
252 state[LEFT].addPartners(s);
253 state[RIGHT].addPartners(s);
254 }*/
255
256 /*public void delPartners(AtomSet s) throws ToolBusException{
257 state[LEFT].delPartners(s);
258 state[RIGHT].delPartners(s);
259 }*/
260 }