Type ASTCast::analyse(SemanticAnalyser *analyser, const TypeExpectation &expectation) { auto type = analyser->analyseTypeExpr(typeExpr_, expectation); Type originalType = value_->analyse(analyser, expectation); if (originalType.compatibleTo(type, analyser->typeContext())) { analyser->app()->error(CompilerError(position(), "Unnecessary cast.")); } else if (!type.compatibleTo(originalType, analyser->typeContext())) { auto typeString = type.toString(analyser->typeContext()); analyser->app()->error(CompilerError(position(), "Cast to unrelated type ", typeString," will always fail.")); } if (type.type() == TypeType::Class) { if (!type.genericArguments().empty()) { analyser->app()->error(CompilerError(position(), "Class casts with generic arguments are not available.")); } if (originalType.type() == TypeType::Someobject || originalType.type() == TypeType::Class) { if (originalType.optional()) { throw CompilerError(position(), "Downcast on classes with optionals not possible."); } castType_ = CastType::ClassDowncast; assert(originalType.storageType() == StorageType::Simple && originalType.size() == 1); } else { castType_ = CastType::ToClass; assert(originalType.storageType() == StorageType::Box); } } else if (type.type() == TypeType::Protocol && isStatic(typeExpr_->availability())) { if (!type.genericArguments().empty()) { analyser->app()->error(CompilerError(position(), "Cannot cast to generic protocols.")); } castType_ = CastType::ToProtocol; assert(originalType.storageType() == StorageType::Box); } else if ((type.type() == TypeType::ValueType || type.type() == TypeType::Enum) && isStatic(typeExpr_->availability())) { castType_ = CastType::ToValueType; assert(originalType.storageType() == StorageType::Box); type.forceBox(); } else { auto typeString = type.toString(analyser->typeContext()); throw CompilerError(position(), "You cannot cast to ", typeString, "."); } type.setOptional(true); return type; }
bool Package::fetchRawType(EmojicodeChar name, EmojicodeChar ns, bool optional, const Token *token, Type *type) { if (ns == globalNamespace) { switch (name) { case E_OK_HAND_SIGN: *type = Type(TT_BOOLEAN, optional); return true; case E_INPUT_SYMBOL_FOR_SYMBOLS: *type = Type(TT_SYMBOL, optional); return true; case E_STEAM_LOCOMOTIVE: *type = Type(TT_INTEGER, optional); return true; case E_ROCKET: *type = Type(TT_DOUBLE, optional); return true; case E_MEDIUM_WHITE_CIRCLE: if (optional) { compilerWarning(token, "🍬⚪️ is identical to ⚪️. Do not specify 🍬."); } *type = Type(TT_SOMETHING, false); return true; case E_LARGE_BLUE_CIRCLE: *type = Type(TT_SOMEOBJECT, optional); return true; case E_SPARKLES: compilerError(token, "The Nothingness type may not be referenced to."); } } std::array<EmojicodeChar, 2> key = {ns, name}; auto it = types_.find(key); if (it != types_.end()) { auto xtype = it->second; if (optional) xtype.setOptional(); *type = xtype; return true; } else { return false; } }