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 }