#include "Entity/Type.h"
bool Type::equals(const SharedPtr &rhs) const {
// 妿rhs为nullptr, ç´æ¥è¿åfalse
if (!rhs) {
return false;
}
// 妿æ¯è¾ç两类åä¸å±äºåç±», ç´æ¥è¿åfalse
if (isBasic() && rhs->isArray() || isArray() && rhs->isBasic()) {
return false;
}
if (SharedPtr basicType = dynPtrCast(rhs)) {
const auto *type = dynamic_cast(this);
return type->equals(basicType);
} else {
SharedPtr arrayType = dynPtrCast(rhs);
const auto *type = dynamic_cast(this);
return type->equals(arrayType);
}
}
// ç¸åç±»å
// 1. ç¸ççç±»åæ¯ç¸åç±»å
// 2. åºç¡æ´åååºç¡æµ®ç¹åæ¯ç¸åç±»å
// 3. æ°ç»ä¸ç©ºæ°ç»æ¯ç¸åç±»å
bool Type::sameAs(const SharedPtr &rhs) const {
// 峿ä½åä¸ºç©ºç´æ¥è¿åfalse
if (!rhs) {
return false;
}
// ç¸ççç±»åæ¯å
¼å®¹ç
if (equals(rhs)) {
return true;
}
// æ´æ°åæµ®ç¹æ°æ¯åç±»ç
if (isNumber() && rhs->isNumber()) {
return true;
}
if (isArray() && rhs->isUnknown()) {
// 1. å·¦æä½å为æ°ç», 峿ä½å为unknownåºç¡ç±»å, å·¦æä½åå
¼å®¹å³æä½å(åä¹ä¸æç«)
// 2. 左峿ä½å齿¯æ°ç», ä¸å³æä½å为空æ ç», å·¦æä½å深度ä¸å°äºå³æä½å深度, å·¦æä½åå
¼å®¹å³æä½å(åä¹ä¸æç«)
if (rhs->isBasic() || rhs->isArray() && asArray()->getDepth() >= rhs->asArray()->getDepth()) {
return true;
}
}
return false;
}
// å·¦æä½å: å½¢å¼ä¸çç±»å(å·¦å¼çç±»å(åé声æç±»å), 彿°å½¢åç±»å)
// 峿ä½å: å®é
çç±»å(å³å¼çç±»å(åéèµå¼ç±»å), 彿°å®åç±»å)
// å
¼å®¹æ¯ææ¹åç, å·¦æä½åå
¼å®¹å³æä½åå¹¶ä¸ä¸å®ä»£è¡¨å³æä½åå
¼å®¹å·¦æä½å
bool Type::compatibleWith(const SharedPtr &rhs) const {
// 峿ä½åä¸ºç©ºç´æ¥è¿åfalse
if (!rhs) {
return false;
}
// åç±»çç±»åæ¯å
¼å®¹ç
if (equals(rhs) || sameAs(rhs)) {
return true;
}
if (isNumberArray() && rhs->isNumberArray()) {
if (asArray()->getDepth() == rhs->asArray()->getDepth()) {
return true;
}
}
return false;
}
BasicType::BasicType(BasicTypeKind kind) : kind(kind) {}
bool BasicType::isBasic() const {
return true;
}
bool BasicType::isBoolean() const {
return kind == BasicTypeKind::Boolean;
}
bool BasicType::isInteger() const {
return kind == BasicTypeKind::Integer;
}
bool BasicType::isFloat() const {
return kind == BasicTypeKind::Float;
}
bool BasicType::isNumber() const {
return kind == BasicTypeKind::Integer || kind == BasicTypeKind::Float;
}
bool BasicType::isString() const {
return kind == BasicTypeKind::String;
}
bool BasicType::isUnknown() const {
return kind == BasicTypeKind::Unknown;
}
bool BasicType::isArray() const {
return false;
}
SharedPtr BasicType::asArray() const {
return nullptr;
}
BasicTypeKind BasicType::getKind() const {
return kind;
}
bool BasicType::equals(const SharedPtr &rhs) const {
return kind == rhs->kind;
}
bool BasicType::isNumberArray() const {
return false;
}
SharedPtr ArrayType::createNDArrayType(const SharedPtr &basicType, size_t depth) {
SharedPtr type = basicType;
for (size_t i = 0; i < depth; ++i) {
type = makeShared(type);
}
return staticPtrCast(type);
}
ArrayType::ArrayType(const SharedPtr &elementType) : elementType(elementType) {
if (elementType->isArray()) {
depth = elementType->asArray()->depth + 1;
}
}
bool ArrayType::isBasic() const {
return false;
}
bool ArrayType::isBoolean() const {
return false;
}
bool ArrayType::isInteger() const {
return false;
}
bool ArrayType::isFloat() const {
return false;
}
bool ArrayType::isNumber() const {
return false;
}
bool ArrayType::isString() const {
return false;
}
bool ArrayType::isUnknown() const {
return getBasicElementType()->isUnknown();
}
bool ArrayType::isArray() const {
return true;
}
SharedPtr ArrayType::asArray() const {
return constPtrCast(staticPtrCast(shared_from_this()));
}
const SharedPtr &ArrayType::getElementType() const {
return elementType;
}
SharedPtr ArrayType::getBasicElementType() const {
if (elementType->isBasic()) {
return elementType;
}
SharedPtr iterType = elementType;
while (iterType->isArray()) {
iterType = iterType->asArray()->elementType;
}
return iterType;
}
bool ArrayType::equals(const SharedPtr &rhs) const {
return elementType->equals(rhs->elementType);
}
size_t ArrayType::getDepth() const {
return depth;
}
bool ArrayType::isNumberArray() const {
if (getBasicElementType()->isNumber()) {
return true;
}
return false;
}