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 }