001 package toolbus; 002 003 import java.util.ArrayList; 004 import java.util.Iterator; 005 import java.util.List; 006 import toolbus.environment.Binding; 007 import toolbus.environment.Environment; 008 import toolbus.exceptions.ToolBusException; 009 import toolbus.exceptions.ToolBusInternalError; 010 import aterm.AFun; 011 import aterm.ATerm; 012 import aterm.ATermAppl; 013 import aterm.ATermList; 014 import aterm.ATermPlaceholder; 015 import aterm.pure.PureFactory; 016 017 public class TBTermFactory extends PureFactory{ 018 /** 019 * A term of type VAR 020 */ 021 public static final int VAR = 80; 022 023 private final AFun fun_TBTermVar; 024 025 public final ATerm True; 026 public final ATerm False; 027 028 public final ATerm BoolType; 029 public final ATerm IntType; 030 public final ATerm RealType; 031 public final ATerm StrType; 032 public final ATerm TermType; 033 public final ATerm ListType; 034 public final ATerm BlobType; 035 036 public final ATerm Undefined; 037 038 public final ATerm BoolPlaceholder; 039 public final ATerm IntPlaceholder; 040 public final ATerm RealPlaceholder; 041 public final ATerm StrPlaceholder; 042 public final ATerm TermPlaceholder; 043 public final ATerm ListPlaceholder; 044 public final ATerm BlobPlaceholder; 045 046 public final ATermList EmptyList; 047 048 protected TBTermFactory(){ 049 super(); 050 051 fun_TBTermVar = makeAFun("var", 3, false); 052 053 True = make("true"); 054 False = make("false"); 055 056 BoolType = make("bool"); 057 IntType = make("int"); 058 RealType = make("real"); 059 StrType = make("str"); 060 TermType = make("term"); 061 ListType = make("list"); 062 BlobType = make("blob"); 063 064 Undefined = make("undefined"); 065 066 BoolPlaceholder = makePlaceholder(BoolType); 067 IntPlaceholder = makePlaceholder(IntType); 068 RealPlaceholder = makePlaceholder(RealType); 069 StrPlaceholder = makePlaceholder(StrType); 070 TermPlaceholder = makePlaceholder(TermType); 071 ListPlaceholder = makePlaceholder(ListType); 072 BlobPlaceholder = makePlaceholder(BlobType); 073 074 EmptyList = makeList(); 075 076 Functions.init(this); 077 } 078 079 private static class InstanceKeeper{ 080 public final static TBTermFactory instance = new TBTermFactory(); 081 } 082 083 public static TBTermFactory getInstance(){ 084 return InstanceKeeper.instance; 085 } 086 087 public String statistics(){ 088 return toString(); 089 } 090 091 public TBTermVar makeTBTermVar(String name, ATerm type, ATerm isResult, ATermList annos){ 092 ATerm[] args = new ATerm[3]; 093 args[0] = type; 094 args[1] = make(name); 095 args[2] = isResult; 096 return (TBTermVar) build(new TBTermVar(this, annos, fun_TBTermVar, args)); 097 } 098 099 public TBTermVar makeTBTermVar(String name, ATerm type){ 100 return makeTBTermVar(name, type, False, EmptyList); 101 } 102 103 public TBTermVar makeTBTermVar(String name, ATerm type, ATerm isResVar){ 104 return makeTBTermVar(name, type, isResVar, EmptyList); 105 } 106 107 public TBTermVar makeTBTermResVar(String name, ATerm type){ 108 return makeTBTermVar(name, type, True, EmptyList); 109 } 110 111 public TBTermVar mkVar(ATerm name, String processName, ATerm type){ 112 return makeTBTermVar(name.toString() + "$" + processName, type); 113 } 114 115 public TBTermVar mkResVar(ATerm name, String processName, ATerm type){ 116 return makeTBTermResVar(name.toString() + "$" + processName, type); 117 } 118 119 /*****/ 120 121 public boolean isTrue(ATerm t){ 122 return t == True; 123 } 124 125 public boolean isFalse(ATerm t){ 126 return t == False; 127 } 128 129 public boolean isBoolean(ATerm t){ 130 return t == True || t == False; 131 } 132 133 public boolean isInt(ATerm t){ 134 return t.getType() == ATerm.INT; 135 } 136 137 public boolean isStr(ATerm t){ 138 if(isAppl(t)){ 139 return (((ATermAppl) t).isQuoted()) && ((ATermAppl) t).getArity() == 0; 140 } 141 return false; 142 } 143 144 public boolean isReal(ATerm t){ 145 return (t.getType() == ATerm.REAL); 146 } 147 148 public boolean isAppl(ATerm t){ 149 return t.getType() == ATerm.APPL; 150 } 151 152 public boolean isList(ATerm t){ 153 return t.getType() == ATerm.LIST; 154 } 155 156 public boolean isBlob(ATerm t){ 157 return t.getType() == ATerm.BLOB; 158 } 159 160 public ATerm getArgs(ATerm t){ 161 return ((ATermAppl) t).getArguments(); 162 } 163 164 public int size(ATerm l){ 165 return ((ATermList) l).getLength(); 166 } 167 168 public ATerm first(ATerm l){ 169 ATermList lst = (ATermList) l; 170 if(!lst.isEmpty()){ 171 return lst.elementAt(0); 172 } 173 return Undefined; 174 // throw new ToolBusError("function first cannot be applied to empty list"); 175 } 176 177 public ATerm next(ATerm l){ 178 ATermList lst = (ATermList) l; 179 if(lst.isEmpty()){ 180 return lst; 181 } 182 return lst.getNext(); 183 } 184 185 public boolean member(ATerm e, ATerm l){ 186 ATermList lst = (ATermList) l; 187 int length = lst.getLength(); 188 for(int i = 0; i < length; i++){ 189 if(e.isEqual(lst.elementAt(i))) return true; 190 } 191 return false; 192 } 193 194 public boolean subset(ATerm l1, ATerm l2){ 195 ATerm terml2 = l2; 196 197 ATermList lst1 = (ATermList) l1; 198 int length1 = lst1.getLength(); 199 for(int i = 0; i < length1; i++){ 200 ATerm e = lst1.elementAt(i); 201 if(!member(e, terml2)){ 202 return false; 203 } 204 terml2 = delete(terml2, e); 205 } 206 return true; 207 } 208 209 public ATermList delete(ATerm l, ATerm e){ 210 ATermList lst = (ATermList) l; 211 ATermList res = EmptyList; 212 boolean found = false; 213 for(int i = lst.getLength() - 1; i >= 0; i--){ 214 ATerm e2 = lst.elementAt(i); 215 if(e2.isEqual(e) && !found) 216 found = true; 217 else res = makeList(e2, res); 218 } 219 return res; 220 } 221 222 public ATerm diff(ATerm l1, ATerm l2){ 223 ATermList lst1 = (ATermList) l1; 224 ATermList res = EmptyList; 225 for(int i = lst1.getLength() - 1; i >= 0; i--){ 226 ATerm e = lst1.elementAt(i); 227 if(!member(e, l2)) res = makeList(e, res); 228 } 229 return res; 230 } 231 232 public ATerm inter(ATerm l1, ATerm l2){ 233 ATermList lst1 = (ATermList) l1; 234 ATermList res = EmptyList; 235 for(int i = lst1.getLength() - 1; i >= 0; i--){ 236 ATerm e = lst1.elementAt(i); 237 if(member(e, l2)) res = makeList(e, res); 238 } 239 // System.err.println("inter(" + l1 + ", " + l2 + ") ==> " + res); 240 return res; 241 } 242 243 public ATerm join(ATerm l1, ATerm l2){ 244 // if(l1 == null) 245 // return l2; 246 // if(l2 == null) 247 // return l1; 248 ATermList lst1 = isList(l1) ? (ATermList) l1 : makeList(l1); 249 ATermList res = isList(l2) ? (ATermList) l2 : makeList(l2); 250 for(int i = lst1.getLength() - 1; i >= 0; i--){ 251 ATerm e = lst1.elementAt(i); 252 res = makeList(e, res); 253 } 254 // System.err.println("join(" + l1 + ", " + l2 + ") ==> " + res); 255 return res; 256 } 257 258 public ATerm concat(ATerm s1, ATerm s2){ 259 String str1 = isStr(s1) ? ((ATermAppl) s1).getName() : s1.toString(); 260 String str2 = isStr(s1) ? ((ATermAppl) s2).getName() : s2.toString(); 261 String res = str1 + str2; 262 AFun af = makeAFun(res, 0, true); 263 return makeAppl(af); 264 } 265 266 public ATerm index(ATerm l, int i){ 267 ATerm res; 268 try{ 269 res = ((ATermList) l).elementAt(i - 1); 270 }catch(IllegalArgumentException iaex){ 271 throw new IllegalArgumentException("An index out of bounds exception occured while retrieving the term at index: "+i+", from the following list: "+l); 272 } 273 return res; 274 } 275 276 public ATerm replace(ATerm l, int n, ATerm e){ 277 ATermList lst = (ATermList) l; 278 ATermList res = EmptyList; 279 for(int i = lst.getLength() - 1; i >= 0; i--){ 280 ATerm elem = (i == n - 1) ? e : lst.elementAt(i); 281 res = makeList(elem, res); 282 } 283 return res; 284 } 285 286 public ATerm put(ATerm l, ATerm k, ATerm v){ 287 ATermList pair = makeList(k, makeList(v)); 288 return makeList(pair, (ATermList) l); 289 } 290 291 public ATerm get(ATerm l, ATerm k){ 292 ATermList lst = (ATermList) l; 293 for(ATermList pair = (ATermList) lst.getFirst(); !lst.isEmpty(); lst = lst.getNext()){ 294 if(k.isEqual(pair.getFirst())) return pair.getLast(); 295 } 296 return Undefined; 297 } 298 299 public boolean isVar(ATerm t){ 300 return t.getType() == VAR && !((TBTermVar) t).isResultVar(); 301 } 302 303 public boolean isResultVar(ATerm t){ 304 return t.getType() == VAR && ((TBTermVar) t).isResultVar(); 305 } 306 307 public boolean isAnyVar(ATerm t){ 308 return t.getType() == VAR; 309 } 310 311 public TBTermVar replaceAssignableVar(TBTermVar v, Environment env) throws ToolBusException{ 312 // System.err.println("replaceAssignableVar: " + v + "; " + env); 313 314 Binding b = env.getBinding(v); 315 // System.err.println("Binding = " + b.var + ";" + b.val); 316 if(b == null || (b.getVal() == Undefined)){ 317 return v; 318 } 319 if(b.isFormal() && isResultVar(b.getVal())){ 320 return replaceAssignableVar((TBTermVar) b.getVal(), env); 321 } 322 return b.getVar(); 323 } 324 325 /** 326 * Replace the formals in ATerm t by their values using Environment env. 327 * 328 * @param t 329 * Aterm containing formals 330 * @param env 331 * environment to be used. 332 */ 333 public ATerm replaceFormals(ATerm t, Environment env) throws ToolBusException{ 334 if(env.size() == 0) return t; 335 336 switch(t.getType()){ 337 case ATerm.BLOB: 338 case ATerm.INT: 339 case ATerm.PLACEHOLDER: 340 case ATerm.REAL: 341 return t; 342 343 case VAR: 344 return env.replaceFormal((TBTermVar) t); 345 346 case ATerm.APPL: 347 ATermAppl apt = (ATermAppl) t; 348 349 AFun afun = apt.getAFun(); 350 ATerm args[] = apt.getArgumentArray(); 351 ATerm cargs[] = new ATerm[args.length]; 352 int nargs = args.length; 353 if(nargs == 0) return t; 354 for(int i = 0; i < nargs; i++){ 355 cargs[i] = replaceFormals(args[i], env); 356 } 357 return makeAppl(afun, cargs); 358 359 case ATerm.LIST: 360 ATermList lst = EmptyList; 361 ATermList tlst = (ATermList) t; 362 for(int i = tlst.getLength() - 1; i >= 0; i--){ 363 lst = lst.insert(replaceFormals(tlst.elementAt(i), env)); 364 } 365 return lst; 366 } 367 throw new ToolBusInternalError("illegal ATerm in replaceFormals: " + t); 368 } 369 370 /** 371 * Transform a term into a pattern that can be used by tool interfaces. 372 */ 373 public ATerm makePattern(ATerm t){ 374 if(t == Undefined) return t; 375 376 switch(t.getType()){ 377 case ATerm.BLOB: 378 return BlobPlaceholder; 379 380 case ATerm.INT: 381 return IntPlaceholder; 382 383 case ATerm.PLACEHOLDER: 384 return t; 385 386 case ATerm.REAL: 387 return RealPlaceholder; 388 389 case VAR: 390 TBTermVar var = (TBTermVar) t; 391 ATerm type = var.getVarType(); 392 return makePlaceholder(type); 393 394 case ATerm.APPL: 395 ATermAppl apt = (ATermAppl) t; 396 if(isBoolean(apt)){ 397 return BoolPlaceholder; 398 } 399 AFun fun = apt.getAFun(); 400 ATerm args[] = apt.getArgumentArray(); 401 int nargs = args.length; 402 if(nargs == 0){ 403 if(fun.isQuoted()){ 404 return StrPlaceholder; 405 } 406 return apt; 407 } 408 409 ATerm vargs[] = new ATerm[nargs]; 410 for(int i = 0; i < nargs; i++){ 411 vargs[i] = makePattern(args[i]); 412 } 413 return makeAppl(fun, vargs); 414 415 case ATerm.LIST: 416 ATermList lst = EmptyList; 417 ATermList tlst = (ATermList) t; 418 for(int i = tlst.getLength() - 1; i >= 0; i--){ 419 lst = lst.insert(makePattern(tlst.elementAt(i))); 420 } 421 return lst; 422 423 } 424 throw new ToolBusInternalError("illegal ATerm in getType: " + t); 425 } 426 427 // TODO Optimize 428 /** 429 * Replace all variables in an ATerm by their value. 430 */ 431 public ATerm substitute(ATerm t, Environment env){ 432 if(t == Undefined) return t; 433 434 switch(t.getType()){ 435 case ATerm.BLOB: 436 case ATerm.INT: 437 case ATerm.PLACEHOLDER: 438 case ATerm.REAL: 439 return t; 440 441 case VAR: 442 TBTermVar var = (TBTermVar) t; 443 if(var.isResultVar()) return var; 444 445 return env.getValue(var); 446 447 case ATerm.APPL: 448 ATermAppl apt = (ATermAppl) t; 449 if(apt.getArity() == 0) return t; 450 451 AFun afun = apt.getAFun(); 452 ATerm args[] = apt.getArgumentArray(); 453 ATermList applAnnos = apt.getAnnotations(); 454 455 int nargs = args.length; 456 ATerm vargs[] = new ATerm[nargs]; 457 for(int i = 0; i < nargs; i++){ 458 vargs[i] = substitute(args[i], env); 459 } 460 return makeAppl(afun, vargs, applAnnos); 461 462 case ATerm.LIST: 463 ATermList tlst = (ATermList) t; 464 ATermList listAnnos = t.getAnnotations(); 465 466 if(tlst == EmptyList) return t; 467 468 int len = tlst.getLength(); 469 ATerm[] listContent = new ATerm[len]; 470 for(int i = len - 1; i >= 0; i--){ 471 listContent[i] = tlst.getFirst(); 472 tlst = tlst.getNext(); 473 } 474 475 ATermList lst = EmptyList; 476 for(int i = 0; i < len; i++){ 477 lst = lst.insert((substitute(listContent[i], env))); 478 } 479 480 lst = (ATermList) lst.setAnnotations(listAnnos); 481 482 return lst; 483 } 484 throw new ToolBusInternalError("Illegal ATerm in substitute: " + t); 485 } 486 487 // TODO Optimize 488 /** 489 * Replaces all variables in an ATerm by their value. If a variable result variable is present 490 * the full substitute can not be completed and null will be returned instead. 491 * @param t 492 * The term in which variables need to be substituted. 493 * @param env 494 * The environment from which the variable values can be retrieved. 495 * @return A complete ATerm tree that doesn't contain any variables; null if the substitute could 496 * not be completed. 497 */ 498 public ATerm fullSubstitute(ATerm t, Environment env){ 499 if(t == Undefined) return t; 500 501 switch(t.getType()){ 502 case ATerm.BLOB: 503 case ATerm.INT: 504 case ATerm.PLACEHOLDER: 505 case ATerm.REAL: 506 return t; 507 508 case VAR: 509 TBTermVar var = (TBTermVar) t; 510 if(var.isResultVar()) return null; 511 512 return env.getValue(var); 513 514 case ATerm.APPL: 515 ATermAppl apt = (ATermAppl) t; 516 if(apt.getArity() == 0) return t; 517 518 AFun afun = apt.getAFun(); 519 ATerm args[] = apt.getArgumentArray(); 520 ATermList applAnnos = apt.getAnnotations(); 521 522 int nargs = args.length; 523 ATerm vargs[] = new ATerm[nargs]; 524 for(int i = 0; i < nargs; i++){ 525 ATerm result = fullSubstitute(args[i], env); 526 if(result == null) return null; 527 vargs[i] = result; 528 } 529 return makeAppl(afun, vargs, applAnnos); 530 531 case ATerm.LIST: 532 ATermList tlst = (ATermList) t; 533 ATermList listAnnos = t.getAnnotations(); 534 535 if(tlst == EmptyList) return t; 536 537 int len = tlst.getLength(); 538 ATerm[] listContent = new ATerm[len]; 539 for(int i = len - 1; i >= 0; i--){ 540 listContent[i] = tlst.getFirst(); 541 tlst = tlst.getNext(); 542 } 543 544 ATermList lst = EmptyList; 545 for(int i = 0; i < len; i++){ 546 ATerm result = fullSubstitute(listContent[i], env); 547 if(result == null) return null; 548 lst = lst.insert(result); 549 } 550 551 lst = (ATermList) lst.setAnnotations(listAnnos); 552 553 return lst; 554 } 555 throw new ToolBusInternalError("Illegal ATerm in substitute: " + t); 556 } 557 558 public boolean match(ATerm left, Environment leftEnv, ATerm right, Environment rightEnv){ 559 List<Binding> leftDeltaEnv = new ArrayList<Binding>(); 560 List<Binding> rightDeltaEnv = new ArrayList<Binding>(); 561 562 boolean matches = performMatch(left, leftEnv, leftDeltaEnv, right, rightEnv, rightDeltaEnv); 563 if(matches){ 564 Iterator<Binding> leftDeltaEnvIterator = leftDeltaEnv.iterator(); 565 while(leftDeltaEnvIterator.hasNext()){ 566 Binding deltaBinding = leftDeltaEnvIterator.next(); 567 leftEnv.assignVar(deltaBinding.getVar(), deltaBinding.getVal()); 568 } 569 570 Iterator<Binding> rightDeltaEnvIterator = rightDeltaEnv.iterator(); 571 while(rightDeltaEnvIterator.hasNext()){ 572 Binding deltaBinding = rightDeltaEnvIterator.next(); 573 rightEnv.assignVar(deltaBinding.getVar(), deltaBinding.getVal()); 574 } 575 } 576 577 return matches; 578 } 579 580 public boolean matchPatternToValue(ATerm left, Environment leftEnv, ATerm right){ 581 List<Binding> leftDeltaEnv = new ArrayList<Binding>(); 582 583 boolean matches = performPatternMatch(left, leftEnv, right, leftDeltaEnv); 584 if(matches){ 585 Iterator<Binding> deltaEnvIterator = leftDeltaEnv.iterator(); 586 while(deltaEnvIterator.hasNext()){ 587 Binding deltaBinding = deltaEnvIterator.next(); 588 leftEnv.assignVar(deltaBinding.getVar(), deltaBinding.getVal()); 589 } 590 } 591 592 return matches; 593 } 594 595 public boolean patternMatchesToValue(ATerm pattern, Environment patternEnv, ATerm value){ 596 List<Binding> deltaEnv = new ArrayList<Binding>(); 597 598 return performPatternMatch(pattern, patternEnv, value, deltaEnv); 599 } 600 601 private boolean performPatternMatch(ATerm pattern, Environment patternEnv, ATerm value, List<Binding> deltaEnv){ 602 switch(pattern.getType()){ 603 case VAR: 604 TBTermVar pVar = (TBTermVar) pattern; 605 if(pVar.isResultVar()){ 606 if(Functions.compatibleTypes(pVar.getVarType(), value)){ 607 Binding deltaBinding = new Binding(pVar, value); 608 deltaEnv.add(deltaBinding); 609 return true; 610 } 611 return false; 612 } 613 return performPatternMatch(patternEnv.getValue(pVar), patternEnv, value, deltaEnv); 614 615 case ATerm.APPL: 616 if(value.getType() != ATerm.APPL) return false; 617 618 ATermAppl pa = (ATermAppl) pattern; 619 ATermAppl va = (ATermAppl) value; 620 if(pa.getAFun() != va.getAFun()) return false; 621 622 ATerm[] patternChildren = pa.getArgumentArray(); 623 ATerm[] valueChildren = va.getArgumentArray(); 624 for(int i = patternChildren.length - 1; i >= 0; i--){ 625 if(!performPatternMatch(patternChildren[i], patternEnv, valueChildren[i], deltaEnv)) return false; 626 } 627 628 return true; 629 case ATerm.LIST: 630 if(value.getType() != ATerm.LIST) return false; 631 632 ATermList pl = (ATermList) pattern; 633 ATermList vl = (ATermList) value; 634 int plLength = pl.getLength(); 635 if(plLength != vl.getLength()) return false; 636 while(pl != EmptyList){ 637 if(!performPatternMatch(pl.getFirst(), patternEnv, vl.getFirst(), deltaEnv)) return false; 638 pl = pl.getNext(); 639 vl = vl.getNext(); 640 } 641 642 return true; 643 case ATerm.PLACEHOLDER: 644 case ATerm.INT: 645 case ATerm.REAL: 646 case ATerm.BLOB: 647 return ((pattern.hasAnnotations() ? pattern.removeAnnotations() : pattern) == (value.hasAnnotations() ? value.removeAnnotations() : value)); 648 default: 649 throw new ToolBusInternalError("Illegal ATerm pattern in matchPatternToValue: " + pattern); 650 } 651 } 652 653 private boolean performMatch(ATerm left, Environment leftEnv, List<Binding> leftDeltaEnv, ATerm right, Environment rightEnv, List<Binding> rightDeltaEnv){ 654 ATerm rightTerm = right; 655 if(rightTerm.getType() == VAR){ 656 TBTermVar rightVar = (TBTermVar) rightTerm; 657 if(rightVar.isResultVar()){ 658 if(left.getType() == VAR){ 659 TBTermVar leftVar = (TBTermVar) left; 660 if(!leftVar.isResultVar()){ 661 ATerm leftValue = leftEnv.getValue(leftVar); 662 663 if(Functions.compatibleTypes(rightVar.getVarType(), leftValue)){ 664 ATerm fullySubstitutedLeftValue = fullSubstitute(leftValue, leftEnv); 665 if(fullySubstitutedLeftValue != null){ 666 Binding deltaBinding = new Binding(rightVar, fullySubstitutedLeftValue); 667 rightDeltaEnv.add(deltaBinding); 668 return true; 669 } 670 return false; 671 } 672 }else{ 673 return false; 674 } 675 }else{ 676 if(Functions.compatibleTypes(rightVar.getVarType(), left)){ 677 ATerm fullySubstitutedLeft = fullSubstitute(left, leftEnv); 678 if(fullySubstitutedLeft != null){ 679 Binding deltaBinding = new Binding(rightVar, fullySubstitutedLeft); 680 rightDeltaEnv.add(deltaBinding); 681 return true; 682 } 683 return false; 684 } 685 } 686 return false; 687 } 688 689 rightTerm = rightEnv.getValue(rightVar); 690 } 691 692 switch(left.getType()){ 693 case VAR: 694 TBTermVar pVar = (TBTermVar) left; 695 if(pVar.isResultVar()){ 696 if(Functions.compatibleTypes(pVar.getVarType(), rightTerm)){ 697 ATerm fullySubstitutedRightValue = fullSubstitute(rightTerm, rightEnv); 698 if(fullySubstitutedRightValue != null){ 699 Binding deltaBinding = new Binding(pVar, fullySubstitutedRightValue); 700 leftDeltaEnv.add(deltaBinding); 701 return true; 702 } 703 return false; 704 } 705 return false; 706 } 707 return performMatch(leftEnv.getValue(pVar), leftEnv, leftDeltaEnv, rightTerm, rightEnv, rightDeltaEnv); 708 709 case ATerm.APPL: 710 if(rightTerm.getType() != ATerm.APPL) return false; 711 712 ATermAppl pa = (ATermAppl) left; 713 ATermAppl va = (ATermAppl) rightTerm; 714 if(pa.getAFun() != va.getAFun()) return false; 715 716 ATerm[] patternChildren = pa.getArgumentArray(); 717 ATerm[] valueChildren = va.getArgumentArray(); 718 for(int i = patternChildren.length - 1; i >= 0; i--){ 719 if(!performMatch(patternChildren[i], leftEnv, leftDeltaEnv, valueChildren[i], rightEnv, rightDeltaEnv)) return false; 720 } 721 722 return true; 723 case ATerm.LIST: 724 if(rightTerm.getType() != ATerm.LIST) return false; 725 726 ATermList pl = (ATermList) left; 727 ATermList vl = (ATermList) rightTerm; 728 int plLength = pl.getLength(); 729 if(plLength != vl.getLength()) return false; 730 while(pl != EmptyList){ 731 if(!performMatch(pl.getFirst(), leftEnv, leftDeltaEnv, vl.getFirst(), rightEnv, rightDeltaEnv)) return false; 732 pl = pl.getNext(); 733 vl = vl.getNext(); 734 } 735 736 return true; 737 case ATerm.PLACEHOLDER: 738 case ATerm.INT: 739 case ATerm.REAL: 740 case ATerm.BLOB: 741 return ((left.hasAnnotations() ? left.removeAnnotations() : left) == (rightTerm.hasAnnotations() ? rightTerm.removeAnnotations() : rightTerm)); 742 default: 743 throw new ToolBusInternalError("Illegal ATerm pattern in matchPatternToValue: " + left); 744 } 745 } 746 747 public boolean mightMatch(ATerm terma, ATerm termb){ 748 switch(terma.getType()){ 749 case VAR: 750 return Functions.compatibleTypes(((TBTermVar) terma).getVarType(), termb); 751 case ATerm.BLOB: 752 if(isAnyVar(termb)) return true; 753 return terma.isEqual(termb) || (termb == BlobPlaceholder) || (termb == TermPlaceholder); 754 755 case ATerm.INT: 756 if(isAnyVar(termb)) return true; 757 return terma.isEqual(termb) || (termb == IntPlaceholder) || (termb == TermPlaceholder); 758 759 case ATerm.REAL: 760 if(isAnyVar(termb)) return true; 761 return terma.isEqual(termb) || (termb == RealPlaceholder) || (termb == TermPlaceholder); 762 763 case ATerm.PLACEHOLDER: 764 if(isAnyVar(termb)) return true; 765 766 if(terma == TermPlaceholder) return true; 767 768 switch(termb.getType()){ 769 case ATerm.INT: 770 return (terma == IntPlaceholder); 771 case ATerm.REAL: 772 return (terma == RealPlaceholder); 773 case ATerm.APPL: 774 return matchPlaceholder((ATermAppl) termb, (ATermPlaceholder) terma, true); 775 case ATerm.BLOB: 776 return (terma == BlobPlaceholder); 777 case ATerm.LIST: 778 return matchListPlaceholder((ATermList) termb, (ATermPlaceholder) terma, true); 779 } 780 return false; 781 782 case ATerm.APPL: 783 if(isAnyVar(termb)) return true; 784 ATermAppl apta = (ATermAppl) terma; 785 786 switch(termb.getType()){ 787 case ATerm.PLACEHOLDER: 788 return matchPlaceholder(apta, (ATermPlaceholder) termb, false); 789 790 case ATerm.APPL: 791 ATermAppl aptb = (ATermAppl) termb; 792 if(apta.getAFun() != aptb.getAFun()) return false; 793 794 ATerm a_args[] = apta.getArgumentArray(); 795 ATerm b_args[] = aptb.getArgumentArray(); 796 for(int i = a_args.length - 1; i >= 0; i--){ 797 if(!mightMatch(a_args[i], b_args[i])) return false; 798 } 799 return true; 800 default: 801 return false; 802 } 803 804 case ATerm.LIST: 805 if(isAnyVar(termb)) return true; 806 807 ATermList lsta = (ATermList) terma; 808 switch(termb.getType()){ 809 case ATerm.PLACEHOLDER: 810 return matchListPlaceholder(lsta, (ATermPlaceholder) termb, false); 811 812 case ATerm.LIST: 813 ATermList lstb = (ATermList) termb; 814 if(lsta.getLength() != lstb.getLength()) return false; 815 816 while(!lsta.isEmpty()){ 817 if(!mightMatch(lsta.getFirst(), lstb.getFirst())) return false; 818 lsta = lsta.getNext(); 819 lstb = lstb.getNext(); 820 } 821 return true; 822 default: 823 return false; 824 } 825 826 default: 827 throw new ToolBusInternalError("illegal ATerm in performMatch: " + terma); 828 } 829 } 830 831 private boolean matchListPlaceholder(ATermList terma, ATermPlaceholder tb, boolean swapargs){ 832 ATermList ta = terma; 833 834 if(tb == ListPlaceholder) return true; 835 836 ATerm placeholder = tb.getPlaceholder(); 837 if(placeholder.getType() == ATerm.APPL){ 838 ATermAppl aplPlaceholder = (ATermAppl) placeholder; 839 if(aplPlaceholder.getName() != "list") return false; 840 841 int arity = aplPlaceholder.getArity(); 842 843 if(arity == 1){ 844 ATerm elemtype = aplPlaceholder.getArgument(0); 845 ATermPlaceholder elm = makePlaceholder(elemtype); 846 847 while(!ta.isEmpty()){ 848 if(!swapMatch(elm, ta.getFirst(), swapargs)) return false; 849 850 ta = ta.getNext(); 851 } 852 return true; 853 } 854 855 if(arity != ta.getLength()) return false; 856 857 for(int i = 0; i < arity; i++){ 858 ATerm elemtype = aplPlaceholder.getArgument(i); 859 ATermPlaceholder elemPlaceholder = makePlaceholder(elemtype); 860 861 if(!swapMatch(elemPlaceholder, ta.getFirst(), swapargs)) return false; 862 863 ta = ta.getNext(); 864 } 865 return true; 866 } 867 return swapMatch(ta, placeholder, swapargs); 868 } 869 870 private boolean matchPlaceholder(ATermAppl ta, ATermPlaceholder tb, boolean swapargs){ 871 if(tb == StrPlaceholder && ta.getArity() == 0) return true; 872 else if(tb == TermPlaceholder) return true; 873 874 ATerm placeholder = tb.getPlaceholder(); 875 if(placeholder.getType() == ATerm.APPL){ 876 ATermAppl aplPlaceholder = (ATermAppl) placeholder; 877 int arity = aplPlaceholder.getArity(); 878 879 if(arity == 0) return (ta.getName() == aplPlaceholder.getName()); 880 881 if(arity != ta.getArity()) return false; 882 883 for(int i = arity - 1; i >= 0; i--){ 884 ATerm elemtype = aplPlaceholder.getArgument(i); 885 ATermPlaceholder elemPlaceholder = makePlaceholder(elemtype); 886 887 if(!swapMatch(elemPlaceholder, ta.getArgument(i), swapargs)) return false; 888 } 889 return true; 890 891 } 892 return swapMatch(ta, placeholder, swapargs); 893 } 894 895 private boolean swapMatch(ATerm ta, ATerm tb, boolean swapargs){ 896 return swapargs ? mightMatch(tb, ta) : mightMatch(ta, tb); 897 } 898 }