00001
00002
00003
00004 #include "typing.h"
00005 #include "functions.h"
00006 #define RE_ERROR(x) if(x) {goto error;}
00007 #define RE_ERROR2(x,y) if(x) {localErrorMsg=(y);goto error;}
00008 #define N_BASE_TYPES 7
00009 NodeType baseTypes[N_BASE_TYPES] = {
00010 T_INT,
00011 T_BOOL,
00012 T_DOUBLE,
00013 T_DATETIME,
00014 T_STRING,
00015 T_PATH,
00016 T_IRODS,
00017 };
00018 void doNarrow(Node **l, Node **r, int ln, int rn, int flex, Node **nl, Node **nr, int *nln, int *nrn);
00019 Satisfiability createSimpleConstraint(ExprType *a, ExprType *b, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r);
00020 ExprType *createType(ExprType *t, Node **nc, int nn, Hashtable *typingEnv, Hashtable *equivalence, Region *r);
00021 ExprType *getFullyBoundedVar(Region *r);
00022
00023
00024
00025
00026
00027 int typeParameters(ExprType** paramTypes, int len, Node** subtrees, int dynamictyping, Env* funcDesc, Hashtable *symbol_type_table, List *typingConstraints, rError_t *errmsg, Node **errnode, Region *r) {
00028 int i;
00029 for(i=0;i<len;i++) {
00030 paramTypes[i] = dereference(typeExpression3(subtrees[i], dynamictyping, funcDesc, symbol_type_table, typingConstraints, errmsg, errnode, r), symbol_type_table, r);
00031 if(getNodeType(paramTypes[i]) == T_ERROR) {
00032 return i;
00033 }
00034 }
00035 return -1;
00036 }
00037
00038 int tautologyLt(ExprType *type, ExprType *expected) {
00039
00040 if(typeEqSyntatic(type, expected)) {
00041 return 1;
00042 }
00043 if(getNodeType(type)==T_DYNAMIC) {
00044 return 0;
00045 }
00046 if(getNodeType(expected)==T_DYNAMIC) {
00047 return 1;
00048 }
00049 int i;
00050 ExprType a, b;
00051 if (getNodeType(type) == T_VAR) {
00052 if(T_VAR_NUM_DISJUNCTS(type) > 0) {
00053 for(i=0;i<T_VAR_NUM_DISJUNCTS(type);i++) {
00054 setNodeType(&a, getNodeType(T_VAR_DISJUNCT(type,i)));
00055 if(!tautologyLt(&a, expected)) {
00056 return 0;
00057 }
00058 }
00059 return 1;
00060 } else {
00061 return 0;
00062 }
00063
00064 } else if (getNodeType(expected) == T_VAR) {
00065 if(T_VAR_NUM_DISJUNCTS(expected) > 0) {
00066 for(i=0;i<T_VAR_NUM_DISJUNCTS(expected);i++) {
00067 setNodeType(&b, getNodeType(T_VAR_DISJUNCT(expected,i)));
00068 if(!tautologyLt(type, &b)) {
00069 return 0;
00070 }
00071 }
00072 return 1;
00073 } else {
00074 return 0;
00075 }
00076 } else if ((getNodeType(type) == T_CONS && getNodeType(expected) == T_CONS) || (getNodeType(type) == T_TUPLE && getNodeType(expected) == T_TUPLE) ) {
00077 if(getNodeType(type) == T_CONS && strcmp(T_CONS_TYPE_NAME(type), T_CONS_TYPE_NAME(expected))!=0) {
00078 return 0;
00079 }
00080 int i;
00081 for(i=0;i<T_CONS_ARITY(type);i++) {
00082 if(tautologyLt(T_CONS_TYPE_ARG(type, 0), T_CONS_TYPE_ARG(expected, 0))==0) {
00083 return 0;
00084 }
00085 }
00086 return 1;
00087 } else {
00088 return tautologyLtBase(type, expected);
00089 }
00090 }
00091 char *getBaseTypeOrTVarId(ExprType *a, char buf[128]) {
00092 if(isBaseType(a)) {
00093 snprintf(buf, 128, "%s", typeName_ExprType(a));
00094 } else {
00095 getTVarName(T_VAR_ID(a), buf);
00096 }
00097 return buf;
00098 }
00099 int tautologyLtBase(ExprType *a, ExprType *b) {
00100 if(getNodeType(a) != T_IRODS && getNodeType(a) == getNodeType(b)) {
00101 return 1;
00102 }
00103 if(getNodeType(a) == T_INT && getNodeType(b) == T_DOUBLE) {
00104 return 1;
00105 }
00106 if(getNodeType(a) == T_IRODS && getNodeType(b)==T_IRODS && (a->text==NULL || b->text == NULL || strcmp(a->text, b->text) == 0)) {
00107 return 1;
00108 }
00109 int i;
00110 if(a->exprType != 0 && TYPE(a) == T_VAR) {
00111 for(i = 0; i < a->exprType->degree; i++) {
00112 if(typeEqSyntatic(a->exprType->subtrees[i], b)) {
00113 return 1;
00114 }
00115 }
00116 }
00117 return 0;
00118 }
00119 int occursIn(ExprType *var, ExprType *type) {
00120 if(getNodeType(type) == T_VAR) {
00121 return T_VAR_ID(var) == T_VAR_ID(type);
00122 } else {
00123 int i;
00124 for(i=0;i<type->degree;i++) {
00125 if(occursIn(var, type->subtrees[i])) {
00126 return 1;
00127 }
00128 }
00129 return 0;
00130 }
00131 }
00132 ExprType* getEquivalenceClassRep(ExprType *varOrBase, Hashtable *equivalence) {
00133 ExprType *equiv1 = NULL, *equiv2;
00134 char name[128];
00135 equiv2 = varOrBase;
00136 int ref = 0;
00137 while(equiv2 != NULL) {
00138 equiv1 = equiv2;
00139 equiv2 = (ExprType *) lookupFromHashTable(equivalence, getBaseTypeOrTVarId(equiv1, name));
00140 ref ++;
00141 }
00142 if(ref > 1) {
00143 updateInHashTable(equivalence, getBaseTypeOrTVarId(varOrBase, name), equiv1);
00144 }
00145 return equiv1;
00146
00147 }
00148
00149
00150 int occursInEquiv(ExprType *var, ExprType *type, Hashtable *equivalence) {
00151 if(getNodeType(type) == T_VAR && isBaseType(type)) {
00152 ExprType *varEquiv = getEquivalenceClassRep(var, equivalence);
00153 ExprType *typeEquiv = getEquivalenceClassRep(type, equivalence);
00154 return typeEqSyntatic(varEquiv, typeEquiv);
00155 } else {
00156 int i;
00157 for(i=0;i<type->degree;i++) {
00158 if(occursInEquiv(var, type->subtrees[i], equivalence)) {
00159 return 1;
00160 }
00161 }
00162 return 0;
00163 }
00164 }
00165
00166 Satisfiability splitVarR(ExprType *consTuple, ExprType *var, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00167 if(occursInEquiv(var, consTuple, equivalence) || isBaseType(getEquivalenceClassRep(var, equivalence))) {
00168 return ABSURDITY;
00169 }
00170 char tvarname[128];
00171 ExprType **typeArgs = (ExprType **) region_alloc(r, sizeof(ExprType *) * T_CONS_ARITY(consTuple));
00172 int i;
00173 ExprType *type;
00174 for(i=0;i<T_CONS_ARITY(consTuple);i++) {
00175 typeArgs[i] = newTVar(r);
00176 }
00177 if(getNodeType(consTuple) == T_CONS) {
00178 type = newConsType(T_CONS_ARITY(consTuple), T_CONS_TYPE_NAME(consTuple), typeArgs, r);
00179 } else {
00180 type = newTupleType(T_CONS_ARITY(consTuple), typeArgs, r);
00181 }
00182 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(var), tvarname), type);
00183 return splitConsOrTuple(consTuple, type, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00184
00185 }
00186 Satisfiability splitVarL(ExprType *var, ExprType *consTuple, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00187 if(occursInEquiv(var, consTuple, equivalence) || isBaseType(getEquivalenceClassRep(var, equivalence))) {
00188 return ABSURDITY;
00189 }
00190 char tvarname[128];
00191 ExprType **typeArgs = (ExprType **) region_alloc(r, sizeof(ExprType *) * T_CONS_ARITY(consTuple));
00192 int i;
00193 ExprType *type;
00194 for(i=0;i<T_CONS_ARITY(consTuple);i++) {
00195 typeArgs[i] = newTVar(r);
00196 }
00197 if(getNodeType(consTuple) == T_CONS) {
00198 type = newConsType(T_CONS_ARITY(consTuple), T_CONS_TYPE_NAME(consTuple), typeArgs, r);
00199 } else {
00200 type = newTupleType(T_CONS_ARITY(consTuple), typeArgs, r);
00201 }
00202 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(var), tvarname), type);
00203 return splitConsOrTuple(type, consTuple, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00204
00205 }
00206
00207
00208
00209
00210
00211
00212
00213 Satisfiability simplifyR(ExprType *a, ExprType *b, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00214 ExprType *bm;
00215 if(T_VAR_NUM_DISJUNCTS(b) == 0) {
00216 bm = getFullyBoundedVar(r);
00217 } else {
00218 bm = b;
00219 }
00220 Node *cl[MAX_NUM_DISJUNCTS], *cr[MAX_NUM_DISJUNCTS];
00221 int nln, nrn;
00222 doNarrow(&a, T_VAR_DISJUNCTS(bm), 1, T_VAR_NUM_DISJUNCTS(bm), flex, cl, cr, &nln, &nrn);
00223 ExprType *bn;
00224 if(nrn == 0) {
00225 return ABSURDITY;
00226 } else {
00227 bn = createType(b, cr, nrn, typingEnv, equivalence, r);
00228 if(bn == b) {
00229 return TAUTOLOGY;
00230 }
00231 return createSimpleConstraint(a, bn, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00232 }
00233 }
00234
00235 ExprType *getFullyBoundedVar(Region *r) {
00236 ExprType **ds = (ExprType **) region_alloc(r, sizeof(ExprType *) * N_BASE_TYPES);
00237 int i;
00238 for(i=0;i<N_BASE_TYPES;i++) {
00239 ds[i] = newSimpType(baseTypes[i], r);
00240 }
00241 ExprType *var = newTVar2(N_BASE_TYPES, ds, r);
00242 return var;
00243 }
00244
00245 Satisfiability simplifyL(ExprType *a, ExprType *b, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00246 ExprType *am;
00247 if(T_VAR_NUM_DISJUNCTS(a) == 0) {
00248 am = getFullyBoundedVar(r);
00249 } else {
00250 am = a;
00251 }
00252 Node *cl[MAX_NUM_DISJUNCTS], *cr[MAX_NUM_DISJUNCTS];
00253 int nln, nrn;
00254 doNarrow(T_VAR_DISJUNCTS(am), &b, T_VAR_NUM_DISJUNCTS(am), 1, flex, cl, cr, &nln, &nrn);
00255 ExprType *an;
00256 if(nln == 0) {
00257 return ABSURDITY;
00258 } else {
00259 an = createType(a, cl, nln, typingEnv, equivalence, r);
00260 if(an == a) {
00261 return TAUTOLOGY;
00262 }
00263 return createSimpleConstraint(an, b, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00264 }
00265
00266 }
00267
00268 void addToEquivalenceClass(ExprType *a, ExprType *b, Hashtable *equivalence) {
00269 char name[128];
00270 ExprType *an = getEquivalenceClassRep(a, equivalence);
00271 ExprType *bn = getEquivalenceClassRep(b, equivalence);
00272 if(!typeEqSyntatic(an, bn)) {
00273 if(isBaseType(an)) {
00274 insertIntoHashTable(equivalence, getTVarName(T_VAR_ID(bn), name), an);
00275 } else {
00276 insertIntoHashTable(equivalence, getTVarName(T_VAR_ID(an), name), bn);
00277 }
00278 }
00279 }
00280 void doNarrow(Node **l, Node **r, int ln, int rn, int flex, Node **nl, Node **nr, int *nln, int *nrn) {
00281 Node *retl[MAX_NUM_DISJUNCTS], *retr[MAX_NUM_DISJUNCTS];
00282 int i,k;
00283 for(i=0;i<ln;i++) {
00284 retl[i] = NULL;
00285 }
00286 for(k=0;k<rn;k++) {
00287 retr[k] = NULL;
00288 }
00289 for(k=0;k<rn;k++) {
00290 for(i=0;i<ln;i++) {
00291 if(applyBaseTypeRule(l[i], r[k], flex) == TAUTOLOGY) {
00292 retl[i] = l[i];
00293 retr[k] = r[k];
00294 if(getNodeType(l[i]) == T_IRODS && l[i]->text == NULL) {
00295 retl[i] = retr[k];
00296 }
00297 if(getNodeType(r[k]) == T_IRODS && r[k]->text == NULL) {
00298 retr[k] = retl[i];
00299 }
00300
00301 }
00302 }
00303 }
00304 *nln = 0;
00305 for(i=0;i<ln;i++) {
00306 if(retl[i]!=NULL) {
00307 nl[(*nln)++] = retl[i];
00308 }
00309 }
00310 *nrn = 0;
00311 for(k=0;k<rn;k++) {
00312 if(retr[k]!=NULL) {
00313 nr[(*nrn)++] = retr[k];
00314 }
00315 }
00316 }
00317
00318 Satisfiability createSimpleConstraint(ExprType *a, ExprType *b, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00319 char name[128];
00320 if(isBaseType(a) && isBaseType(b)) {
00321 return TAUTOLOGY;
00322 } else {
00323 addToEquivalenceClass(a, b, equivalence);
00324 if(flex) {
00325 listAppend(simpleTypingConstraints, newTypingConstraint(a, newUnaryType(T_FLEX, b, r), TC_LT, node, r), r);
00326 return CONTINGENCY;
00327 } else {
00328 if((getNodeType(a) == T_VAR && T_VAR_NUM_DISJUNCTS(a)==0) || isBaseType(b)) {
00329 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(a), name), b);
00330 } else if((getNodeType(b) == T_VAR && T_VAR_NUM_DISJUNCTS(b)==0) || isBaseType(a)) {
00331 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(b), name), a);
00332 } else {
00333 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(a), name), b);
00334 }
00335 return TAUTOLOGY;
00336 }
00337 }
00338 }
00339 ExprType *createType(ExprType *t, Node **nc, int nn, Hashtable *typingEnv, Hashtable *equivalence, Region *r) {
00340 char name[128];
00341 ExprType *gcd;
00342 if (nn == T_VAR_NUM_DISJUNCTS(t)) {
00343 gcd = t;
00344 } else {
00345 if(nn==1) {
00346 gcd = *nc;
00347 } else {
00348 gcd = newTVar2(nn, nc, r);
00349 }
00350 insertIntoHashTable(typingEnv, getTVarName(T_VAR_ID(t), name), gcd);
00351 addToEquivalenceClass(t, gcd, equivalence);
00352 }
00353 return gcd;
00354 }
00355 Satisfiability narrow(ExprType *type, ExprType *expected, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00356
00357 if(T_VAR_ID(type) == T_VAR_ID(expected)) {
00358 return TAUTOLOGY;
00359 } else if(T_VAR_NUM_DISJUNCTS(type) > 0 && T_VAR_NUM_DISJUNCTS(expected) > 0) {
00360 int nln, nrn;
00361 Node *cl[100], *cr[100];
00362 doNarrow(T_VAR_DISJUNCTS(type), T_VAR_DISJUNCTS(expected), T_VAR_NUM_DISJUNCTS(type), T_VAR_NUM_DISJUNCTS(expected), flex, cl, cr, &nln, &nrn);
00363 ExprType *an;
00364 ExprType *bn;
00365 if(nln == 0 || nrn == 0) {
00366 return ABSURDITY;
00367 } else {
00368 an = createType(type, cl, nln, typingEnv, equivalence, r);
00369 bn = createType(expected, cr, nrn, typingEnv, equivalence, r);
00370 }
00371 return createSimpleConstraint(an, bn, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00372 } else if(T_VAR_NUM_DISJUNCTS(type)==0) {
00373 return createSimpleConstraint(type, expected, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00374 } else {
00375 return createSimpleConstraint(type, expected, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00376 }
00377 }
00378 #define logicalAnd(a, b, c) \
00379 { \
00380 switch(a) { \
00381 case ABSURDITY: \
00382 (c) = ABSURDITY; \
00383 case CONTINGENCY: \
00384 (c) = (b) == ABSURDITY ? ABSURDITY : CONTINGENCY; \
00385 case TAUTOLOGY: \
00386 (c) = (b); \
00387 } \
00388 }
00389
00390 Satisfiability splitConsOrTuple(ExprType *a, ExprType *b, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00391
00392 if((getNodeType(a) == T_CONS && strcmp(T_CONS_TYPE_NAME(a), T_CONS_TYPE_NAME(b)) != 0) ||
00393 T_CONS_ARITY(a) != T_CONS_ARITY(b)) {
00394 return ABSURDITY;
00395 } else {
00396 int i;
00397 Satisfiability ret = TAUTOLOGY;
00398 for(i=0;i<T_CONS_ARITY(a);i++) {
00399 ExprType *simpa = T_CONS_TYPE_ARG(a, i);
00400 ExprType *simpb = T_CONS_TYPE_ARG(b, i);
00401 Satisfiability sat = simplifyLocally(simpa, simpb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00402 switch(sat) {
00403 case ABSURDITY:
00404 return ABSURDITY;
00405 case TAUTOLOGY:
00406 break;
00407 case CONTINGENCY:
00408 ret = CONTINGENCY;
00409 break;
00410 }
00411
00412 }
00413 return ret;
00414 }
00415 }
00416
00417
00418 int isBaseType(ExprType *t) {
00419 int i;
00420 for(i=0;i<N_BASE_TYPES;i++) {
00421 if(getNodeType(t) == baseTypes[i]) {
00422 return 1;
00423 }
00424 }
00425 return 0;
00426 }
00427
00428 int applyBaseTypeRule(ExprType *tca, ExprType *tcb, int flex)
00429 {
00430 return (flex && tautologyLtBase(tca, tcb)) ||
00431 (!flex && ((getNodeType(tca) == T_IRODS && getNodeType(tcb) == T_IRODS && (tca->text == NULL || tcb->text == NULL)) ||
00432 typeEqSyntatic(tca, tcb)));
00433 }
00434
00435 int baseRuleApplies(ExprType *ta, ExprType *tb, int flex, ExprType **templa, ExprType **templb, Region *r) {
00436 if(isBaseType(ta) && isBaseType(tb) && applyBaseTypeRule(ta, tb, flex)) {
00437 *templa = ta;
00438 *templb = tb;
00439 return 1;
00440 } else if(flex && isIterableBaseRuleType(ta, templa, templb, r) && getNodeType(tb) == T_CONS) {
00441 return 1;
00442 } else {
00443 return 0;
00444 }
00445 }
00446
00447 Satisfiability simplifyLocally(ExprType *tca, ExprType *tcb, int flex, Node *node, Hashtable *typingEnv, Hashtable *equivalence, List *simpleTypingConstraints, Region *r) {
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461 if(tca == tcb) {
00462 return TAUTOLOGY;
00463 }
00464
00465 if(getNodeType(tcb) == T_FLEX) {
00466 tcb = tcb->subtrees[0];
00467 flex = 1;
00468 } else if(getNodeType(tcb) == T_FIXD) {
00469 tcb = tcb->subtrees[0];
00470 }
00471
00472 tca = dereference(tca, typingEnv, r);
00473 tcb = dereference(tcb, typingEnv, r);
00474
00475 ExprType *templa, *templb;
00476
00477 if(getNodeType(tca) == T_UNSPECED || getNodeType(tca) == T_DYNAMIC || getNodeType(tcb) == T_DYNAMIC) {
00478 return TAUTOLOGY;
00479 }
00480 else if(baseRuleApplies(tca, tcb, flex, &templa, &templb, r)) {
00481 Satisfiability c;
00482 logicalAnd(simplifyLocally(tca, templa, flex, node, typingEnv, equivalence, simpleTypingConstraints, r),
00483 simplifyLocally(templb, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r), c);
00484 return c;
00485 } else if(getNodeType(tca) == T_VAR && getNodeType(tcb) == T_VAR) {
00486 return narrow(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00487
00488 } else if(getNodeType(tca)==T_VAR && isBaseType(tcb)) {
00489 return simplifyL(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00490
00491 } else if(getNodeType(tcb)==T_VAR && isBaseType(tca)) {
00492 return simplifyR(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00493
00494 } else if(getNodeType(tca)==T_VAR && (getNodeType(tcb) == T_CONS || getNodeType(tcb) == T_TUPLE)) {
00495 return splitVarL(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00496
00497 } else if(getNodeType(tcb)==T_VAR && (getNodeType(tca) == T_CONS || getNodeType(tca) == T_TUPLE)) {
00498 return splitVarR(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00499
00500 } else if((getNodeType(tca) == T_CONS && getNodeType(tcb) == T_CONS)
00501 || (getNodeType(tca) == T_TUPLE && getNodeType(tcb) == T_TUPLE)) {
00502 return splitConsOrTuple(tca, tcb, flex, node, typingEnv, equivalence, simpleTypingConstraints, r);
00503 } else {
00504 return ABSURDITY;
00505 }
00506 }
00507
00508
00509
00510
00511 Satisfiability solveConstraints(List *typingConstraints, Hashtable *typingEnv, rError_t *errmsg, Node ** errnode, Region *r) {
00512
00513
00514
00515
00516
00517 ListNode *nextNode = NULL;
00518 do {
00519 Satisfiability sat = simplify(typingConstraints, typingEnv, errmsg, errnode, r);
00520 if(sat == ABSURDITY) {
00521 return ABSURDITY;
00522 }
00523 int changed = 0;
00524 nextNode = typingConstraints->head;
00525 while(nextNode!=NULL && !changed) {
00526 TypingConstraint *tc = (TypingConstraint *)nextNode->value;
00527
00528
00529
00530
00531 ExprType *a = dereference(TC_A(tc), typingEnv, r);
00532 ExprType *b = dereference(TC_B(tc), typingEnv, r);
00533 if(getNodeType(b) == T_FLEX || getNodeType(b) == T_FIXD) {
00534 b = b->subtrees[0];
00535 }
00536
00537
00538
00539
00540 if (getNodeType(a) == T_VAR && getNodeType(b) == T_VAR && T_VAR_ID(a) == T_VAR_ID(b)) {
00541 listRemove(typingConstraints, nextNode);
00542 nextNode = typingConstraints->head;
00543 changed = 1;
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566 } else if (getNodeType(a) != T_VAR && getNodeType(b) != T_VAR) {
00567 printf("error: simplified type does not have variable on either side.\n");
00568 } else {
00569 nextNode = nextNode->next;
00570 }
00571
00572 }
00573 } while(nextNode != NULL);
00574 if(!consistent(typingConstraints, typingEnv, r)) {
00575 return ABSURDITY;
00576 }
00577 return typingConstraints->head == NULL ? TAUTOLOGY : CONTINGENCY;
00578 }
00579
00580 int consistent(List *typingConstraints, Hashtable *typingEnv, Region *r) {
00581 return 1;
00582 }
00583 Satisfiability simplify(List *typingConstraints, Hashtable *typingEnv, rError_t *errmsg, Node **errnode, Region *r) {
00584 ListNode *ln;
00585 int changed;
00586 Hashtable *equivalence = newHashTable2(10, r);
00587 List *simpleTypingConstraints = newList(r);
00588
00589
00590
00591 Satisfiability ret = TAUTOLOGY;
00592 do {
00593 changed = typingEnv->len;
00594 ln = typingConstraints->head;
00595
00596
00597 while(ln!=NULL) {
00598 TypingConstraint *tc = (TypingConstraint *)ln->value;
00599 switch(simplifyLocally(TC_A(tc), TC_B(tc), 0, TC_NODE(tc), typingEnv, equivalence, simpleTypingConstraints, r)) {
00600 case TAUTOLOGY:
00601 break;
00602 case CONTINGENCY:
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 ret = CONTINGENCY;
00614 break;
00615 case ABSURDITY:
00616 *errnode = TC_NODE(tc);
00617 char errmsgbuf1[ERR_MSG_LEN], errmsgbuf2[ERR_MSG_LEN], buf2[1024], buf3[1024];
00618 snprintf(errmsgbuf1, ERR_MSG_LEN, "simplify: unsolvable typing constraint %s < %s.\n", typeToString(TC_A(tc), typingEnv, buf2, 1024), typeToString(TC_B(tc), typingEnv, buf3, 1024));
00619 generateErrMsg(errmsgbuf1, NODE_EXPR_POS((*errnode)), (*errnode)->base, errmsgbuf2);
00620 addRErrorMsg(errmsg, RE_TYPE_ERROR, errmsgbuf2);
00621
00622
00623 return ABSURDITY;
00624 }
00625 ln = ln->next;
00626 }
00627
00628
00629
00630
00631 typingConstraints->head = simpleTypingConstraints->head;
00632 typingConstraints->tail = simpleTypingConstraints->tail;
00633 simpleTypingConstraints->head = simpleTypingConstraints->tail = NULL;
00634 } while(changed < typingEnv->len);
00635
00636 return ret;
00637 }
00638
00639
00640
00641 ExprType *getElemType(ExprType *type, Region *r) {
00642 if(getNodeType(type) == T_STRING) {
00643 return newSimpType(T_STRING, r);
00644 } else if(getNodeType(type) == T_PATH || strcmp(type->text, CollInp_MS_T) == 0){
00645 return newIRODSType(DataObjInp_MS_T, r);
00646 } else if(strcmp(type->text, IntArray_MS_T) == 0) {
00647 return newSimpType(T_INT, r);
00648 } else if(strcmp(type->text, StrArray_MS_T) == 0) {
00649 return newSimpType(T_STRING, r);
00650 } else if(strcmp(type->text, GenQueryOut_MS_T) == 0) {
00651 return newIRODSType(KeyValPair_MS_T, r);
00652 }
00653 return NULL;
00654 }
00655
00656
00657
00658
00659 int isIterableBaseRuleType(ExprType *type, ExprType **templa, ExprType **templb, Region *r) {
00660 int nodeType = getNodeType(type);
00661 char *typeName = type->text;
00662 switch(nodeType) {
00663 case T_IRODS:
00664 if(strcmp(typeName, CollInp_MS_T) == 0) {
00665 *templa = type;
00666 } else if(strcmp(typeName, IntArray_MS_T) == 0) {
00667 *templa = type;
00668 } else if(strcmp(typeName, StrArray_MS_T) == 0) {
00669 *templa = type;
00670 } else if(strcmp(typeName, GenQueryOut_MS_T) == 0) {
00671 *templa = type;
00672 } else {
00673 return 0;
00674 }
00675 *templb = newCollType(getElemType(type, r), r);
00676 return 1;
00677 case T_STRING:
00678 *templa = type;
00679 *templb = newCollType(newSimpType(T_STRING, r), r);
00680 return 1;
00681 case T_PATH:
00682 *templa = type;
00683 *templb = newCollType(getElemType(type, r), r);
00684 return 1;
00685 case T_TUPLE:
00686 if(T_CONS_ARITY(type)==2) {
00687 ExprType **compTypes = (ExprType **)region_alloc(r, sizeof(ExprType *) * 2);
00688 compTypes[0] = newIRODSType(GenQueryInp_MS_T, r);
00689 compTypes[1] = newIRODSType(GenQueryOut_MS_T, r);
00690 *templa = newTupleType(2, compTypes, r);
00691 *templb = newCollType(newIRODSType(KeyValPair_MS_T, r), r);
00692 return 1;
00693 } else {
00694 return 0;
00695 }
00696 default:
00697 return 0;
00698 }
00699 }
00700
00701
00702
00703
00704 ExprType* isIterable(ExprType *type, int dynamictyping, Hashtable* var_type_table, Region *r) {
00705 ExprType *derefedType = dereference(type, var_type_table, r);
00706 Node *disjuncts[6];
00707 Res *unified, *comp0, *comp1;
00708 switch(getNodeType(derefedType)) {
00709 case T_CONS:
00710 if(strcmp(type->text, LIST) == 0) {
00711
00712 return dereference(T_CONS_TYPE_ARG(derefedType, 0), var_type_table, r);
00713 } else {
00714 return NULL;
00715 }
00716 case T_VAR:
00717 if(T_VAR_NUM_DISJUNCTS(derefedType)==0) {
00718
00719 unifyTVarL(derefedType, newCollType(newTVar(r), r), var_type_table, r);
00720 derefedType = dereference(derefedType, var_type_table, r);
00721 return dereference(T_CONS_TYPE_ARG(derefedType, 0), var_type_table, r);
00722 }
00723
00724 case T_IRODS:
00725 case T_STRING:
00726 case T_PATH:
00727 disjuncts[0] = newSimpType(T_STRING, r);
00728 disjuncts[1] = newIRODSType(CollInp_MS_T, r);
00729 disjuncts[2] = newIRODSType(IntArray_MS_T, r);
00730 disjuncts[3] = newIRODSType(StrArray_MS_T, r);
00731 disjuncts[4] = newIRODSType(GenQueryOut_MS_T, r);
00732 disjuncts[5] = newSimpType(T_PATH, r);
00733
00734 unified = unifyTVarL(derefedType, newTVar2(6, disjuncts, r), var_type_table, r);
00735 if(getNodeType(unified) == T_ERROR) {
00736 return NULL;
00737 }
00738 if(unified->nodeType == T_VAR) {
00739 Node *disjunctsElem[4];
00740 int i;
00741 for(i=0;i<T_VAR_NUM_DISJUNCTS(unified);i++) {
00742 disjunctsElem[i] = getElemType(T_VAR_DISJUNCT(unified, i), r);
00743 }
00744 return newTVar2(T_VAR_NUM_DISJUNCTS(unified), disjunctsElem, r);
00745 } else {
00746 return getElemType(unified, r);
00747 }
00748 case T_TUPLE:
00749 if(T_CONS_ARITY(derefedType)!=2)
00750 return NULL;
00751 comp0 = dereference(T_CONS_TYPE_ARG(derefedType, 0), var_type_table, r);
00752 comp1 = dereference(T_CONS_TYPE_ARG(derefedType, 1), var_type_table, r);
00753 if(getNodeType(comp0) != T_IRODS ||
00754 strcmp(T_CONS_TYPE_NAME(comp0), GenQueryInp_MS_T) !=0 ||
00755 getNodeType(comp1) != T_IRODS ||
00756 strcmp(T_CONS_TYPE_NAME(comp1), GenQueryOut_MS_T) !=0) {
00757 return NULL;
00758 }
00759 return newIRODSType(KeyValPair_MS_T, r);
00760
00761 case T_DYNAMIC:
00762 return type;
00763 default:
00764 return NULL;
00765 }
00766 }
00767
00768
00769 ExprType* typeFunction3(Node* node, int dynamictyping, Env* funcDesc, Hashtable* var_type_table, List *typingConstraints, rError_t *errmsg, Node **errnode, Region *r) {
00770
00771 int i;
00772 char *localErrorMsg;
00773 ExprType *res3 = NULL;
00774
00775
00776
00777 Node *fn = node->subtrees[0];
00778 Node *arg = node->subtrees[1];
00779 char buf[ERR_MSG_LEN];
00780
00781 char typebuf[ERR_MSG_LEN];
00782 char typebuf2[ERR_MSG_LEN];
00783
00784 if(getNodeType(fn) == TK_TEXT && strcmp(fn->text, "foreach") == 0) {
00785 RE_ERROR2(getNodeType(arg) != N_TUPLE || arg->degree != 3,"wrong number of arguments to microservice");
00786 RE_ERROR2(getNodeType(arg->subtrees[0])!=TK_VAR,"argument form error");
00787 char* varname = arg->subtrees[0]->text;
00788 ExprType *varType0 = (ExprType *)lookupFromHashTable(var_type_table, varname);
00789 ExprType *varType;
00790 ExprType *collType = varType0 == NULL? NULL:dereference(varType0, var_type_table, r);
00791 if(collType!=NULL) {
00792 varType = isIterable(collType, dynamictyping, var_type_table, r);
00793 if(varType == NULL) {
00794
00795 RE_ERROR2(1, "foreach is applied to a non collection type");
00796 }
00797 } else {
00798 varType = newTVar(r);
00799 collType = newCollType(varType, r);
00800 }
00801 if(varType0 == NULL) {
00802 insertIntoHashTable(var_type_table, varname, varType);
00803 } else {
00804 updateInHashTable(var_type_table, varname, varType);
00805 }
00806 arg->subtrees[0]->exprType = collType;
00807 res3 = typeExpression3(arg->subtrees[1], dynamictyping, funcDesc, var_type_table,typingConstraints,errmsg,errnode,r);
00808 RE_ERROR2(getNodeType(res3) == T_ERROR, "foreach loop type error");
00809 res3 = typeExpression3(arg->subtrees[2], dynamictyping, funcDesc, var_type_table,typingConstraints,errmsg,errnode,r);
00810 RE_ERROR2(getNodeType(res3) == T_ERROR, "foreach recovery type error");
00811 setIOType(arg->subtrees[0], IO_TYPE_EXPRESSION);
00812 for(i = 1;i<3;i++) {
00813 setIOType(arg->subtrees[i], IO_TYPE_ACTIONS);
00814 }
00815 ExprType **typeArgs = allocSubtrees(r, 3);
00816 typeArgs[0] = collType;
00817 typeArgs[1] = newTVar(r);
00818 typeArgs[2] = newTVar(r);
00819 arg->coercionType = newTupleType(3, typeArgs, r);
00820
00821 updateInHashTable(var_type_table, varname, collType);
00822 return res3;
00823 } else {
00824 ExprType *fnType = typeExpression3(fn, dynamictyping, funcDesc, var_type_table,typingConstraints,errmsg,errnode,r);
00825 if(getNodeType(fnType) == T_ERROR) return fnType;
00826 N_TUPLE_CONSTRUCT_TUPLE(arg) = 1;
00827 ExprType *argType = typeExpression3(arg, dynamictyping, funcDesc, var_type_table,typingConstraints,errmsg,errnode,r);
00828 if(getNodeType(argType) == T_ERROR) return argType;
00829
00830 ExprType *fType = getNodeType(fnType) == T_CONS && strcmp(fnType->text, FUNC) == 0 ? fnType : unifyWith(fnType, newFuncType(newTVar(r), newTVar(r), r), var_type_table, r);
00831
00832 RE_ERROR2(getNodeType(fType) == T_ERROR, "the first component of a function application does not have a function type");
00833 ExprType *paramType = dereference(fType->subtrees[0], var_type_table, r);
00834 ExprType *retType = dereference(fType->subtrees[1], var_type_table, r);
00835
00836 RE_ERROR2(getNodeType(fn) == TK_TEXT && strcmp(fn->text, "assign") == 0 &&
00837 arg->degree>0 &&
00838 !isPattern(arg->subtrees[0]), "the first argument of microservice assign is not a variable or a pattern");
00839 RE_ERROR2(getNodeType(fn) == TK_TEXT && strcmp(fn->text, "let") == 0 &&
00840 arg->degree>0 &&
00841 !isPattern(arg->subtrees[0]), "the first argument of microservice let is not a variable or a pattern");
00842
00843
00844
00845
00846
00847 ExprType *t = NULL;
00848 if(getVararg(fType) != OPTION_VARARG_ONCE) {
00849
00850 int fixParamN = paramType->degree - 1;
00851 int argN = node->subtrees[1] ->degree;
00852 int copyN = argN - fixParamN;
00853 ExprType **subtrees = paramType->subtrees;
00854 if(copyN < (getVararg(fType) == OPTION_VARARG_PLUS ? 1 : 0) || (getVararg(fType) == OPTION_VARARG_OPTIONAL && copyN > 1)) {
00855 snprintf(buf, 1024, "unsolvable vararg typing constraint %s < %s %s",
00856 typeToString(argType, var_type_table, typebuf, ERR_MSG_LEN),
00857 typeToString(paramType, var_type_table, typebuf2, ERR_MSG_LEN),
00858 getVararg(fType) == OPTION_VARARG_PLUS ? "*" : getVararg(fType) == OPTION_VARARG_OPTIONAL? "?" : "+");
00859 RE_ERROR2(1, buf);
00860 }
00861 ExprType **paramTypes = allocSubtrees(r, argN);
00862 int i;
00863 for(i = 0;i<fixParamN;i++) {
00864 paramTypes[i] = subtrees[i];
00865 }
00866 for(i=0;i<copyN;i++) {
00867 paramTypes[i+fixParamN] = subtrees[fixParamN];
00868 }
00869 t = newTupleType(argN, paramTypes, r);
00870 } else {
00871 t = paramType;
00872 }
00873
00874
00875 int ret = typeFuncParam(node->subtrees[1], argType, t, var_type_table, typingConstraints, errmsg, r);
00876 if(ret!=0) {
00877 *errnode = node->subtrees[1];
00878 RE_ERROR2(ret != 0, "parameter type error");
00879 }
00880 int i;
00881 for(i=0;i<node->subtrees[1]->degree;i++) {
00882 setIOType(node->subtrees[1]->subtrees[i], getIOType(t->subtrees[i]));
00883 }
00884
00885 arg->coercionType = t;
00886
00887
00888
00889
00890
00891 return instantiate(replaceDynamicWithNewTVar(retType, r), var_type_table, 0, r);
00892 }
00893 char errbuf[ERR_MSG_LEN];
00894 char errmsgbuf[ERR_MSG_LEN];
00895 error:
00896 *errnode = node;
00897 snprintf(errmsgbuf, ERR_MSG_LEN, "type error: %s in %s", localErrorMsg, fn->text);
00898 generateErrMsg(errmsgbuf, NODE_EXPR_POS((*errnode)), (*errnode)->base, errbuf);
00899 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
00900 return newSimpType(T_ERROR,r);
00901 }
00902 ExprType *replaceDynamicWithNewTVar(ExprType *type, Region *r) {
00903 ExprType *newt = (ExprType *)region_alloc(r, sizeof(ExprType));
00904 *newt = *type;
00905 if(getNodeType(type) == T_DYNAMIC) {
00906 setNodeType(newt, T_VAR);
00907 T_VAR_ID(newt) = newTVarId();
00908 }
00909 int i;
00910 for(i=0;i<type->degree;i++) {
00911 newt->subtrees[i] = replaceDynamicWithNewTVar(type->subtrees[i], r);
00912 }
00913 return newt;
00914 }
00915 int typeFuncParam(Node *param, Node *paramType, Node *formalParamType, Hashtable *var_type_table, List *typingConstraints, rError_t *errmsg, Region *r) {
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925 TypingConstraint *tc = newTypingConstraint(paramType, formalParamType, TC_LT, param, r);
00926 listAppend(typingConstraints, tc, r);
00927 Node *errnode;
00928 Satisfiability tcons = simplify(typingConstraints, var_type_table, errmsg, &errnode, r);
00929 switch(tcons) {
00930 case TAUTOLOGY:
00931 break;
00932 case CONTINGENCY:
00933 break;
00934 case ABSURDITY:
00935 return -1;
00936 }
00937 return 0;
00938 }
00939
00940 ExprType* typeExpression3(Node *expr, int dynamictyping, Env *funcDesc, Hashtable *varTypes, List *typingConstraints, rError_t *errmsg, Node **errnode, Region *r) {
00941 ExprType *res;
00942 ExprType **components;
00943 ExprType* t = NULL;
00944 int i;
00945 expr->option |= OPTION_TYPED;
00946 switch(getNodeType(expr)) {
00947 case TK_BOOL:
00948 return expr->exprType = dynamictyping?newSimpType(T_DYNAMIC, r):newSimpType(T_BOOL, r);
00949 case TK_INT:
00950 return expr->exprType = dynamictyping?newSimpType(T_DYNAMIC, r):newSimpType(T_INT,r);
00951 case TK_DOUBLE:
00952 return expr->exprType = dynamictyping?newSimpType(T_DYNAMIC, r):newSimpType(T_DOUBLE,r);
00953 case TK_STRING:
00954 return expr->exprType = dynamictyping?newSimpType(T_DYNAMIC, r):newSimpType(T_STRING,r);
00955 case TK_VAR:
00956 t = (ExprType *)lookupFromHashTable(varTypes, expr->text);
00957 if(t==NULL) {
00958
00959 t = newTVar(r);
00960 insertIntoHashTable(varTypes, expr->text, t);
00961 }
00962 t = dereference(t, varTypes, r);
00963 return expr->exprType = t;
00964 case TK_TEXT:
00965 if(strcmp(expr->text,"nop")==0) {
00966 return expr->exprType = newFuncType(newTupleType(0, NULL, r), newSimpType(T_INT, r), r);
00967 } else {
00968
00969 FunctionDesc *fDesc;
00970 if(funcDesc != NULL && (fDesc = (FunctionDesc*)lookupFromEnv(funcDesc, expr->text))!=NULL && fDesc->exprType!=NULL) {
00971 return expr->exprType = dupType(fDesc->exprType, r);
00972 } else {
00973 ExprType *paramType = newSimpType(T_DYNAMIC, r);
00974 setIOType(paramType, IO_TYPE_DYNAMIC);
00975 ExprType *fType = newFuncType(newUnaryType(T_TUPLE, paramType, r), newSimpType(T_DYNAMIC, r), r);
00976 setVararg(fType, OPTION_VARARG_STAR);
00977 return expr->exprType = fType;
00978 }
00979 }
00980 case N_TUPLE:
00981 components = (ExprType **) region_alloc(r, sizeof(ExprType *) * expr->degree);
00982 for(i=0;i<expr->degree;i++) {
00983 components[i] = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
00984 if(getNodeType(components[i]) == T_ERROR) {
00985 return expr->exprType = components[i];
00986 }
00987 }
00988 if(N_TUPLE_CONSTRUCT_TUPLE(expr) || expr->degree != 1) {
00989 return expr->exprType = newTupleType(expr->degree, components, r);
00990 } else {
00991 return expr->exprType = components[0];
00992 }
00993
00994 case N_APPLICATION:
00995
00996
00997 return expr->exprType = typeFunction3(expr, dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
00998 case N_ACTIONS:
00999 if(expr->degree == 0) {
01000
01001 return expr->exprType = newSimpType(T_INT, r);
01002 }
01003 for(i=0;i<expr->degree;i++) {
01004
01005 res = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
01006
01007 if(getNodeType(res) == T_ERROR) {
01008 return expr->exprType = res;
01009 }
01010 }
01011 return expr->exprType = res;
01012 case N_ACTIONS_RECOVERY:
01013 res = typeExpression3(expr->subtrees[0], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode, r);
01014 if(getNodeType(res) == T_ERROR) {
01015 return expr->exprType = res;
01016 }
01017 res = typeExpression3(expr->subtrees[1], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode, r);
01018 return expr->exprType = res;
01019 case N_ATTR:
01020
01021 for(i=0;i<expr->degree;i++) {
01022 res = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
01023 if(getNodeType(res) == T_ERROR) {
01024 return expr->exprType = res;
01025 }
01026 }
01027 return expr->exprType = newSimpType(T_DYNAMIC, r);
01028 case N_QUERY_COND_JUNCTION:
01029
01030 for(i=0;i<expr->degree;i++) {
01031 res = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
01032 if(getNodeType(res) == T_ERROR) {
01033 return expr->exprType = res;
01034 }
01035 }
01036 return expr->exprType = newSimpType(T_DYNAMIC, r);
01037 case N_QUERY:
01038
01039 for(i=0;i<expr->degree;i++) {
01040 res = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
01041 if(getNodeType(res) == T_ERROR) {
01042 return expr->exprType = res;
01043 }
01044 }
01045 return expr->exprType = newSimpType(T_DYNAMIC, r);
01046 case N_QUERY_COND:
01047
01048 for(i=0;i<expr->degree;i++) {
01049 res = typeExpression3(expr->subtrees[i], dynamictyping, funcDesc, varTypes, typingConstraints, errmsg, errnode,r);
01050 if(getNodeType(res) == T_ERROR) {
01051 return expr->exprType = res;
01052 }
01053 }
01054 return expr->exprType = newSimpType(T_DYNAMIC, r);
01055 case TK_COL:
01056
01057 return expr->exprType = newSimpType(T_DYNAMIC, r);
01058
01059 default:
01060 break;
01061 }
01062 *errnode = expr;
01063 char errbuf[ERR_MSG_LEN], errbuf0[ERR_MSG_LEN];
01064 snprintf(errbuf0, ERR_MSG_LEN, "error: unsupported ast node %d", getNodeType(expr));
01065 generateErrMsg(errbuf0, NODE_EXPR_POS(expr), expr->base, errbuf);
01066 addRErrorMsg(errmsg, RE_TYPE_ERROR, errbuf);
01067 return expr->exprType = newSimpType(T_ERROR,r);
01068
01069 }
01070
01071
01072
01073
01074
01075
01076 void postProcessCoercion(Node *expr, Hashtable *varTypes, rError_t *errmsg, Node **errnode, Region *r) {
01077 expr->coercionType = expr->coercionType==NULL?NULL:instantiate(expr->coercionType, varTypes, 0, r);
01078 expr->exprType = expr->exprType==NULL?NULL:instantiate(expr->exprType, varTypes, 0, r);
01079 int i;
01080 for(i=0;i<expr->degree;i++) {
01081 postProcessCoercion(expr->subtrees[i], varTypes, errmsg, errnode, r);
01082 }
01083 if(expr->coercionType!=NULL && expr->exprType!=NULL) {
01084
01085
01086
01087 if(getNodeType(expr) == N_TUPLE) {
01088 ExprType **csubtrees = expr->coercionType->subtrees;
01089 int i;
01090 for(i=0;i<expr->degree;i++) {
01091 if(typeEqSyntatic(expr->subtrees[i]->exprType, csubtrees[i])) {
01092 expr->subtrees[i]->option &= ~OPTION_COERCE;
01093 } else {
01094 expr->subtrees[i]->option |= OPTION_COERCE;
01095 }
01096 }
01097 }
01098 }
01099 }
01100
01101
01102
01103 void postProcessActions(Node *expr, Env *systemFunctionTables, rError_t *errmsg, Node **errnode, Region *r) {
01104 int i;
01105 switch(getNodeType(expr)) {
01106 case N_TUPLE:
01107 for(i=0;i<expr->degree;i++) {
01108 if(getIOType(expr->subtrees[i]) == IO_TYPE_ACTIONS && getNodeType(expr->subtrees[i]) != N_ACTIONS) {
01109 setIOType(expr->subtrees[i], IO_TYPE_INPUT);
01110 Node **params = (Node **)region_alloc(r, sizeof(Node *)*1);
01111 params[0] = expr->subtrees[i];
01112 Label pos;
01113 pos.base = expr->base;
01114 pos.exprloc = NODE_EXPR_POS(expr);
01115 expr->subtrees[i] = createActionsNode(params, 1, &pos, r);
01116 setIOType(expr->subtrees[i], IO_TYPE_ACTIONS);
01117 expr->subtrees[i]->exprType = params[0]->exprType;
01118 }
01119 }
01120 break;
01121 default:
01122 break;
01123 }
01124 for(i=0;i<expr->degree;i++) {
01125 postProcessActions(expr->subtrees[i], systemFunctionTables, errmsg, errnode, r);
01126 }
01127 }