Пример #1
0
void PackageParser::parseGenericArgumentList(TypeDefinitionWithGenerics *typeDef, TypeContext tc) {
    while (stream_.nextTokenIs(E_SPIRAL_SHELL)) {
        stream_.consumeToken(IDENTIFIER);
        
        auto variable = stream_.consumeToken(VARIABLE);
        auto constraintType = parseAndFetchType(tc, NoDynamism, nullptr, true);
        typeDef->addGenericArgument(variable, constraintType);
    }
}
Пример #2
0
void Type::parseGenericArguments(Type contextType, EmojicodeChar theNamespace, TypeDynamism dynamism, const Token *errorToken) {
    if (this->type == TT_CLASS) {
        this->genericArguments = std::vector<Type>(this->eclass->superGenericArguments);
        if (this->eclass->ownGenericArgumentCount){
            int count = 0;
            while(nextToken()->value[0] == E_SPIRAL_SHELL){
                const Token *token = consumeToken();
                
                Type ta = parseAndFetchType(contextType, theNamespace, dynamism, nullptr);
                validateGenericArgument(ta, count, contextType, token);
                genericArguments.push_back(ta);
                
                count++;
            }
            
            if(count != this->eclass->ownGenericArgumentCount){
                auto str = this->toString(typeNothingness, false);
                compilerError(errorToken, "Type %s requires %d generic arguments, but %d were given.", str.c_str(), this->eclass->ownGenericArgumentCount, count);
            }
        }
    }
}
Пример #3
0
void PackageParser::parseClassBody(Class *eclass, std::set<EmojicodeChar> *requiredInitializers, bool allowNative) {
    allowNative = allowNative && package_->requiresBinary();
    
    auto token = stream_.consumeToken(IDENTIFIER);
    if (token.value[0] != E_GRAPES) {
        ecCharToCharStack(token.value[0], s);
        throw CompilerErrorException(token, "Expected 🍇 but found %s instead.", s);
    }
    
    while (stream_.nextTokenIsEverythingBut(E_WATERMELON)) {
        auto documentation = parseDocumentationToken();
        
        auto deprecated = Attribute<E_WARNING_SIGN>().parse(&stream_);
        auto final = Attribute<E_LOCK_WITH_INK_PEN>().parse(&stream_);
        AccessLevel accessLevel = readAccessLevel(&stream_);
        auto override = Attribute<E_BLACK_NIB>().parse(&stream_);
        auto staticOnType = Attribute<E_RABBIT>().parse(&stream_);
        auto required = Attribute<E_KEY>().parse(&stream_);
        auto canReturnNothingness = Attribute<E_CANDY>().parse(&stream_);
        
        auto token = stream_.consumeToken(IDENTIFIER);
        switch (token.value[0]) {
            case E_SHORTCAKE: {
                staticOnType.disallow();
                override.disallow();
                final.disallow();
                required.disallow();
                canReturnNothingness.disallow();
                deprecated.disallow();

                auto &variableName = stream_.consumeToken(VARIABLE);
                auto type = parseAndFetchType(Type(eclass), GenericTypeVariables);
                eclass->addInstanceVariable(Argument(variableName, type));
            }
                break;
            case E_CROCODILE: {
                staticOnType.disallow();
                override.disallow();
                final.disallow();
Пример #4
0
Type Type::parseAndFetchType(Type contextType, EmojicodeChar theNamespace, TypeDynamism dynamism, bool *dynamicType){
    if (dynamicType) {
        *dynamicType = false;
    }
    if (dynamism & AllowGenericTypeVariables && contextType.type == TT_CLASS && (nextToken()->type == VARIABLE || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE))) {
        if (dynamicType) {
            *dynamicType = true;
        }
        
        bool optional = false;
        const Token *variableToken = consumeToken();
        if (variableToken->value[0] == E_CANDY) {
            variableToken = consumeToken();
            optional = true;
        }

        auto it = contextType.eclass->ownGenericArgumentVariables.find(variableToken->value);
        if (it != contextType.eclass->ownGenericArgumentVariables.end()){
            Type type = it->second;
            type.optional = optional;
            return type;
        }
        else {
            compilerError(variableToken, "No such generic type variable \"%s\".", variableToken->value.utf8CString());
        }
    }
    else if (nextToken()->value[0] == E_RAT) {
        const Token *token = consumeToken();
        
        if(!(dynamism & AllowDynamicClassType)){
            compilerError(token, "🐀 not allowed here.");
        }
        
        if (dynamicType) {
            *dynamicType = true;
        }
        return contextType;
    }
    else if (nextToken()->value[0] == E_GRAPES || (nextToken()->value[0] == E_CANDY && nextToken()->nextToken->type == VARIABLE)) {
        bool optional = false;
        if (nextToken()->value[0] == E_CANDY) {
            consumeToken();
            optional = true;
        }
        consumeToken();
        
        Type t(TT_CALLABLE, optional);
        t.arguments = 0;
        
        t.genericArguments.push_back(typeNothingness);
        
        while (!(nextToken()->type == IDENTIFIER && (nextToken()->value[0] == E_WATERMELON || nextToken()->value[0] == E_RIGHTWARDS_ARROW))) {
            t.arguments++;
            t.genericArguments.push_back(parseAndFetchType(contextType, theNamespace, dynamism, nullptr));
        }
        
        if(nextToken()->type == IDENTIFIER && nextToken()->value[0] == E_RIGHTWARDS_ARROW){
            consumeToken();
            t.genericArguments[0] = parseAndFetchType(contextType, theNamespace, dynamism, nullptr);
        }
        
        const Token *token = consumeToken(IDENTIFIER);
        if (token->value[0] != E_WATERMELON) {
            compilerError(token, "Expected 🍉.");
        }
        
        return t;
    }
    else {
        EmojicodeChar typeName, typeNamespace;
        bool optional, existent;
        const Token *token = parseTypeName(&typeName, &typeNamespace, &optional, theNamespace);
        
        Type type = fetchRawType(typeName, typeNamespace, optional, token, &existent);
        
        if (!existent) {
            ecCharToCharStack(typeName, nameString);
            ecCharToCharStack(typeNamespace, namespaceString);
            compilerError(token, "Could not find type %s in enamespace %s.", nameString, namespaceString);
        }
        
        type.parseGenericArguments(contextType, theNamespace, dynamism, token);
        
        return type;
    }
}
Пример #5
0
                deprecated.disallow();

                auto &variableName = stream_.consumeToken(VARIABLE);
                auto type = parseAndFetchType(Type(eclass), GenericTypeVariables);
                eclass->addInstanceVariable(Argument(variableName, type));
            }
                break;
            case E_CROCODILE: {
                staticOnType.disallow();
                override.disallow();
                final.disallow();
                required.disallow();
                canReturnNothingness.disallow();
                deprecated.disallow();
                
                Type type = parseAndFetchType(Type(eclass), GenericTypeVariables, nullptr, true);
                
                if (type.optional()) {
                    throw CompilerErrorException(token, "A class cannot conform to an 🍬 protocol.");
                }
                if (type.type() != TT_PROTOCOL) {
                    throw CompilerErrorException(token, "The given type is not a protocol.");
                }
                
                eclass->addProtocol(type);
            }
                break;
            case E_PIG: {
                required.disallow();
                canReturnNothingness.disallow();