void UnaryOpExpressionAST::typeCheck(TypeChecker& checker) { mOperand->typeCheck(checker); auto opType = mOperand->expressionType(checker); if (mOp == Operator('!') && opType != checker.findType("Bool")) { checker.typeError("The '!' operator can only be applied to values/variables of type 'Bool'."); } else if (mOp == Operator('-') && opType != checker.findType("Int") && opType != checker.findType("Float")) { checker.typeError("The '-' operator can only be applied to values/variables of type 'Int' or 'Float'."); } }
void MemberAccessAST::typeCheck(TypeChecker& checker) { mAccessExpression->typeCheck(checker); if (auto varRef = std::dynamic_pointer_cast<VariableReferenceExpressionAST>(mAccessExpression)) { auto varSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varRef->name())); auto varRefType = checker.findType(varSymbol->variableType()); std::string memberName = getMemberName(); std::string objName = varRefType->name(); if (std::dynamic_pointer_cast<ArrayType>(varRefType)) { objName = "Array"; } if (!checker.objectExists(objName)) { checker.typeError(varRefType->name() + " is not an object type."); } auto& object = checker.getObject(objName); if (!object.fieldExists(memberName)) { checker.typeError("There exists no field '" + memberName + "' in the type '" + varRefType->name() + "'."); } if (auto arrayMember = std::dynamic_pointer_cast<ArrayAccessAST>(mMemberExpression)) { arrayMember->accessExpression()->typeCheck(checker); } } }
void MemberCallExpressionAST::typeCheck(TypeChecker& checker) { mAccessExpression->typeCheck(checker); if (auto varRef = std::dynamic_pointer_cast<VariableReferenceExpressionAST>(mAccessExpression)) { auto varSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varRef->name())); auto varRefType = checker.findType(varSymbol->variableType()); std::string objName = varRefType->name(); if (!checker.objectExists(objName)) { checker.typeError(varRefType->name() + " is not an object type."); } auto classSymbol = std::dynamic_pointer_cast<ClassSymbol>(Helpers::findSymbolInNamespace(mSymbolTable, objName)); mMemberCallExpression->setCallTable(classSymbol->symbolTable()); mMemberCallExpression->generateSymbols(checker.binder(), mSymbolTable); mMemberCallExpression->typeCheck(checker); } else { auto varRefType = mAccessExpression->expressionType(checker); std::string objName = varRefType->name(); if (!checker.objectExists(objName)) { checker.typeError(varRefType->name() + " is not an object type."); } auto classSymbol = std::dynamic_pointer_cast<ClassSymbol>(Helpers::findSymbolInNamespace(mSymbolTable, objName)); mMemberCallExpression->setCallTable(classSymbol->symbolTable()); mMemberCallExpression->generateSymbols(checker.binder(), mSymbolTable); mMemberCallExpression->typeCheck(checker); } }
std::shared_ptr<Type> BinaryOpExpressionAST::expressionType(const TypeChecker& checker) const { auto& boolTypes = checker.operators().binaryOpReturnTypes(); if (boolTypes.count(mOp) > 0) { return boolTypes.at(mOp); } else { if (mOp == Operator('=')) { return checker.findType("Void"); } else { return mLeftHandSide->expressionType(checker); } } }
void ArrayDeclarationAST::typeCheck(TypeChecker& checker) { mLengthExpression->typeCheck(checker); //Check length checker.assertSameType( *checker.makeType("Int"), *mLengthExpression->expressionType(checker), "Expected the length to be of type 'Int'."); //Check if the element type exists checker.assertTypeExists(elementType(), false); checker.assertNotVoid(*checker.findType(elementType()), "Arrays of type 'Void' is not allowed."); //Create the array type if not created checker.makeType(elementType() + "[]"); }
void SetFieldValueAST::typeCheck(TypeChecker& checker) { mObjectRefExpression->typeCheck(checker); std::shared_ptr<Type> objRefType; if (auto varRef = std::dynamic_pointer_cast<VariableReferenceExpressionAST>(mObjectRefExpression)) { auto varSymbol = std::dynamic_pointer_cast<VariableSymbol>(mSymbolTable->find(varRef->name())); objRefType = checker.findType(varSymbol->variableType()); } else if (auto arrayRef = std::dynamic_pointer_cast<ArrayAccessAST>(mObjectRefExpression)) { objRefType = arrayRef->expressionType(checker); } else { checker.typeError("Not implemented"); } auto memberName = getMemberName(); std::string objName = objRefType->name(); if (!checker.objectExists(objName)) { checker.typeError(objRefType->name() + " is not an object type."); } auto& object = checker.getObject(objName); if (!object.fieldExists(memberName)) { checker.typeError("There exists no field '" + memberName + "' in the type '" + objRefType->name() + "'."); } mRightHandSide->typeCheck(checker); //Check rhs std::shared_ptr<Type> fieldType; if (std::dynamic_pointer_cast<ArrayAccessAST>(mMemberExpression)) { fieldType = std::dynamic_pointer_cast<ArrayType>(object.getField(memberName).type())->elementType(); } else { fieldType = object.getField(memberName).type(); } checker.assertSameType( *fieldType, *mRightHandSide->expressionType(checker), asString()); }
void MultiDimArrayDeclarationAST::typeCheck(TypeChecker& checker) { for (auto lengthExpr : mLengthExpressions) { lengthExpr->typeCheck(checker); } //Check lengths int dim = 0; for (auto lengthExpr : mLengthExpressions) { checker.assertSameType( *checker.makeType("Int"), *lengthExpr->expressionType(checker), "Expected the length of dimension " + std::to_string(dim) + " to be of type 'Int'."); dim++; } //Check if the element type exists checker.assertTypeExists(elementType(), false); checker.assertNotVoid(*checker.findType(elementType()), "Arrays of type 'Void' is not allowed."); //Create all array types for (int i = 0; i < mLengthExpressions.size(); i++) { checker.makeType(typeString(i)); } }
std::shared_ptr<Type> ExpressionAST::expressionType(const TypeChecker& checker) const { return checker.findType("Void"); }
std::shared_ptr<Type> ArrayDeclarationAST::expressionType(const TypeChecker& checker) const { return checker.findType(elementType() + "[]"); }
std::shared_ptr<Type> ArraySetElementAST::expressionType(const TypeChecker& checker) const { return checker.findType("Void"); }
std::shared_ptr<Type> MultiDimArrayDeclarationAST::expressionType(const TypeChecker& checker) const { return checker.findType(typeString()); }