/* analyzing assignment statement, if any variable is not declared report an error check the type of left and right */ void analyze_assign(Assign assign, char* procName) { analyze_expr(assign.expr, procName); getExprType(assign.expr, procName); int r = checkType(procName, assign.id, getExprType(assign.expr, procName)); int j = getArrayType(getType(procName,assign.id)) == getExprType(assign.expr, procName) ? 1:0; if(getType(procName,assign.id)==FLOAT_TYPE && getExprType(assign.expr, procName)==INT_TYPE || getType(procName,assign.id)==FLOAT_TYPE && getExprType(assign.expr, procName)==INT_ARRAY_TYPE) r = 1; if(r == 0 && j == 0) { printf("wrong assign type of %s.\n", assign.id); errorNum++; } if(r == -1) { printf("no declaration of %s.\n", assign.id); errorNum++; } }
const RsArrayType* TypeSystem::getArrayType(const std::string& name, size_t size) { const RsType* bt = getTypeInfo(name); assert( bt ); return getArrayType(bt, size); }
/* analyzing each argument of the function call check the arguments number and type with the defination of the callee */ void analyze_arg(Expr arg, char* callee, int paramNum, char* procName) { if(isParamRef(callee, paramNum)==1) { // ref parameters if (arg->kind != EXPR_ID&& arg->kind!=EXPR_ARRAY) { printf("ref parameter is not a scaler.\n"); errorNum++; } if((getParamType(callee, paramNum) != getExprType(arg, procName)) && (getArrayType(getParamType(callee, paramNum)) != getExprType(arg, procName))) { printf("No.%d parameter of function call %s has wrong type.\n", paramNum+1, callee); errorNum++; } } else if(isParamRef(callee, paramNum)==0) { // val parameters if((getParamType(callee, paramNum) != getExprType(arg, procName)) && (getArrayType(getParamType(callee, paramNum)) != getExprType(arg, procName))) { if(getParamType(callee, paramNum) == FLOAT_TYPE && (getExprType(arg, procName) == INT_TYPE || getExprType(arg, procName) == INT_ARRAY_TYPE)) {} else { printf("No.%d parameter of function call %s has wrong type.\n", paramNum+1, callee); errorNum++; } } } }
bool Type::subtypeOf(Type t2) const { // First, check for any members in m_bits that aren't in t2.m_bits. if ((m_bits & t2.m_bits) != m_bits) return false; // If t2 is a constant, we must be the same constant or Bottom. if (t2.m_hasConstVal) { assert(!t2.isUnion()); return m_bits == kBottom || (m_hasConstVal && m_extra == t2.m_extra); } // If t2 is specialized, we must either not be eligible for the same kind of // specialization (Int <= {Int|Arr<Packed>}) or have a specialization that is // a subtype of t2's specialization. if (t2.isSpecialized()) { if (t2.canSpecializeClass()) { if (!isSpecialized()) return false; // Obj=A <: Obj=A // Obj<=A <: Obj<=A if (m_class.isExact() == t2.m_class.isExact() && getClass() == t2.getClass()) { return true; } // A <: B // ---------------- // Obj=A <: Obj<=B // Obj<=A <: Obj<=B if (!t2.m_class.isExact()) return getClass()->classof(t2.getClass()); return false; } assert(t2.canSpecializeArray()); if (!canSpecializeArray()) return true; if (!isSpecialized()) return false; // Both types are specialized Arr types. "Specialized" in this context // means it has at least one of a RepoAuthType::Array* or (const ArrayData* // or ArrayData::ArrayKind). We may return false erroneously in cases where // a 100% accurate comparison of the specializations would be prohibitively // expensive. if (m_arrayInfo == t2.m_arrayInfo) return true; auto rat1 = getArrayType(); auto rat2 = t2.getArrayType(); if (rat1 != rat2 && !(rat1 && !rat2)) { // Different rats are only ok if rat1 is present and rat2 isn't. It's // possible for one rat to be a subtype of another rat or array kind, but // checking that can be very expensive. return false; } auto kind1 = getOptArrayKind(); auto kind2 = t2.getOptArrayKind(); assert(kind1 || kind2); if (kind1 && !kind2) return true; if (kind2 && !kind1) return false; if (*kind1 != *kind2) return false; // Same kinds but we still have to check for const arrays. a <= b iff they // have the same const array or a has a const array and b doesn't. If they // have the same non-nullptr const array the m_arrayInfo check up above // should've triggered. auto const1 = isConst() ? arrVal() : nullptr; auto const2 = t2.isConst() ? t2.arrVal() : nullptr; assert((!const1 && !const2) || const1 != const2); return const1 == const2 || (const1 && !const2); } return true; }
inline char getArrayType(PyArrayObject *args) { return getArrayType((PyObject *)(args)); }
/* analyzing the type of an expression return the type of the expression, if there is an type error return ERROR_TYPE and report the error */ Type getExprType(Expr expr, char* procName) { Type exprType; switch (expr->kind) { case EXPR_ID: exprType = getType(procName,expr->id); break; case EXPR_CONST: if(expr->constant.type == BOOL_CONSTANT) exprType = BOOL_TYPE; else if(expr->constant.type == INT_CONSTANT) exprType = INT_TYPE; else if(expr->constant.type == FLOAT_CONSTANT) exprType = FLOAT_TYPE; break; case EXPR_BINOP: if((expr->binop == BINOP_AND) || (expr->binop ==BINOP_OR)) { // 'and' and 'or' must have bool type operands if((getExprType(expr->e1, procName)==BOOL_TYPE|| getExprType(expr->e1, procName)==BOOL_ARRAY_TYPE) && (getExprType(expr->e2, procName)==BOOL_TYPE|| getExprType(expr->e2, procName)==BOOL_ARRAY_TYPE)) exprType = BOOL_TYPE; else exprType = ERROR_TYPE; } else if(getExprType(expr->e1, procName)==ERROR_TYPE || getExprType(expr->e2, procName)==ERROR_TYPE) { exprType = ERROR_TYPE; } else if((getExprType(expr->e1, procName)==BOOL_TYPE|| getExprType(expr->e1, procName)==BOOL_ARRAY_TYPE) || (getExprType(expr->e2, procName)==BOOL_TYPE|| getExprType(expr->e2, procName)==BOOL_ARRAY_TYPE)) { // other binary operators must not have bool type operands printf("wrong binop_expression operand "); printf("type of bool in line %d.\n", expr->lineno); errorNum++; exprType = ERROR_TYPE; } else if((getExprType(expr->e1, procName)==INT_TYPE|| getExprType(expr->e1, procName)==INT_ARRAY_TYPE) && (getExprType(expr->e2, procName)==INT_TYPE|| getExprType(expr->e2, procName)==INT_ARRAY_TYPE)) { // if both operands are 'int' type, // the expression is 'int' type exprType = INT_TYPE; } else // if one of the operands is 'float' type, // the expression is 'float' type exprType = FLOAT_TYPE; break; case EXPR_UNOP: if(expr->unop == UNOP_NOT) { // 'not' operator must have bool type operand if(getExprType(expr->e1, procName)==BOOL_TYPE|| getExprType(expr->e1, procName)==BOOL_ARRAY_TYPE) exprType = BOOL_TYPE; else exprType = ERROR_TYPE; } else if(getExprType(expr->e1, procName)==BOOL_TYPE|| getExprType(expr->e1, procName)==BOOL_ARRAY_TYPE) { //'-' operator must not have bool type operand printf("wrong Unop_expression type of bool in line %d.\n" , expr->lineno); errorNum++; exprType = ERROR_TYPE; } else exprType = getExprType(expr->e1, procName); break; case EXPR_RELOP: if(getExprType(expr->e1, procName)==ERROR_TYPE || getExprType(expr->e2, procName)==ERROR_TYPE) { exprType = ERROR_TYPE; } else if (expr->relop == RELOP_EQ || expr->relop == RELOP_NE) { if(getExprType(expr->e1, procName) != getExprType(expr->e2, procName) && getExprType(expr->e1, procName) != getArrayType(getExprType(expr->e2, procName))&& getArrayType(getExprType(expr->e1, procName))!= getExprType(expr->e2, procName)) { printf("relation expression have different operands type.\n"); errorNum++; exprType = ERROR_TYPE; } else exprType = BOOL_TYPE; } else if((getExprType(expr->e1, procName)==BOOL_TYPE|| getExprType(expr->e1, procName)==BOOL_ARRAY_TYPE)|| (getExprType(expr->e2, procName)==BOOL_TYPE|| getExprType(expr->e2, procName)==BOOL_ARRAY_TYPE)) { // relation operator must not have bool type operand printf("wrong relation expression operand type of bool.\n"); errorNum++; exprType = ERROR_TYPE; } else // relation expression is bool type exprType = BOOL_TYPE; break; case EXPR_ARRAY: exprType = getType(procName, expr->id); break; } if (exprType == ERROR_TYPE) { // report an error printf("Error type of expression!\n"); errorNum++; } return exprType; }