Esempio n. 1
0
TypeSpec
ASTreturn_statement::typecheck (TypeSpec expected)
{
    FunctionSymbol *myfunc = oslcompiler->current_function ();
    if (myfunc) {
        // If it's a user function (as opposed to a main shader body)...
        if (expr()) {
            // If we are returning a value, it must be assignable to the
            // kind of type the function actually returns.  This check
            // will also catch returning a value from a void function.
            TypeSpec et = expr()->typecheck (myfunc->typespec());
            if (! assignable (myfunc->typespec(), et)) {
                error ("Cannot return a '%s' from '%s %s()'",
                       type_c_str(et), type_c_str(myfunc->typespec()),
                       myfunc->name().c_str());
            }
        } else {
            // If we are not returning a value, it must be a void function.
            if (! myfunc->typespec().is_void ())
                error ("You must return a '%s' from function '%s'",
                       type_c_str(myfunc->typespec()),
                       myfunc->name().c_str());
        }
        // If the function has other statements AFTER 'return', or if
        // the return statement is in a conditional, we'll need to
        // handle it specially when generating code.
        myfunc->complex_return (this->nextptr() != NULL ||
                                myfunc->nesting_level() > 0);
    } else {
        // We're not part of any user function, so this 'return' must 
        // be from the main shader body.  That's fine (it's equivalent
        // to calling exit()), but it can't return a value.
        if (expr())
            error ("Cannot return a value from a shader body");
    }
    return TypeSpec(); // TODO: what should be returned here?
}
void
SemanticAnalysis::visitNameProxy(NameProxy *proxy)
{
    Symbol *binding = proxy->sym();
    switch (binding->kind()) {
    case Symbol::kType:
        cc_.report(proxy->loc(), rmsg::cannot_use_type_as_value)
                << binding->asType()->type();
        break;

    case Symbol::kConstant:
    {
        ConstantSymbol *sym = binding->toConstant();
        proxy->setOutput(sym->type(), VK::rvalue);
        break;
    }

    case Symbol::kFunction:
    {
        FunctionSymbol *sym = binding->toFunction();
        FunctionStatement *decl = sym->impl();
        if (!decl) {
            cc_.report(proxy->loc(), rmsg::function_has_no_impl)
                    << sym->name();
            break;
        }

        if (!decl->type())
            decl->setType(FunctionType::New(decl->signature()));

        // Function symbols are clvalues, since they are named.
        // :TODO:
        proxy->setOutput(decl->type(), VK::lvalue);
        break;
    }

    default:
        assert(false);
    }
}