Ejemplo n.º 1
0
::helpers::path Builder::get_crate_path(const PackageManifest& manifest, const PackageTarget& target, bool is_for_host, const char** crate_type, ::std::string* out_crate_suffix) const
{
    auto outfile = this->get_output_dir(is_for_host);
    // HACK: If there's no version, don't emit a version tag
    ::std::string   crate_suffix;
#if 1
    if( manifest.version() != PackageVersion() ) {
        crate_suffix = ::format("-", manifest.version());
        for(auto& v : crate_suffix)
            if(v == '.')
                v = '_';
    }
#endif

    switch(target.m_type)
    {
    case PackageTarget::Type::Lib:
        if(crate_type) {
            *crate_type = target.m_is_proc_macro ? "proc-macro" : "rlib";
        }
        outfile /= ::format("lib", target.m_name, crate_suffix, ".hir");
        break;
    case PackageTarget::Type::Bin:
        if(crate_type)
            *crate_type = "bin";
        outfile /= ::format(target.m_name, EXESUF);
        break;
    default:
        throw ::std::runtime_error("Unknown target type being built");
    }
    if(out_crate_suffix)
        *out_crate_suffix = crate_suffix;
    return outfile;
}
Ejemplo n.º 2
0
PackageLoadingState packageLoad(const char *name, uint16_t major, uint16_t minor, FunctionFunctionPointerProvider *hfpMethods,
                                InitializerFunctionFunctionPointerProvider *hfpIntializer,
                                mpfc *mpfc, dpfc *dpfc, SizeForClassFunction *sfch){
    char *path;
    asprintf(&path, "%s/%s-v%d/%s.%s", packageDirectory, name, major, name, "so");
    
    void* package = dlopen(path, RTLD_LAZY);
    
    free(path);
    
    if(!package)
        return PACKAGE_LOADING_FAILED;
    
    *hfpMethods = dlsym(package, "handlerPointerForMethod");
    *hfpIntializer = dlsym(package, "handlerPointerForInitializer");
    *mpfc = dlsym(package, "markerPointerForClass");
    *dpfc = dlsym(package, "deinitializerPointerForClass");
    *sfch = dlsym(package, "sizeForClass");
    
    PackageVersion(*pvf)() = dlsym(package, "getVersion");
    PackageVersion pv = pvf();
    
    if(!*hfpMethods || !*hfpIntializer)
        return PACKAGE_LOADING_FAILED;
    
    if(pv.major != major)
        return PACKAGE_INAPPROPRIATE_MAJOR;

    if(pv.minor < minor)
        return PACKAGE_INAPPROPRIATE_MINOR;
    
    return PACKAGE_LOADED;
}
Ejemplo n.º 3
0
void PackageParser::parse() {
    while (stream_.hasMoreTokens()) {
        auto documentation = parseDocumentationToken();
        
        auto exported = Attribute<E_EARTH_GLOBE_EUROPE_AFRICA>().parse(&stream_);
        auto theToken = stream_.consumeToken(IDENTIFIER);
        switch (theToken.value[0]) {
            case E_PACKAGE: {
                exported.disallow();
                
                auto nameToken = stream_.consumeToken(VARIABLE);
                auto namespaceToken = stream_.consumeToken(IDENTIFIER);
                
                auto name = nameToken.value.utf8CString();
                package_->loadPackage(name, namespaceToken.value[0], theToken);
                
                continue;
            }
            case E_CROCODILE:
                parseProtocol(documentation, theToken, exported.set());
                continue;
            case E_TURKEY:
                parseEnum(documentation, exported.set());
                continue;
            case E_RADIO:
                exported.disallow();
                package_->setRequiresBinary();
                if (strcmp(package_->name(), "_") == 0) {
                    throw CompilerErrorException(theToken, "You may not set 📻 for the _ package.");
                }
                continue;
            case E_CRYSTAL_BALL: {
                exported.disallow();
                if (package_->validVersion()) {
                    throw CompilerErrorException(theToken, "Package version already declared.");
                }
                
                auto major = stream_.consumeToken(INTEGER).value.utf8CString();
                auto minor = stream_.consumeToken(INTEGER).value.utf8CString();
                
                uint16_t majori = strtol(major, nullptr, 0);
                uint16_t minori = strtol(minor, nullptr, 0);
                
                delete [] major;
                delete [] minor;
                
                package_->setPackageVersion(PackageVersion(majori, minori));
                if (!package_->validVersion()) {
                    throw CompilerErrorException(theToken, "The provided package version is not valid.");
                }
                
                continue;
            }
            case E_WALE: {
                exported.disallow();
                EmojicodeChar className, enamespace;
                bool optional;
                auto &classNameToken = parseTypeName(&className, &enamespace, &optional);
                
                if (optional) {
                    throw CompilerErrorException(classNameToken, "Optional types are not extendable.");
                }
                
                Type type = typeNothingness;
                
                if (!package_->fetchRawType(className, enamespace, optional, theToken, &type)) {
                    throw CompilerErrorException(classNameToken, "Class does not exist.");
                }
                if (type.type() != TT_CLASS) {
                    throw CompilerErrorException(classNameToken, "Only classes are extendable.");
                }
                
                // Native extensions are allowed if the class was defined in this package.
                parseClassBody(type.eclass, nullptr, type.eclass->package() == package_);
                
                continue;
            }
            case E_RABBIT:
                parseClass(documentation, theToken, exported.set());
                continue;
            case E_SCROLL: {
                exported.disallow();
                auto pathString = stream_.consumeToken(STRING);
                auto relativePath = pathString.position().file;
                auto fileString = pathString.value.utf8CString();
                
                char *str = fileString;
                const char *lastSlash = strrchr(relativePath, '/');
                if (lastSlash != nullptr) {
                    const char *directory = strndup(relativePath, lastSlash - relativePath);
                    asprintf(&str, "%s/%s", directory, fileString);
                    delete [] fileString;
                    delete [] directory;
                }
                
                PackageParser(package_, lex(str)).parse();
                
                delete [] str;
                continue;
            }
            default:
                ecCharToCharStack(theToken.value[0], f);
                throw CompilerErrorException(theToken, "Unexpected identifier %s", f);
                break;
        }
    }
}