Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
    }
}