Example #1
0
void Procedure::checkOverride(Procedure *superProcedure){
    if(overriding && !superProcedure){
        ecCharToCharStack(name, mn);
        compilerError(dToken, "%s was declared āœ’ļø but does not override anything.", mn);
    }
    else if(!overriding && superProcedure){
        ecCharToCharStack(name, mn);
        compilerError(dToken, "If you want to override %s add āœ’ļø.", mn);
    }
}
Example #2
0
void Type::validateGenericArgument(Type ta, uint16_t i, Type contextType, const Token *token){
    if (this->type != TT_CLASS) {
        compilerError(token, "The compiler encountered an internal inconsistency related to generics.");
    }
    if(this->eclass->superclass){
        i += this->eclass->superclass->genericArgumentCount;
    }
    if(!ta.compatibleTo(this->eclass->genericArgumentContraints[i], contextType)){
        compilerError(token, "Types not matching.");
    }
}
Example #3
0
void if2up(char* file,
           char* result,
           char* bindir,
           int suppressWarnings, /* suppress warnings? */
           int profiling /* profiling */
           ) {
   char updater[MAXPATHLEN];
   charStarQueue* argv = 0;

   sprintf(updater,"%s/if2up",bindir);
   enqueue(&argv,updater);

   enqueue(&argv,file);
   enqueue(&argv,result);

   if ( suppressWarnings ) enqueue(&argv,"-w");
   if ( profiling ) enqueue(&argv,"-W");

   enqueue(&argv,"-I"); /* Suppress Sequent code improvement migration */

   if ( Submit(&argv) != 0 ) {
      compilerError("if2 update in place failure");
   }

}
Example #4
0
void if2mem(char* file,
                   char* result,
                   char* bindir,
                   int suppressWarnings, /* suppress warnings? */
                   int profiling, /* profiling */
                   int optimize, /* Perform aggressive optimization */
                   int optimizeInlined /* optimize inlined calls */
            ) {
   char manager[MAXPATHLEN];
   charStarQueue* argv = 0;

   sprintf(manager,"%s/if2mem",bindir);
   enqueue(&argv,manager);

   enqueue(&argv,file);
   enqueue(&argv,result);

   if ( !optimize ) {
      enqueue(&argv,"-v"); /* no invar */
      enqueue(&argv,"-V"); /* no Oinvar */
      enqueue(&argv,"-c"); /* no cse */
      enqueue(&argv,"-g"); /* no gcse */
      enqueue(&argv,"-f"); /* no fold */
   }

   if ( suppressWarnings ) enqueue(&argv,"-w");
   if ( profiling ) enqueue(&argv,"-W");

   if ( Submit(&argv) != 0 ) {
      compilerError("if2 memory manager failure");
   }

}
Example #5
0
const Token* Type::parseTypeName(EmojicodeChar *typeName, EmojicodeChar *enamespace, bool *optional, EmojicodeChar currentNamespace){
    if (nextToken()->type == VARIABLE) {
        compilerError(consumeToken(), "Not in a generic context.");
    }
    auto *className = consumeToken(IDENTIFIER);
    
    if(className->value[0] == E_CANDY){
        *optional = true;
        
        className = consumeToken(IDENTIFIER);
    }
    else {
        *optional = false;
    }
    
    if(className->value[0] == E_ORANGE_TRIANGLE){
        const Token *nsToken = consumeToken(IDENTIFIER);
        *enamespace = nsToken->value[0];
        
        className = consumeToken(IDENTIFIER);
    }
    else {
        *enamespace = currentNamespace;
    }
    
    *typeName = className->value[0];
    
    return className;
}
int main(int argc, char *argv[])
/* Process command line. */
{
optionInit(&argc, argv, options);
if (argc != 1)
    usage();
compilerError();
return 0;
}
Example #7
0
void Package::loadInto(Package *destinationPackage, EmojicodeChar ns, const Token *errorToken) const {
    for (auto exported : exportedTypes_) {
        Type type = typeNothingness;
        if (destinationPackage->fetchRawType(exported.name, ns, false, nullptr, &type)) {
            ecCharToCharStack(ns, nss);
            ecCharToCharStack(exported.name, tname);
            compilerError(errorToken, "Package %s could not be loaded into namespace %s of package %s: %s collides with a type of the same name in the same namespace.", name(), nss, destinationPackage->name(), tname);
        }
        
        destinationPackage->registerType(exported.type, exported.name, ns, false);
    }
}
Example #8
0
void Procedure::parseBody(bool allowNative) {
    if(nextToken()->value[0] == E_RADIO){
        const Token *t = consumeToken(IDENTIFIER);
        if(!allowNative){
            compilerError(t, "Native code is not allowed in this context.");
        }
        native = true;
        return;
    }
    
    const Token *token = consumeToken(IDENTIFIER);
    
    if (token->value[0] != E_GRAPES){
        ecCharToCharStack(token->value[0], c);
        compilerError(token, "Expected šŸ‡ but found %s instead.", c);
    }
    
    firstToken = currentToken;
    
    int d = 0;
    while ((token = until(E_WATERMELON, E_GRAPES, &d)) != nullptr);
}
Example #9
0
void Package::parse(const char *path, const Token *errorToken) {
    packages_.emplace(name(), this);
    
    parseFile(path, this);
    
    if (version().major == 0 && version().minor == 0) {
        compilerError(errorToken, "Package %s does not provide a valid version.", name());
    }
    
    packagesLoadingOrder_.push_back(this);
    
    finishedLoading_ = true;
}
Example #10
0
TypeObject* Method::getGenericType(TypeGenericDefinitionEntry* genericSymbol, TypeGenericEntry* genericParams) {
    if(m_genericParam) {
        TypeGenericDefinitionEntry * pDefGen = m_genericParam;
        TypeGenericEntry* pGen = genericParams;
        while(pGen && pDefGen && strcmp(pDefGen->m_genericName, genericSymbol->m_genericName)) {
            pDefGen = pDefGen->m_pNextGenericEntry;
            pGen = pGen->m_pNext;
        }
        if(!pDefGen && !pGen) {
            compilerError(ERR_INTERNAL, "Generic symbol was not found");
            return NULL;
        }
        if(!pDefGen || pGen) {
            compilerError(ERR_INTERNAL, "Wrong number of generic parameters");
            return NULL;
        }
        return pGen->m_instanceType;
    }
    else {
        return NULL;
    }
}
Example #11
0
void Procedure::checkPromises(Procedure *superProcedure, const char *on, Type contextType) {
    if(superProcedure->final){
        ecCharToCharStack(this->name, mn);
        compilerError(this->dToken, "%s of %s was marked šŸ”.", on, mn);
    }
    if (!this->returnType.compatibleTo(superProcedure->returnType, contextType)) {
        ecCharToCharStack(this->name, mn);
        auto supername = superProcedure->returnType.toString(contextType, true);
        auto thisname = this->returnType.toString(contextType, true);
        compilerError(this->dToken, "Return type %s of %s is not compatible with the return type %s of its %s.", thisname.c_str(), mn, supername.c_str(), on);
    }
    if(superProcedure->arguments.size() != this->arguments.size()){
        ecCharToCharStack(this->name, mn);
        compilerError(this->dToken, "%s expects %s arguments than its %s.", mn, (superProcedure->arguments.size() < this->arguments.size()) ? "more" : "less", on);
    }
    for (uint8_t i = 0; i < superProcedure->arguments.size(); i++) {
        //other way, because the method may define a more generic type
        if (!superProcedure->arguments[i].type.compatibleTo(this->arguments[i].type, contextType)) {
            auto supertype = superProcedure->arguments[i].type.toString(contextType, true);
            auto thisname = this->arguments[i].type.toString(contextType, true);
            compilerError(superProcedure->dToken, "Type %s of argument %d is not compatible with its %s argument type %s.", thisname.c_str(), i + 1, on, supertype.c_str());
        }
    }
}
Example #12
0
void Callable::parseArgumentList(TypeContext ct, Package *package){
    const Token *token;
    
    //Until the grape is found we parse arguments
    while ((token = nextToken()) && token->type == VARIABLE) { //grape
        //Get the variable in which to store the argument
        const Token *variableToken = consumeToken(VARIABLE);
        auto type = Type::parseAndFetchType(ct, AllowGenericTypeVariables, package);
        
        arguments.push_back(Variable(Variable(variableToken, type)));
    }
    
    if (arguments.size() > UINT8_MAX) {
        compilerError(token, "A function cannot take more than 255 arguments.");
    }
}
Example #13
0
Type Type::fetchRawType(EmojicodeChar name, EmojicodeChar enamespace, bool optional, const Token *token, bool *existent){
    *existent = true;
    if(enamespace == globalNamespace){
        switch (name) {
            case E_OK_HAND_SIGN:
                return Type(TT_BOOLEAN, optional);
            case E_INPUT_SYMBOL_FOR_SYMBOLS:
                return Type(TT_SYMBOL, optional);
            case E_STEAM_LOCOMOTIVE:
                return Type(TT_INTEGER, optional);
            case E_ROCKET:
                return Type(TT_DOUBLE, optional);
            case E_MEDIUM_WHITE_CIRCLE:
                if (optional) {
                    compilerWarning(token, "šŸ¬āšŖļø is identical to āšŖļø. Do not specify šŸ¬.");
                }
                return Type(TT_SOMETHING, false);
            case E_LARGE_BLUE_CIRCLE:
                return Type(TT_SOMEOBJECT, optional);
            case E_SPARKLES:
                compilerError(token, "The Nothingness type may not be referenced to.");
        }
    }
    
    Class *eclass = getClass(name, enamespace);
    if (eclass) {
        Type t = Type(eclass, optional);
        t.optional = optional;
        return t;
    }
    
    Protocol *protocol = getProtocol(name, enamespace);
    if(protocol){
        return Type(protocol, optional);
    }
    
    Enum *eenum = getEnum(name, enamespace);
    if(eenum){
        return Type(eenum, optional);
    }
    
    *existent = false;
    return typeNothingness;
}
Example #14
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;
    }
}
Example #15
0
void Procedure::parseGenericArguments(TypeContext ct, Package *package) {
    const Token *token;
    
    //Until the grape is found we parse arguments
    while ((token = nextToken()) && token->type == IDENTIFIER && token->value[0] == E_SPIRAL_SHELL) { //grape
        consumeToken();
        const Token *variable = consumeToken(VARIABLE);
        
        Type t = Type::parseAndFetchType(Type(eclass), AllowGenericTypeVariables, package, nullptr);
        genericArgumentConstraints.push_back(t);
        
        Type rType(TT_LOCAL_REFERENCE, false);
        rType.reference = genericArgumentVariables.size();
        
        if (genericArgumentVariables.count(variable->value)) {
            compilerError(variable, "A generic argument variable with the same name is already in use.");
        }
        genericArgumentVariables.insert(std::map<EmojicodeString, Type>::value_type(variable->value, rType));
    }
}
Example #16
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);
            }
        }
    }
}
Example #17
0
static const Token* until(EmojicodeChar end, EmojicodeChar deeper, int *deep) {
    const Token *token = consumeToken();
    
    if (token == nullptr) {
        compilerError(nullptr, "Unexpected end of program.");
    }
    
    if (token->type != IDENTIFIER) {
        return token;
    }
    
    if(token->value[0] == deeper){
        (*deep)++;
    }
    else if(token->value[0] == end){
        if (*deep == 0){
            return nullptr;
        }
        (*deep)--;
    }
    
    return token;
}
Example #18
0
Package* Package::loadPackage(const char *name, EmojicodeChar ns, const Token *errorToken) {
    Package *package = findPackage(name);
    
    if (package) {
        if (!package->finishedLoading()) {
            compilerError(errorToken, "Circular dependency detected: %s tried to load a package which intiatiated %sā€™s own loading.", name, name);
        }
    }
    else {
        char *path;
        asprintf(&path, packageDirectory "%s/header.emojic", name);
        
        package = new Package(name);
        
        if (strcmp("s", name) != 0) {
            package->loadPackage("s", globalNamespace, errorToken);
        }
        package->parse(path, errorToken);
    }
    
    package->loadInto(this, ns, errorToken);
    return package;
}
Example #19
0
void if1ld(charStarQueue** if1Files,
           char* mono,
           char* bindir,
           int warning,
           int profile,

           int forFortran,
           int forC,
	   int separateCompilation,

           charStarQueue** entries,
           charStarQueue** entriesForC,
           charStarQueue** entriesForFORTRAN,
           charStarQueue** reductionFunctions,


           char* QStamps
           ) {
   char loader[MAXPATHLEN];
   charStarQueue* argv = 0;
   char* entry = 0;

   sprintf(loader,"%s/if1ld",bindir);
   enqueue(&argv,loader);
   enqueue(&argv,"-o");
   enqueue(&argv,mono);

   if ( forFortran ) {
      enqueue(&argv,"-F");
   } else if ( forC ) {
      enqueue(&argv,"-C");
   } else {
      /* enqueue(&argv,"-S"); */
   }
   if ( !warning ) enqueue(&argv,"-w");
   if ( profile ) enqueue(&argv,"-W");
   if ( forFortran ) enqueue(&argv,"-F");
   if ( forC ) enqueue(&argv,"-C");
   if ( separateCompilation ) enqueue(&argv,"-S");
   while(entries && *entries) {
      entry = dequeue(entries);
      enqueue(&argv,"-e");
      enqueue(&argv,entry);
   }
   while(entriesForC && *entriesForC) {
      entry = dequeue(entriesForC);
      enqueue(&argv,"-c");
      enqueue(&argv,entry);
   }
   while(entriesForFORTRAN && *entriesForFORTRAN) {
      entry = dequeue(entriesForC);
      enqueue(&argv,"-f");
      enqueue(&argv,entry);
   }

   while(reductionFunctions && *reductionFunctions) {
      entry = dequeue(reductionFunctions);
      enqueue(&argv,"-r");
      enqueue(&argv,entry);
   }

   enqueue(&argv,QStamps);

   while(if1Files && *if1Files) {
      entry = dequeue(if1Files);
      enqueue(&argv,entry);
   }

   if ( Submit(&argv) != 0 ) {
      compilerError("if1 loader failure");
   }
}
Example #20
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;
    }
}
void analyzeClassesAndWrite(FILE *fout){
    Writer writer(fout);
    
    stringPool.push_back(new Token());
    
    writer.writeByte(ByteCodeSpecificationVersion);
    
    //Decide which classes inherit initializers, if they agree to protocols, and assign virtual table indexes before we analyze the classes!
    for (auto eclass : classes) {
        //decide whether this eclass is eligible for initializer inheritance
        if(eclass->instanceVariables.size() == 0 && eclass->initializerList.size() == 0){
            eclass->inheritsContructors = true;
        }
        
        if(eclass->superclass){
            eclass->nextClassMethodVti = eclass->superclass->nextClassMethodVti;
            eclass->nextInitializerVti = eclass->inheritsContructors ? eclass->superclass->nextInitializerVti : 0;
            eclass->nextMethodVti = eclass->superclass->nextMethodVti;
        }
        else {
            eclass->nextClassMethodVti = 0;
            eclass->nextInitializerVti = 0;
            eclass->nextMethodVti = 0;
        }
        
        Type classType = Type(eclass);
        
        for(auto method : eclass->methodList){
            Method *superMethod = eclass->superclass->getMethod(method->name);

            method->checkOverride(superMethod);
            if (superMethod){
                method->checkPromises(superMethod, "super method", classType);
                method->vti = superMethod->vti;
            }
            else {
                method->vti = eclass->nextMethodVti++;
            }
        }
        for(auto clMethod : eclass->classMethodList){
            ClassMethod *superMethod = eclass->superclass->getClassMethod(clMethod->name);
            
            clMethod->checkOverride(superMethod);
            if (superMethod){
                clMethod->checkPromises(superMethod, "super classmethod", classType);
                clMethod->vti = superMethod->vti;
            }
            else {
                clMethod->vti = eclass->nextClassMethodVti++;
            }
        }
        for(auto initializer : eclass->initializerList){ //TODO: heavily incorrect
            Initializer *superConst = eclass->superclass->getInitializer(initializer->name);
            
            initializer->checkOverride(superConst);
            if (superConst){
                initializer->checkPromises(superConst, "super classmethod", classType);
                //if a eclass has a initializer it does not inherit other initializers, therefore inheriting the VTI could have fatal consequences
            }
            initializer->vti = eclass->nextInitializerVti++;
        }
    }
    
    writer.writeUInt16(classes.size());
    
    uint8_t pkgCount = (uint8_t)packages.size();
    //must be s and _
    if(pkgCount == 2){
        pkgCount = 1;
    }
    if(pkgCount > 253){
        compilerError(nullptr, "You exceeded the maximum of 253 packages.");
    }
    writer.writeByte(pkgCount);
    
    size_t pkgI = 0;
    
    Package *pkg = nullptr;
    Class *eclass;
    for (size_t i = 0; eclass = classes[i], i < classes.size(); i++) {
        if((pkg != eclass->package && pkgCount > 1) || !pkg){ //pkgCount > 1: Ignore the second s
            if (i > 0){
                writer.writeByte(0);
            }
            pkg = eclass->package;
            Package *pkg = packages[pkgI++];
            
            uint16_t l = strlen(pkg->name) + 1;
            writer.writeUInt16(l);
            
            writer.writeBytes(pkg->name, l);
            
            writer.writeUInt16(pkg->version.major);
            writer.writeUInt16(pkg->version.minor);

            writer.writeByte(pkg->requiresNativeBinary ? 1 : 0);
        }
        else if (i > 0){
            writer.writeByte(1);
        }
        
        analyzeClass(Type(eclass), writer);
    }
    writer.writeByte(0);
    
    writer.writeUInt16(stringPool.size());
    for (auto token : stringPool) {
        writer.writeUInt16(token->value.size());
        
        for (auto c : token->value) {
            writer.writeEmojicodeChar(c);
        }
    }
    
    writer.writeUInt16(startingFlag.eclass->index);
    writer.writeUInt16(startingFlag.eclass->getClassMethod(E_CHEQUERED_FLAG)->vti);
}
void analyzeClass(Type classType, Writer &writer){
    auto eclass = classType.eclass;
    
    writer.writeEmojicodeChar(eclass->name);
    if(eclass->superclass){
        writer.writeUInt16(eclass->superclass->index);
    }
    else { //If the eclass does not have a superclass the own index gets written
        writer.writeUInt16(eclass->index);
    }
    
    Scope objectScope(true);
    
    //Get the ID offset for this eclass by summing up all superclasses instance variable counts
    uint16_t offset = 0;
    for(Class *aClass = eclass->superclass; aClass != nullptr; aClass = aClass->superclass){
        offset += aClass->instanceVariables.size();
    }
    writer.writeUInt16(eclass->instanceVariables.size() + offset);
    
    //Number of methods inclusive superclass
    writer.writeUInt16(eclass->nextMethodVti);
    //Number of eclass methods inclusive superclass
    writer.writeUInt16(eclass->nextClassMethodVti);
    //Initializer inclusive superclass
    writer.writeByte(eclass->inheritsContructors ? 1 : 0);
    writer.writeUInt16(eclass->nextInitializerVti);
    
    writer.writeUInt16(eclass->methodList.size());
    writer.writeUInt16(eclass->initializerList.size());
    writer.writeUInt16(eclass->classMethodList.size());
    
    for (auto var : eclass->instanceVariables) {
        CompilerVariable *cv = new CompilerVariable(var->type, offset++, 1, false);
        cv->variable = var;
        objectScope.setLocalVariable(var->name, cv);
    }
    
    pushScope(&objectScope);
    
    for (auto method : eclass->methodList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*method, writer, classType);
    }
    
    for (auto initializer : eclass->initializerList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*initializer, writer, classType, false, initializer);
    }
    
    popScope();
    
    for (auto classMethod : eclass->classMethodList) {
        StaticFunctionAnalyzer::writeAndAnalyzeProcedure(*classMethod, writer, classType, true);
    }
    
    if (eclass->instanceVariables.size() > 0 && eclass->initializerList.size() == 0) {
        auto str = classType.toString(typeNothingness, true);
        compilerWarning(eclass->classBegin, "Class %s defines %d instances variables but has no initializers.", str.c_str(), eclass->instanceVariables.size());
    }
    
    writer.writeUInt16(eclass->protocols().size());
    
    if (eclass->protocols().size() > 0) {
        auto biggestPlaceholder = writer.writePlaceholder<uint16_t>();
        auto smallestPlaceholder = writer.writePlaceholder<uint16_t>();

        uint_fast16_t smallestProtocolIndex = UINT_FAST16_MAX;
        uint_fast16_t biggestProtocolIndex = 0;
        
        for (auto protocol : eclass->protocols()) {
            writer.writeUInt16(protocol->index);
            
            if (protocol->index > biggestProtocolIndex) {
                biggestProtocolIndex = protocol->index;
            }
            if (protocol->index < smallestProtocolIndex) {
                smallestProtocolIndex = protocol->index;
            }
            
            writer.writeUInt16(protocol->methods().size());
            
            for (auto method : protocol->methods()) {
                Method *clm = eclass->getMethod(method->name);
                
                if (clm == nullptr) {
                    auto className = classType.toString(typeNothingness, true);
                    auto protocolName = Type(protocol, false).toString(typeNothingness, true);
                    ecCharToCharStack(method->name, ms);
                    compilerError(eclass->classBegin, "Class %s does not agree to protocol %s: Method %s is missing.", className.c_str(), protocolName.c_str(), ms);
                }
                
                writer.writeUInt16(clm->vti);
                clm->checkPromises(method, "protocol definition", classType);
            }
        }
        
        biggestPlaceholder.write(biggestProtocolIndex);
        smallestPlaceholder.write(smallestProtocolIndex);
    }
}
Example #23
0
void Method::setGenericParam() {
    m_genericParam = popGenericNameList();
    if(m_genericParam != NULL && getGenre() == EGENRE::_DELEGATE) {
        compilerError(ERR_NOT_SUPPORTED_YET, "Generic delegates are not supported yet");
    }
}