/** * Unify non tvar or union types. * return The most general instance if unifiable * NULL if not */ ExprType* unifyNonTvars(ExprType *type, ExprType *expected, Hashtable *varTypes, Region *r) { if(getNodeType(type) == T_CONS && getNodeType(expected) == T_CONS) { if(strcmp(T_CONS_TYPE_NAME(type), T_CONS_TYPE_NAME(expected)) == 0 && T_CONS_ARITY(type) == T_CONS_ARITY(expected)) { ExprType **subtrees = (ExprType **) region_alloc(r, sizeof(ExprType *) * T_CONS_ARITY(expected)); int i; for(i=0;i<T_CONS_ARITY(type);i++) { ExprType *elemType = unifyWith( T_CONS_TYPE_ARG(type, i), T_CONS_TYPE_ARG(expected, i), varTypes,r); /* unifyWithCoercion performs dereference */ if(elemType == NULL) { return NULL; } subtrees[i] = elemType; } return dereference(newConsType(T_CONS_ARITY(expected), T_CONS_TYPE_NAME(expected), subtrees, r), varTypes, r); } else { return NULL; } } else if(getNodeType(type) == T_IRODS || getNodeType(expected) == T_IRODS) { if(strcmp(type->text, expected->text)!=0) { return NULL; } return expected; } else if(getNodeType(expected) == getNodeType(type)) { /* primitive types */ return expected; } else { return newErrorType(RE_TYPE_ERROR, r); } }
int typeEqSyntatic(ExprType *a, ExprType *b) { if(getNodeType(a)!=getNodeType(b) || getVararg(a) != getVararg(b)) { return 0; } switch(getNodeType(a)) { case T_CONS: case T_TUPLE: if(T_CONS_ARITY(a) == T_CONS_ARITY(b) && (getNodeType(a) == T_TUPLE || strcmp(T_CONS_TYPE_NAME(a), T_CONS_TYPE_NAME(b)) == 0)) { int i; for(i=0;i<T_CONS_ARITY(a);i++) { if(!typeEqSyntatic(T_CONS_TYPE_ARG(a, i),T_CONS_TYPE_ARG(b, i))) { return 0; } } return 1; } return 0; case T_VAR: return T_VAR_ID(a) == T_VAR_ID(b); case T_IRODS: return strcmp(a->text, b->text) == 0; default: return 1; } }
ExprType *dupTypeAux(ExprType *ty, Region *r, Hashtable *varTable) { ExprType **paramTypes; int i; ExprType *newt; ExprType *exist; char *name; char buf[128]; switch(getNodeType(ty)) { case T_CONS: paramTypes = (ExprType **) region_alloc(r,sizeof(ExprType *)*T_CONS_ARITY(ty)); for(i=0;i<T_CONS_ARITY(ty);i++) { paramTypes[i] = dupTypeAux(T_CONS_TYPE_ARG(ty, i),r,varTable); } newt = newConsType(T_CONS_ARITY(ty), T_CONS_TYPE_NAME(ty), paramTypes, r); newt->option = ty->option; break; case T_TUPLE: paramTypes = (ExprType **) region_alloc(r,sizeof(ExprType *)*T_CONS_ARITY(ty)); for(i=0;i<T_CONS_ARITY(ty);i++) { paramTypes[i] = dupTypeAux(T_CONS_TYPE_ARG(ty, i),r,varTable); } newt = newTupleType(T_CONS_ARITY(ty), paramTypes, r); newt->option = ty->option; break; case T_VAR: name = getTVarName(T_VAR_ID(ty), buf); exist = (ExprType *)lookupFromHashTable(varTable, name); if(exist != NULL) newt = exist; else { newt = newTVar2(T_VAR_NUM_DISJUNCTS(ty), T_VAR_DISJUNCTS(ty), r); insertIntoHashTable(varTable, name, newt); } newt->option = ty->option; break; case T_FLEX: paramTypes = (ExprType **) region_alloc(r,sizeof(ExprType *)*1); paramTypes[0] = dupTypeAux(ty->subtrees[0],r,varTable); newt = newExprType(T_FLEX, 1, paramTypes, r); newt->option = ty->option; break; default: newt = ty; break; } return newt; }
int coercible(ExprType *a, ExprType *b) { return (getNodeType(a)!=T_CONS && getNodeType(a) == getNodeType(b)) || (getNodeType(b) == T_DOUBLE && getNodeType(a) == T_INT) || (getNodeType(b) == T_DOUBLE && getNodeType(a) == T_STRING) || (getNodeType(b) == T_INT && getNodeType(a) == T_DOUBLE) || (getNodeType(b) == T_INT && getNodeType(a) == T_STRING) || (getNodeType(b) == T_STRING && getNodeType(a) == T_INT) || (getNodeType(b) == T_STRING && getNodeType(a) == T_DOUBLE) || (getNodeType(b) == T_STRING && getNodeType(a) == T_BOOL) || (getNodeType(b) == T_BOOL && getNodeType(a) == T_STRING) || (getNodeType(b) == T_DATETIME && getNodeType(a) == T_INT) || (getNodeType(b) == T_DATETIME && getNodeType(a) == T_DOUBLE) || (getNodeType(b) == T_DYNAMIC) || (getNodeType(a) == T_DYNAMIC) || (getNodeType(a)==T_CONS && getNodeType(b)==T_CONS && coercible(T_CONS_TYPE_ARG(a, 0), T_CONS_TYPE_ARG(b, 0))); }
/************************ Res to Microservice parameter ***********************/ int convertResToMsParam(msParam_t *var, Res *res, rError_t *errmsg) { strArray_t *arr = NULL; intArray_t *arr2 = NULL; int i = 0; int maxlen = 0; var->inpOutBuf = NULL; var->label = NULL; switch(TYPE(res)) { case T_ERROR: /* error message */ var->inOutStruct = (int *)malloc(sizeof(int)); *((int *)var->inOutStruct) = RES_ERR_CODE(res); var->type = strdup(INT_MS_T); break; case T_DOUBLE: /* number */ var->inOutStruct = (double *)malloc(sizeof(double)); *((double *)var->inOutStruct) = RES_DOUBLE_VAL(res); var->type = strdup(DOUBLE_MS_T); break; case T_INT: /* number */ var->inOutStruct = (int *)malloc(sizeof(int)); *((int *)var->inOutStruct) = RES_INT_VAL(res); var->type = strdup(INT_MS_T); break; case T_STRING: /* string */ var->inOutStruct = res->text == NULL? NULL : strdup(res->text); var->type = strdup(STR_MS_T); break; case T_PATH: /* path */ var->inOutStruct = res->text == NULL? NULL : strdup(res->text); var->type = strdup(STR_MS_T); break; case T_DATETIME: /* date time */ /*var->inOutStruct = (time_t *)malloc(sizeof(time_t)); */ /**((time_t *)var->inOutStruct) = res->value.t; */ /*var->type = strdup(DATETIME_MS_T); */ /* Here we pass datatime as an integer to reuse exiting packing instructions. Need to change to long int. */ var->inOutStruct = (rodsLong_t *)malloc(sizeof(int)); *((rodsLong_t *)var->inOutStruct) = RES_TIME_VAL(res); var->type = strdup(INT_MS_T); break; case T_CONS: if(strcmp(T_CONS_TYPE_NAME(res->exprType), LIST) == 0) { switch(getNodeType(T_CONS_TYPE_ARG(res->exprType, 0))) { case T_STRING: arr = (strArray_t *)malloc(sizeof(strArray_t)); arr->len = res->degree; maxlen = 0; for(i=0;i<res->degree;i++) { int slen = RES_STRING_STR_LEN(res->subtrees[i]); maxlen = maxlen < slen? slen: maxlen; } arr->size = maxlen; arr->value = (char *)malloc(sizeof(char)*maxlen*(arr->len)); for(i=0;i<res->degree;i++) { strcpy(arr->value + maxlen*i, res->subtrees[i]->text); } var->inOutStruct = arr; var->type = strdup(StrArray_MS_T); break; case T_INT: arr2 = (intArray_t *)malloc(sizeof(intArray_t)); arr2->len = res->degree; arr2->value = (int *)malloc(sizeof(int)*(arr2->len)); for(i=0;i<res->degree;i++) { arr2->value[i] = RES_INT_VAL(res); } var->inOutStruct = arr2; var->type = strdup(IntArray_MS_T); break; /*case T_IRODS: var->inOutStruct = res->value.uninterpreted.inOutStruct; var->inpOutBuf = res->value.uninterpreted.inOutBuffer; var->type = strdup(KeyValPair_MS_T); break;*/ default: /* current there is no existing packing instructions for arbitrary collection */ /* report error */ addRErrorMsg(errmsg, RE_PACKING_ERROR, "no packing instruction for arbitrary collection type"); return RE_PACKING_ERROR; } } else { addRErrorMsg(errmsg, RE_PACKING_ERROR, "no packing instruction for arbitrary constructed type"); return RE_PACKING_ERROR; } break; case T_IRODS: var->inOutStruct = RES_UNINTER_STRUCT(res); var->inpOutBuf = RES_UNINTER_BUFFER(res); var->type = strdup(res->exprType->text); break; case T_UNSPECED: var->inOutStruct = NULL; var->type = NULL; break; default: /*error */ addRErrorMsg(errmsg, RE_PACKING_ERROR, "no packing instruction for arbitrary type"); return RE_PACKING_ERROR; } return 0; }
char* typeToString(ExprType *type, Hashtable *var_types, char *buf, int bufsize) { buf[0] = '\0'; Region *r = make_region(0, NULL); if(getVararg(type) != OPTION_VARARG_ONCE) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "vararg "); } ExprType *etype = type; if(getNodeType(etype) == T_VAR && var_types != NULL) { /* dereference */ etype = dereference(etype, var_types, r); } if(getNodeType(etype) == T_VAR) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", etype == NULL?"?":typeName_ExprType(etype)); snprintf(buf+strlen(buf), bufsize-strlen(buf), "%d", T_VAR_ID(etype)); if(T_VAR_NUM_DISJUNCTS(type)!=0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "{"); int i; for(i=0;i<T_VAR_NUM_DISJUNCTS(type);i++) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", typeName_ExprType(T_VAR_DISJUNCT(type, i))); } snprintf(buf+strlen(buf), bufsize-strlen(buf), "}"); } } else if(getNodeType(etype) == T_CONS) { if(strcmp(etype->text, FUNC) == 0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "("); typeToString(T_CONS_TYPE_ARG(etype, 0), var_types, buf+strlen(buf), bufsize-strlen(buf)); snprintf(buf+strlen(buf), bufsize-strlen(buf), ")"); snprintf(buf+strlen(buf), bufsize-strlen(buf), "->"); typeToString(T_CONS_TYPE_ARG(etype, 1), var_types, buf+strlen(buf), bufsize-strlen(buf)); } else { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", T_CONS_TYPE_NAME(etype)); int i; if(T_CONS_ARITY(etype) != 0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "("); for(i=0;i<T_CONS_ARITY(etype);i++) { if(i!=0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), ", "); } typeToString(T_CONS_TYPE_ARG(etype, i), var_types, buf+strlen(buf), bufsize-strlen(buf)); } snprintf(buf+strlen(buf), bufsize-strlen(buf), ")"); } } } else if(getNodeType(etype) == T_FLEX) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", typeName_ExprType(etype)); typeToString(etype->subtrees[0], var_types, buf+strlen(buf), bufsize-strlen(buf)); } else if(getNodeType(etype) == T_FIXD) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", typeName_ExprType(etype)); typeToString(etype->subtrees[0], var_types, buf+strlen(buf), bufsize-strlen(buf)); snprintf(buf+strlen(buf), bufsize-strlen(buf), "=> "); typeToString(etype->subtrees[1], var_types, buf+strlen(buf), bufsize-strlen(buf)); } else if(getNodeType(etype) == T_TUPLE) { if(T_CONS_ARITY(etype) == 0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "unit"); } else { if(T_CONS_ARITY(etype) == 1) { snprintf(buf+strlen(buf), bufsize-strlen(buf), "("); } int i; for(i=0;i<T_CONS_ARITY(etype);i++) { if(i!=0) { snprintf(buf+strlen(buf), bufsize-strlen(buf), " * "); } typeToString(T_CONS_TYPE_ARG(etype, i), var_types, buf+strlen(buf), bufsize-strlen(buf)); } if(T_CONS_ARITY(etype) == 1) { snprintf(buf+strlen(buf), bufsize-strlen(buf), ")"); } } } else { snprintf(buf+strlen(buf), bufsize-strlen(buf), "%s ", etype == NULL?"?":typeName_ExprType(etype)); } int i = strlen(buf) - 1; while(buf[i]==' ') i--; buf[i+1]='\0'; region_free(r); return buf; }