/** * 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); } }
ExprType *typeRuleSet( RuleSet *ruleset, rError_t *errmsg, Node **errnode, Region *r ) { Env *funcDesc = ruleEngineConfig.extFuncDescIndex; Hashtable *ruleType = newHashTable2( MAX_NUM_RULES * 2, r ); ExprType *res; int i; for ( i = 0; i < ruleset->len; i++ ) { RuleDesc *rule = ruleset->rules[i]; if ( rule->ruleType == RK_REL || rule->ruleType == RK_FUNC ) { List *typingConstraints = newList( r ); Hashtable *varTypes = newHashTable2( 100, r ); ExprType *restype = typeRule( rule, funcDesc, varTypes, typingConstraints, errmsg, errnode, r ); /*char buf[1024]; */ /*typingConstraintsToString(typingConstraints, buf, 1024); */ /*printf("rule %s, typing constraints: %s\n", ruleset->rules[i]->subtrees[0]->text, buf); */ if ( getNodeType( restype ) == T_ERROR ) { res = restype; char *errbuf = ( char * ) malloc( ERR_MSG_LEN * 1024 * sizeof( char ) ); errMsgToString( errmsg, errbuf, ERR_MSG_LEN * 1024 ); #ifdef DEBUG writeToTmp( "ruleerr.log", errbuf ); writeToTmp( "ruleerr.log", "\n" ); #endif rodsLog( LOG_ERROR, "%s", errbuf ); free( errbuf ); freeRErrorContent( errmsg ); RETURN; } /* check that function names are unique and do not conflict with system msis */ char errbuf[ERR_MSG_LEN]; char *ruleName = rule->node->subtrees[0]->text; FunctionDesc *fd; if ( ( fd = ( FunctionDesc * )lookupFromEnv( funcDesc, ruleName ) ) != NULL ) { if ( getNodeType( fd ) != N_FD_EXTERNAL && getNodeType( fd ) != N_FD_RULE_INDEX_LIST ) { char *err; switch ( getNodeType( fd ) ) { case N_FD_CONSTRUCTOR: err = "redefinition of constructor"; break; case N_FD_DECONSTRUCTOR: err = "redefinition of deconstructor"; break; case N_FD_FUNCTION: err = "redefinition of system microservice"; break; default: err = "redefinition of system symbol"; break; } generateErrMsg( err, NODE_EXPR_POS( rule->node ), rule->node->base, errbuf ); addRErrorMsg( errmsg, RE_FUNCTION_REDEFINITION, errbuf ); res = newErrorType( RE_FUNCTION_REDEFINITION, r ); *errnode = rule->node; RETURN; } } RuleDesc *rd = ( RuleDesc * )lookupFromHashTable( ruleType, ruleName ); if ( rd != NULL ) { if ( rule->ruleType == RK_FUNC || rd ->ruleType == RK_FUNC ) { generateErrMsg( "redefinition of function", NODE_EXPR_POS( rule->node ), rule->node->base, errbuf ); addRErrorMsg( errmsg, RE_FUNCTION_REDEFINITION, errbuf ); generateErrMsg( "previous definition", NODE_EXPR_POS( rd->node ), rd->node->base, errbuf ); addRErrorMsg( errmsg, RE_FUNCTION_REDEFINITION, errbuf ); res = newErrorType( RE_FUNCTION_REDEFINITION, r ); *errnode = rule->node; RETURN; } } else { insertIntoHashTable( ruleType, ruleName, rule ); } } } res = newSimpType( T_INT, r ); /* Although a rule set does not have type T_INT, return T_INT to indicate success. */ ret: return res; }