示例#1
0
TypeSpec
ASTfunction_call::typecheck_all_poly (TypeSpec expected, bool coerce)
{
    for (FunctionSymbol *poly = func();  poly;  poly = poly->nextpoly()) {
        const char *code = poly->argcodes().c_str();
        int advance;
        TypeSpec returntype = m_compiler->type_from_code (code, &advance);
        code += advance;
        if (check_arglist (m_name.c_str(), args(), code, coerce)) {
            // Return types also must match if not coercible
            if (coerce || expected == TypeSpec() || expected == returntype) {
                m_sym = poly;
                return returntype;
            }
        }
    }
    return TypeSpec();
}
示例#2
0
void
OSLCompilerImpl::initialize_builtin_funcs ()
{
    for (int i = 0;  builtin_func_args[i];  ++i) {
        ustring funcname (builtin_func_args[i++]);
        // Count the number of polymorphic versions and look for any
        // special hint markers.
        int npoly = 0;
        bool readwrite_special_case = false;
        bool texture_args = false;
        bool printf_args = false;
        bool takes_derivs = false;
        for (npoly = 0;  builtin_func_args[i+npoly];  ++npoly) {
            if (! strcmp (builtin_func_args[i+npoly], "!rw"))
                readwrite_special_case = true;
            else if (! strcmp (builtin_func_args[i+npoly], "!tex"))
                texture_args = true;
            else if (! strcmp (builtin_func_args[i+npoly], "!printf"))
                printf_args = true;
            else if (! strcmp (builtin_func_args[i+npoly], "!deriv"))
                takes_derivs = true;
        }
        // Now add them in reverse order, so the order in the table is
        // the priority order for approximate matches.
        for (int j = npoly-1;  j >= 0;  --j) {
            if (builtin_func_args[i+j][0] == '!')  // Skip special hints
                continue;
            ustring poly (builtin_func_args[i+j]);
            Symbol *last = symtab().clash (funcname);
            ASSERT (last == NULL || last->symtype() == SymTypeFunction);
            TypeSpec rettype = type_from_code (poly.c_str());
            FunctionSymbol *f = new FunctionSymbol (funcname, rettype);
            f->nextpoly ((FunctionSymbol *)last);
            f->argcodes (poly);
            f->readwrite_special_case (readwrite_special_case);
            f->texture_args (texture_args);
            f->printf_args (printf_args);
            f->takes_derivs (takes_derivs);
            symtab().insert (f);
        }
        i += npoly;
    }
}
示例#3
0
TypeSpec
ASTfunction_call::typecheck (TypeSpec expected)
{
    typecheck_children ();

    bool match = false;

    // Look for an exact match, including expected return type
    m_typespec = typecheck_all_poly (expected, false);
    if (m_typespec != TypeSpec())
        match = true;

    // Now look for an exact match on args, but any assignable return type
    if (! match && expected != TypeSpec()) {
        m_typespec = typecheck_all_poly (TypeSpec(), false);
        if (m_typespec != TypeSpec())
            match = true;
    }

    // Now look for a coercible match of args, exact march on return type
    if (! match) {
        m_typespec = typecheck_all_poly (expected, true);
        if (m_typespec != TypeSpec())
            match = true;
    }

    // All that failed, try for a coercible match on everything
    if (! match && expected != TypeSpec()) {
        m_typespec = typecheck_all_poly (TypeSpec(), true);
        if (m_typespec != TypeSpec())
            match = true;
    }

    if (match) {
        if (! is_user_function ())
            typecheck_builtin_specialcase ();
        return m_typespec;
    }

    // Couldn't find any way to match any polymorphic version of the
    // function that we know about.  OK, at least try for helpful error
    // message.
    std::string choices ("");
    for (FunctionSymbol *poly = func();  poly;  poly = poly->nextpoly()) {
        const char *code = poly->argcodes().c_str();
        int advance;
        TypeSpec returntype = m_compiler->type_from_code (code, &advance);
        code += advance;
        if (choices.length())
            choices += "\n";
        choices += Strutil::format ("\t%s %s (%s)",
                              type_c_str(returntype), m_name.c_str(),
                              m_compiler->typelist_from_code(code).c_str());
    }

    std::string actualargs;
    for (ASTNode::ref arg = args();  arg;  arg = arg->next()) {
        if (actualargs.length())
            actualargs += ", ";
        actualargs += arg->typespec().string();
    }

    error ("No matching function call to '%s (%s)'\n    Candidates are:\n%s", 
           m_name.c_str(), actualargs.c_str(), choices.c_str());
    return TypeSpec();
}