001 package toolbus; 002 003 import java.util.Hashtable; 004 005 import toolbus.environment.Environment; 006 import toolbus.exceptions.ToolBusError; 007 import toolbus.exceptions.ToolBusException; 008 import toolbus.exceptions.ToolBusInternalError; 009 import toolbus.process.ProcessInstance; 010 import aterm.AFun; 011 import aterm.ATerm; 012 import aterm.ATermAppl; 013 import aterm.ATermInt; 014 import aterm.ATermList; 015 import aterm.ATermPlaceholder; 016 import aterm.ATermReal; 017 018 abstract class FunctionDescriptor{ 019 private final TBTermFactory tbfactory; 020 private final String name; 021 private final ATerm argtypes[]; 022 private final ATerm resultType; 023 024 public FunctionDescriptor(TBTermFactory tbfactory, String name, ATerm resultType){ 025 this.tbfactory = tbfactory; 026 this.name = name; 027 this.resultType = resultType; 028 argtypes = new ATerm[0]; 029 } 030 031 public FunctionDescriptor(TBTermFactory tbfactory, String name, ATerm arg0, ATerm resultType){ 032 this.tbfactory = tbfactory; 033 this.name = name; 034 this.resultType = resultType; 035 argtypes = new ATerm[1]; 036 argtypes[0] = arg0; 037 } 038 039 public FunctionDescriptor(TBTermFactory tbfactory, String name, ATerm arg0, ATerm arg1, ATerm resultType){ 040 this.tbfactory = tbfactory; 041 this.name = name; 042 this.resultType = resultType; 043 argtypes = new ATerm[2]; 044 argtypes[0] = arg0; 045 argtypes[1] = arg1; 046 } 047 048 public FunctionDescriptor(TBTermFactory tbfactory, String name, ATerm arg0, ATerm arg1, ATerm arg2, ATerm resultType){ 049 this.tbfactory = tbfactory; 050 this.name = name; 051 this.resultType = resultType; 052 argtypes = new ATerm[3]; 053 argtypes[0] = arg0; 054 argtypes[1] = arg1; 055 argtypes[2] = arg2; 056 } 057 058 public String getName(){ 059 return name; 060 } 061 062 public ATerm getResultType(){ 063 return resultType; 064 } 065 066 /** 067 * checkStatic performs a static type check for calls to built-in functions 068 * 069 * @param actual 070 * an array of types of actual parameters 071 * @return boolean 072 * @throws ToolBusError 073 */ 074 public boolean checkStatic(ATerm actual[]) throws ToolBusError{ 075 if(argtypes.length != actual.length) throw new ToolBusError("funcion " + name + " has wrong number of arguments"); 076 077 for(int i = 0; i < argtypes.length; i++){ 078 if(!Functions.compatibleTypes(actual[i], argtypes[i])) throw new ToolBusError(arg(i) + " of " + name + " has type " + actual[i] + " but should have type " + argtypes[i]); 079 } 080 return true; 081 } 082 083 private String[] argNumberStrings = new String[]{"first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"}; 084 085 public String arg(int n){ 086 if(n < argNumberStrings.length) return argNumberStrings[n] + " argument"; 087 088 return "some argument"; 089 } 090 091 public boolean checkRunTime(ATerm actual[]) throws ToolBusException{ 092 if(argtypes.length != actual.length) throw new ToolBusError(name + " has wrong number of arguments"); 093 for(int i = 0; i < argtypes.length; i++){ 094 if(argtypes[i] == tbfactory.BoolType){ 095 if(!tbfactory.isBoolean(actual[i])) throw new ToolBusError(arg(i) + " of " + name + " should have type boolean, got " + actual[i]); 096 }else if(argtypes[i] == tbfactory.IntType){ 097 if(!(actual[i] instanceof ATermInt)) throw new ToolBusError(arg(i) + " of " + name + " should have type integer, got " + actual[i]); 098 }else if(argtypes[i] == tbfactory.RealType){ 099 if(!(actual[i] instanceof ATermReal)) throw new ToolBusError(arg(i) + " of " + name + " should have type real, got " + actual[i]); 100 }else if(argtypes[i] == tbfactory.StrType){ 101 if(!(actual[i] instanceof ATermAppl) || ((ATermAppl) actual[i]).getArity() > 0){ 102 throw new ToolBusError(arg(i) + " of " + name + " should have type string, got " + actual[i]); 103 } 104 }else if(argtypes[i] == tbfactory.TermType){ 105 /* Ignore */ 106 }else if(argtypes[i] == tbfactory.ListType){ 107 if(!(actual[i] instanceof ATermList)) throw new ToolBusError(arg(i) + " of " + name + " should be a list type, got " + actual[i]); 108 }else throw new ToolBusInternalError("check: wrong type " + argtypes[i]); 109 } 110 return true; 111 } 112 113 abstract public ATerm apply(ATerm args[], ProcessInstance pi) throws ToolBusException; 114 } 115 116 public class Functions{ 117 private static Hashtable<String, FunctionDescriptor> Funs; 118 private static TBTermFactory tbfactory; 119 120 public static void init(TBTermFactory tbfac){ 121 tbfactory = tbfac; 122 Funs = new Hashtable<String, FunctionDescriptor>(); 123 defineFuns(); 124 } 125 126 /** 127 * Declaration 128 */ 129 private static void define(FunctionDescriptor fd){ 130 Funs.put(fd.getName(), fd); 131 } 132 133 private static void defineFuns(){ 134 define(new FunctionDescriptor(tbfactory, "is-bool", tbfactory.TermType, tbfactory.BoolType){ 135 public ATerm apply(ATerm args[], ProcessInstance pi){ 136 return tbfactory.isBoolean(args[0]) ? tbfactory.True : tbfactory.False; 137 } 138 }); 139 140 define(new FunctionDescriptor(tbfactory, "is-int", tbfactory.TermType, tbfactory.BoolType){ 141 public ATerm apply(ATerm args[], ProcessInstance pi){ 142 return tbfactory.isInt(args[0]) ? tbfactory.True : tbfactory.False; 143 } 144 }); 145 146 define(new FunctionDescriptor(tbfactory, "is-real", tbfactory.TermType, tbfactory.BoolType){ 147 public ATerm apply(ATerm args[], ProcessInstance pi){ 148 return tbfactory.isReal(args[0]) ? tbfactory.True : tbfactory.False; 149 } 150 }); 151 152 define(new FunctionDescriptor(tbfactory, "is-str", tbfactory.TermType, tbfactory.BoolType){ 153 public ATerm apply(ATerm args[], ProcessInstance pi){ 154 return tbfactory.isStr(args[0]) ? tbfactory.True : tbfactory.False; 155 } 156 }); 157 158 // is-bstr 159 define(new FunctionDescriptor(tbfactory, "is-appl", tbfactory.TermType, tbfactory.BoolType){ 160 public ATerm apply(ATerm args[], ProcessInstance pi){ 161 return tbfactory.isAppl(args[0]) ? tbfactory.True : tbfactory.False; 162 } 163 }); 164 165 define(new FunctionDescriptor(tbfactory, "is-list", tbfactory.TermType, tbfactory.BoolType){ 166 public ATerm apply(ATerm args[], ProcessInstance pi){ 167 return tbfactory.isList(args[0]) ? tbfactory.True : tbfactory.False; 168 } 169 }); 170 171 define(new FunctionDescriptor(tbfactory, "is-empty", tbfactory.TermType, tbfactory.BoolType){ 172 public ATerm apply(ATerm args[], ProcessInstance pi){ 173 // if(args[0] == null){ 174 // return tbfactory.True; 175 // } 176 if(tbfactory.isList(args[0])){ 177 if(((ATermList) args[0]).getLength() == 0) return tbfactory.True; 178 } 179 return tbfactory.False; 180 } 181 }); 182 183 define(new FunctionDescriptor(tbfactory, "int-to-real", tbfactory.IntType, tbfactory.RealType){ 184 public ATerm apply(ATerm args[], ProcessInstance pi){ 185 return tbfactory.makeReal(((ATermInt) args[0]).getInt()); 186 } 187 }); 188 189 define(new FunctionDescriptor(tbfactory, "real-to-int", tbfactory.RealType, tbfactory.IntType){ 190 public ATerm apply(ATerm args[], ProcessInstance pi){ 191 return tbfactory.makeInt((int) ((ATermReal) args[0]).getReal()); 192 } 193 }); 194 195 // is-var, see method eval 196 // is-result-var, see method eval 197 // TODO: is-formal 198 define(new FunctionDescriptor(tbfactory, "fun", tbfactory.TermType, tbfactory.StrType){ 199 public ATerm apply(ATerm args[], ProcessInstance pi){ 200 String fname = ((ATermAppl) args[0]).getName(); 201 return tbfactory.make("<str>", fname); 202 } 203 }); 204 205 define(new FunctionDescriptor(tbfactory, "args", tbfactory.TermType, tbfactory.ListType){ 206 public ATerm apply(ATerm args[], ProcessInstance pi){ 207 return tbfactory.getArgs(args[0]); 208 } 209 }); 210 211 define(new FunctionDescriptor(tbfactory, "true", tbfactory.BoolType){ 212 public ATerm apply(ATerm args[], ProcessInstance pi){ 213 return tbfactory.True; 214 } 215 }); 216 217 define(new FunctionDescriptor(tbfactory, "false", tbfactory.BoolType){ 218 public ATerm apply(ATerm args[], ProcessInstance pi){ 219 return tbfactory.False; 220 } 221 }); 222 223 define(new FunctionDescriptor(tbfactory, "not", tbfactory.BoolType, tbfactory.BoolType){ 224 public ATerm apply(ATerm args[], ProcessInstance pi){ 225 return args[0] == tbfactory.True ? tbfactory.False : tbfactory.True; 226 } 227 }); 228 229 define(new FunctionDescriptor(tbfactory, "and", tbfactory.BoolType, tbfactory.BoolType, tbfactory.BoolType){ 230 public ATerm apply(ATerm args[], ProcessInstance pi){ 231 return (args[0] == tbfactory.True) && (args[1] == tbfactory.True) ? tbfactory.True : tbfactory.False; 232 } 233 }); 234 235 define(new FunctionDescriptor(tbfactory, "or", tbfactory.BoolType, tbfactory.BoolType, tbfactory.BoolType){ 236 public ATerm apply(ATerm args[], ProcessInstance pi){ 237 return (args[0] == tbfactory.True) || (args[1] == tbfactory.True) ? tbfactory.True : tbfactory.False; 238 } 239 }); 240 241 define(new FunctionDescriptor(tbfactory, "equal", tbfactory.TermType, tbfactory.TermType, tbfactory.BoolType){ 242 public ATerm apply(ATerm args[], ProcessInstance pi){ 243 ATerm res = (args[0] == args[1]) ? tbfactory.True : tbfactory.False; 244 // System.err.println("equal: " + args[0] + " == " + args[1] + " ==> " + res); 245 return res; 246 } 247 }); 248 249 define(new FunctionDescriptor(tbfactory, "not-equal", tbfactory.TermType, tbfactory.TermType, tbfactory.BoolType){ 250 public ATerm apply(ATerm args[], ProcessInstance pi){ 251 ATerm res = (args[0] != args[1]) ? tbfactory.True : tbfactory.False; 252 // System.err.println("not-equal: " + args[0] + " == " + args[1] + " ==> " + res); 253 return res; 254 } 255 }); 256 257 define(new FunctionDescriptor(tbfactory, "add", tbfactory.IntType, tbfactory.IntType, tbfactory.IntType){ 258 public ATerm apply(ATerm args[], ProcessInstance pi){ 259 return tbfactory.makeInt(((ATermInt) args[0]).getInt() + ((ATermInt) args[1]).getInt()); 260 } 261 }); 262 263 define(new FunctionDescriptor(tbfactory, "sub", tbfactory.IntType, tbfactory.IntType, tbfactory.IntType){ 264 public ATerm apply(ATerm args[], ProcessInstance pi){ 265 return tbfactory.makeInt(((ATermInt) args[0]).getInt() - ((ATermInt) args[1]).getInt()); 266 } 267 }); 268 269 define(new FunctionDescriptor(tbfactory, "mul", tbfactory.IntType, tbfactory.IntType, tbfactory.IntType){ 270 public ATerm apply(ATerm args[], ProcessInstance pi){ 271 return tbfactory.makeInt(((ATermInt) args[0]).getInt() * ((ATermInt) args[1]).getInt()); 272 } 273 }); 274 275 define(new FunctionDescriptor(tbfactory, "div", tbfactory.IntType, tbfactory.IntType, tbfactory.IntType){ 276 public ATerm apply(ATerm args[], ProcessInstance pi){ 277 return tbfactory.makeInt(((ATermInt) args[0]).getInt() / ((ATermInt) args[1]).getInt()); 278 } 279 }); 280 281 define(new FunctionDescriptor(tbfactory, "mod", tbfactory.IntType, tbfactory.IntType, tbfactory.IntType){ 282 public ATerm apply(ATerm args[], ProcessInstance pi){ 283 return tbfactory.makeInt(((ATermInt) args[0]).getInt() % ((ATermInt) args[1]).getInt()); 284 } 285 }); 286 287 define(new FunctionDescriptor(tbfactory, "abs", tbfactory.IntType, tbfactory.IntType){ 288 public ATerm apply(ATerm args[], ProcessInstance pi){ 289 return tbfactory.makeInt(Math.abs(((ATermInt) args[0]).getInt())); 290 } 291 }); 292 293 define(new FunctionDescriptor(tbfactory, "less", tbfactory.IntType, tbfactory.IntType, tbfactory.BoolType){ 294 public ATerm apply(ATerm args[], ProcessInstance pi){ 295 return ((ATermInt) args[0]).getInt() < ((ATermInt) args[1]).getInt() ? tbfactory.True : tbfactory.False; 296 } 297 }); 298 define(new FunctionDescriptor(tbfactory, "less-equal", tbfactory.IntType, tbfactory.IntType, tbfactory.BoolType){ 299 public ATerm apply(ATerm args[], ProcessInstance pi){ 300 return ((ATermInt) args[0]).getInt() <= ((ATermInt) args[1]).getInt() ? tbfactory.True : tbfactory.False; 301 } 302 }); 303 304 define(new FunctionDescriptor(tbfactory, "greater", tbfactory.IntType, tbfactory.IntType, tbfactory.BoolType){ 305 public ATerm apply(ATerm args[], ProcessInstance pi){ 306 return ((ATermInt) args[0]).getInt() > ((ATermInt) args[1]).getInt() ? tbfactory.True : tbfactory.False; 307 } 308 }); 309 310 define(new FunctionDescriptor(tbfactory, "greater-equal", tbfactory.IntType, tbfactory.IntType, tbfactory.BoolType){ 311 public ATerm apply(ATerm args[], ProcessInstance pi){ 312 return ((ATermInt) args[0]).getInt() >= ((ATermInt) args[1]).getInt() ? tbfactory.True : tbfactory.False; 313 } 314 }); 315 316 define(new FunctionDescriptor(tbfactory, "radd", tbfactory.RealType, tbfactory.RealType, tbfactory.RealType){ 317 public ATerm apply(ATerm args[], ProcessInstance pi){ 318 return tbfactory.makeReal(((ATermReal) args[0]).getReal() + ((ATermReal) args[1]).getReal()); 319 } 320 }); 321 322 define(new FunctionDescriptor(tbfactory, "rsub", tbfactory.RealType, tbfactory.RealType, tbfactory.RealType){ 323 public ATerm apply(ATerm args[], ProcessInstance pi){ 324 return tbfactory.makeReal(((ATermReal) args[0]).getReal() - ((ATermReal) args[1]).getReal()); 325 } 326 }); 327 328 define(new FunctionDescriptor(tbfactory, "rmul", tbfactory.RealType, tbfactory.RealType, tbfactory.RealType){ 329 public ATerm apply(ATerm args[], ProcessInstance pi){ 330 return tbfactory.makeReal(((ATermReal) args[0]).getReal() * ((ATermReal) args[1]).getReal()); 331 } 332 }); 333 define(new FunctionDescriptor(tbfactory, "rdiv", tbfactory.RealType, tbfactory.RealType, tbfactory.RealType){ 334 public ATerm apply(ATerm args[], ProcessInstance pi){ 335 return tbfactory.makeReal(((ATermReal) args[0]).getReal() / ((ATermReal) args[1]).getReal()); 336 } 337 }); 338 339 define(new FunctionDescriptor(tbfactory, "rless", tbfactory.RealType, tbfactory.RealType, tbfactory.BoolType){ 340 public ATerm apply(ATerm args[], ProcessInstance pi){ 341 return ((ATermReal) args[0]).getReal() < ((ATermReal) args[1]).getReal() ? tbfactory.True : tbfactory.False; 342 } 343 }); 344 345 define(new FunctionDescriptor(tbfactory, "rless-equal", tbfactory.RealType, tbfactory.RealType, tbfactory.BoolType){ 346 public ATerm apply(ATerm args[], ProcessInstance pi){ 347 return ((ATermReal) args[0]).getReal() <= ((ATermReal) args[1]).getReal() ? tbfactory.True : tbfactory.False; 348 } 349 }); 350 351 define(new FunctionDescriptor(tbfactory, "rgreater", tbfactory.RealType, tbfactory.RealType, tbfactory.BoolType){ 352 public ATerm apply(ATerm args[], ProcessInstance pi){ 353 return ((ATermReal) args[0]).getReal() > ((ATermReal) args[1]).getReal() ? tbfactory.True : tbfactory.False; 354 } 355 }); 356 define(new FunctionDescriptor(tbfactory, "rgreater-equal", tbfactory.RealType, tbfactory.RealType, tbfactory.BoolType){ 357 public ATerm apply(ATerm args[], ProcessInstance pi){ 358 return ((ATermReal) args[0]).getReal() >= ((ATermReal) args[1]).getReal() ? tbfactory.True : tbfactory.False; 359 } 360 }); 361 362 // sin, cos, atan atan2 exp log log10 sqrt 363 define(new FunctionDescriptor(tbfactory, "rabs", tbfactory.RealType, tbfactory.RealType){ 364 public ATerm apply(ATerm args[], ProcessInstance pi){ 365 return tbfactory.makeReal(Math.abs(((ATermReal) args[0]).getReal())); 366 } 367 }); 368 369 define(new FunctionDescriptor(tbfactory, "size", tbfactory.ListType, tbfactory.IntType){ 370 public ATerm apply(ATerm args[], ProcessInstance pi){ 371 // if(args[0] == null){ 372 // return factory.makeInt(0); 373 // } 374 return tbfactory.makeInt(tbfactory.size(args[0])); 375 } 376 }); 377 378 define(new FunctionDescriptor(tbfactory, "index", tbfactory.ListType, tbfactory.IntType, tbfactory.TermType){ 379 public ATerm apply(ATerm args[], ProcessInstance pi){ 380 return tbfactory.index(args[0], ((ATermInt) args[1]).getInt()); 381 } 382 }); 383 384 define(new FunctionDescriptor(tbfactory, "replace", tbfactory.ListType, tbfactory.IntType, tbfactory.TermType, tbfactory.ListType){ 385 public ATerm apply(ATerm args[], ProcessInstance pi){ 386 return tbfactory.replace(args[0], ((ATermInt) args[1]).getInt(), args[2]); 387 } 388 }); 389 390 define(new FunctionDescriptor(tbfactory, "get", tbfactory.ListType, tbfactory.TermType, tbfactory.TermType){ 391 public ATerm apply(ATerm args[], ProcessInstance pi){ 392 return tbfactory.get(args[0], args[1]); 393 } 394 }); 395 396 define(new FunctionDescriptor(tbfactory, "put", tbfactory.ListType, tbfactory.TermType, tbfactory.TermType, tbfactory.ListType){ 397 public ATerm apply(ATerm args[], ProcessInstance pi){ 398 return tbfactory.put(args[0], args[1], args[2]); 399 } 400 }); 401 402 define(new FunctionDescriptor(tbfactory, "first", tbfactory.ListType, tbfactory.TermType){ 403 public ATerm apply(ATerm args[], ProcessInstance pi){ 404 // if(args[0] == null){ 405 // return null; 406 // } 407 return tbfactory.first(args[0]); 408 } 409 }); 410 411 define(new FunctionDescriptor(tbfactory, "next", tbfactory.ListType, tbfactory.ListType){ 412 public ATerm apply(ATerm args[], ProcessInstance pi){ 413 // if(args[0] == null){ 414 // return null; 415 // } 416 return tbfactory.next(args[0]); 417 } 418 }); 419 420 define(new FunctionDescriptor(tbfactory, "member", tbfactory.TermType, tbfactory.ListType, tbfactory.BoolType){ 421 public ATerm apply(ATerm args[], ProcessInstance pi){ 422 return tbfactory.member(args[0], args[1]) ? tbfactory.True : tbfactory.False; 423 } 424 }); 425 426 define(new FunctionDescriptor(tbfactory, "subset", tbfactory.ListType, tbfactory.ListType, tbfactory.BoolType){ 427 public ATerm apply(ATerm args[], ProcessInstance pi){ 428 return tbfactory.subset(args[0], args[1]) ? tbfactory.True : tbfactory.False; 429 } 430 }); 431 432 define(new FunctionDescriptor(tbfactory, "diff", tbfactory.ListType, tbfactory.ListType, tbfactory.ListType){ 433 public ATerm apply(ATerm args[], ProcessInstance pi){ 434 return tbfactory.diff(args[0], args[1]); 435 } 436 }); 437 438 define(new FunctionDescriptor(tbfactory, "inter", tbfactory.ListType, tbfactory.ListType, tbfactory.ListType){ 439 public ATerm apply(ATerm args[], ProcessInstance pi){ 440 return tbfactory.inter(args[0], args[1]); 441 } 442 }); 443 444 define(new FunctionDescriptor(tbfactory, "join", tbfactory.TermType, tbfactory.TermType, tbfactory.ListType){ 445 public ATerm apply(ATerm args[], ProcessInstance pi){ 446 return tbfactory.join(args[0], args[1]); 447 } 448 }); 449 450 define(new FunctionDescriptor(tbfactory, "concat", tbfactory.StrType, tbfactory.StrType, tbfactory.StrType){ 451 public ATerm apply(ATerm args[], ProcessInstance pi){ 452 return tbfactory.concat(args[0], args[1]); 453 } 454 }); 455 456 // functions 457 define(new FunctionDescriptor(tbfactory, "process-id", tbfactory.IntType){ 458 public ATerm apply(ATerm args[], ProcessInstance pi){ 459 return tbfactory.makeInt(pi.getProcessId()); 460 } 461 }); 462 463 define(new FunctionDescriptor(tbfactory, "process-name", tbfactory.StrType){ 464 public ATerm apply(ATerm args[], ProcessInstance pi){ 465 AFun afun = tbfactory.makeAFun(pi.getProcessName(), 0, true); 466 return tbfactory.makeAppl(afun); 467 } 468 }); 469 470 define(new FunctionDescriptor(tbfactory, "get-property", tbfactory.StrType, tbfactory.StrType){ 471 public ATerm apply(ATerm args[], ProcessInstance pi){ 472 ToolBus tb = pi.getToolBus(); 473 String arg = ((ATermAppl) args[0]).getName(); 474 String val = tb.getProperty(arg); 475 if(val == null){ 476 val = ""; 477 } 478 AFun afun = tbfactory.makeAFun(val, 0, true); 479 return tbfactory.makeAppl(afun); 480 } 481 }); 482 483 // quote 484 // current-time 485 define(new FunctionDescriptor(tbfactory, "current-time", tbfactory.IntType){ 486 public ATerm apply(ATerm args[], ProcessInstance pi){ 487 int n = (int) pi.getRunTime(); 488 return tbfactory.makeInt(n); 489 } 490 }); 491 492 // sec 493 // msec 494 } 495 496 public static ATerm checkStatic(String fun, ATerm args[]) throws ToolBusError{ 497 FunctionDescriptor fd = Funs.get(fun); 498 if(fd == null) throw new ToolBusError("Unknown function: " + fun); 499 500 if(fd.checkStatic(args)) return fd.getResultType(); 501 502 return null; 503 } 504 505 private static ATerm apply(String fun, ATerm args[], ProcessInstance process) throws ToolBusException{ 506 FunctionDescriptor fd = Funs.get(fun); 507 508 if(fd == null){ 509 throw new ToolBusError("Unknown function: " + fun); 510 } 511 fd.checkRunTime(args); // redundant after typecheck! 512 return fd.apply(args, process); 513 } 514 515 public static ATerm eval(ATerm t, ProcessInstance pi, Environment env) throws ToolBusException{ 516 // System.err.println("eval: " + t + "; env = " + env); 517 switch(t.getType()){ 518 519 case ATerm.BLOB: 520 case ATerm.INT: 521 case ATerm.PLACEHOLDER: 522 case ATerm.REAL: 523 return t; 524 525 case TBTermFactory.VAR: 526 return env.getValue((TBTermVar) t); 527 528 case ATerm.APPL: 529 if(tbfactory.isBoolean(t)) return t; 530 if(tbfactory.isStr(t)) return t; 531 String fun = ((ATermAppl) t).getName(); 532 ATerm args[] = ((ATermAppl) t).getArgumentArray(); 533 if(fun == "quote"){ // TODO: check # of args 534 // System.err.println("quote: " + t + " ==> " + tbfactory.substitute(args[0], 535 // env)); 536 return tbfactory.substitute(args[0], env); 537 } 538 if(fun == "is-var") return tbfactory.isVar(args[0]) ? tbfactory.True : tbfactory.False; 539 if(fun == "is-result-var") return tbfactory.isResultVar(args[0]) ? tbfactory.True : tbfactory.False; 540 if(args.length == 0 && !((fun == "process-id") || fun == "process-name")) return t; 541 ATerm vargs[] = new ATerm[args.length]; 542 for(int i = 0; i < args.length; i++){ 543 vargs[i] = eval(args[i], pi, env); 544 } 545 return apply(fun, vargs, pi); 546 547 case ATerm.LIST: 548 ATermList lst = tbfactory.makeList(); 549 ATermList tlst = (ATermList) t; 550 for(int i = tlst.getLength() - 1; i >= 0; i--){ 551 lst = lst.insert(eval(tlst.elementAt(i), pi, env)); 552 } 553 return lst; 554 } 555 throw new ToolBusInternalError("illegal ATerm in eval: " + t); 556 } 557 558 public static ATerm checkType(ATerm t, Environment env, boolean quoted) throws ToolBusException{ 559 // System.err.println("checkType(" + t + ")"); 560 switch(t.getType()){ 561 case ATerm.INT: 562 return tbfactory.IntType; 563 564 case ATerm.PLACEHOLDER: 565 return ((ATermPlaceholder) t).getPlaceholder(); 566 567 case ATerm.REAL: 568 return tbfactory.RealType; 569 570 case ATerm.BLOB: 571 return tbfactory.BlobType; 572 573 case TBTermFactory.VAR: 574 return ((TBTermVar) t).getVarType(); 575 576 case ATerm.APPL: 577 ATermAppl apt = (ATermAppl) t; 578 579 if(apt == tbfactory.Undefined) return tbfactory.Undefined; 580 581 if(tbfactory.isBoolean(apt)){ 582 return tbfactory.BoolType; 583 } 584 if(apt.isQuoted() && apt.getArity() == 0){ 585 return tbfactory.StrType; 586 } 587 String name = apt.getName(); 588 ATerm args[] = apt.getArgumentArray(); 589 if(args.length == 0 && Funs.get(name) == null) return t; 590 if(name == "quote") return checkType(args[0], env, true); 591 592 ATerm vargs[] = new ATerm[args.length]; 593 for(int i = 0; i < args.length; i++){ 594 vargs[i] = checkType(args[i], env, quoted); 595 } 596 if(quoted){ 597 AFun afun = apt.getAFun(); 598 return tbfactory.makeAppl(afun, vargs); 599 } 600 601 return Functions.checkStatic(name, vargs); 602 603 case ATerm.LIST: 604 ATermList lst = tbfactory.makeList(); 605 ATermList tlst = (ATermList) t; 606 for(int i = tlst.getLength() - 1; i >= 0; i--){ 607 lst = lst.insert(checkType(tlst.elementAt(i), env, quoted)); 608 } 609 return lst; 610 } 611 throw new ToolBusInternalError("illegal ATerm in checkType: " + t); 612 } 613 614 /** 615 * compatibleTypeList checks that a list of types is compatible with a given element type 616 * 617 * @param list 618 * the list to be checked 619 * @param elmtype 620 * the required element type 621 * @return boolean 622 */ 623 public static boolean compatibleTypeList(ATermList list, ATerm elmtype){ 624 ATermList lst = list; 625 while(!lst.isEmpty()){ 626 if(!compatibleTypes(lst.getFirst(), elmtype)) return false; 627 628 lst = lst.getNext(); 629 } 630 return true; 631 } 632 633 /** 634 * compatibleTypes checks that two types are compatible 635 * 636 * @param t1 637 * first type 638 * @param t2 639 * second type 640 * @return boolean 641 */ 642 public static boolean compatibleTypes(ATerm t1, ATerm t2){ 643 ATerm term1 = t1; 644 ATerm term2 = t2; 645 646 // System.err.println("compatibleType(" + t1 + ", " + t2 + ")"); 647 648 if(term2 == tbfactory.Undefined) return true; 649 650 if(term1.getType() == ATerm.PLACEHOLDER) term1 = ((ATermPlaceholder) term1).getPlaceholder(); 651 if(tbfactory.isAnyVar(term1)) term1 = ((TBTermVar) term1).getVarType(); 652 653 if(term2.getType() == ATerm.PLACEHOLDER) term2 = ((ATermPlaceholder) term2).getPlaceholder(); 654 if(tbfactory.isAnyVar(term2)) term2 = ((TBTermVar) term2).getVarType(); 655 656 if(term1.equals(term2)) return true; 657 658 if(term1.equals(tbfactory.TermType) || term2.equals(tbfactory.TermType)) return true; 659 660 switch(term1.getType()){ 661 case ATerm.INT: 662 return term2.equals(tbfactory.IntType); 663 case ATerm.REAL: 664 return term2.equals(tbfactory.RealType); 665 case ATerm.BLOB: 666 return term2.equals(tbfactory.BlobType); 667 668 case ATerm.PLACEHOLDER: 669 return compatibleTypes(((ATermPlaceholder) term1).getPlaceholder(), term2); 670 671 case ATerm.APPL: 672 ATermAppl ap1 = (ATermAppl) term1; 673 if(term2.getType() != ATerm.APPL){ 674 if(ap1.getName() == "list" && term2.getType() == ATerm.LIST){ 675 if(ap1.getArity() == 0) return true; 676 677 return compatibleTypeList((ATermList) term2, ap1.getArgument(0)); 678 }else if(term2.getType() == ATerm.INT && term1.equals(tbfactory.IntType)) 679 return true; 680 else if(term2.getType() == ATerm.REAL && term1.equals(tbfactory.RealType)) 681 return true; 682 else if(term2.getType() == ATerm.BLOB && term1.equals(tbfactory.BlobType)) 683 return true; 684 else return false; 685 } 686 687 ATermAppl ap2 = (ATermAppl) term2; 688 // System.err.println("compatibleType: ap1.getName() = " + ap1.getName() + ";" + 689 // "ap2.getName() = " + ap2.getName()); 690 if(term1.equals(tbfactory.StrType) && ap2.getArity() == 0 && ap2.isQuoted()) return true; 691 if(term2.equals(tbfactory.StrType) && ap1.getArity() == 0 && ap1.isQuoted()) return true; 692 if(term1.equals(tbfactory.BoolType) && tbfactory.isBoolean(term2)) return true; 693 if(term2.equals(tbfactory.BoolType) && tbfactory.isBoolean(term1)) return true; 694 if(ap1.getName() != ap2.getName()) return false; 695 if(ap1.getArity() == 0 || ap2.getArity() == 0) return true; 696 if(ap1.getArity() != ap2.getArity()) return false; 697 for(int i = 0; i < ap1.getArity() - 1; i++){ 698 if(!compatibleTypes(ap1.getArgument(i), ap2.getArgument(i))) return false; 699 } 700 return true; 701 702 case ATerm.LIST: 703 if(term2.getType() == ATerm.LIST){ 704 ATermList lst1 = (ATermList) term1; 705 ATermList lst2 = (ATermList) term2; 706 if(lst1.getLength() != lst2.getLength()) return false; 707 for(; !lst1.isEmpty(); lst1 = lst1.getNext(), lst2 = lst2.getNext()){ 708 if(!compatibleTypes(lst1.getFirst(), lst2.getFirst())) return false; 709 } 710 return true; 711 } 712 if(term2.getType() == ATerm.APPL){ 713 ATermAppl ap = (ATermAppl) term2; 714 if(ap.getName() == "list"){ 715 if(ap.getArity() == 0) return true; 716 717 return compatibleTypeList((ATermList) term1, ap.getArgument(0)); 718 } 719 720 return false; 721 } 722 } 723 throw new ToolBusInternalError("Illegal ATerm in compareType: " + term1); 724 } 725 }