예제 #1
0
Type *
NameResolver::resolveBase(TypeSpecifier &spec)
{
  switch (spec.resolver()) {
    // These are the most common cases - either a primitive type or a signature
    // containing primitive types. In some cases we could have already resolved
    // the type even earlier, for example, the parser does this for certain =
    // builtin tags.
    case TOK_VOID:
      return cc_.types()->getVoid();
    case TOK_IMPLICIT_INT:
      return cc_.types()->getImplicitInt();
    case TOK_INT:
      return cc_.types()->getPrimitive(PrimitiveType::Int32);
    case TOK_BOOL:
      return cc_.types()->getPrimitive(PrimitiveType::Bool);
    case TOK_CHAR:
      return cc_.types()->getPrimitive(PrimitiveType::Char);
    case TOK_FLOAT:
      return cc_.types()->getPrimitive(PrimitiveType::Float);
    case TOK_DEFINED:
      return spec.getResolvedBase();
    case TOK_FUNCTION:
    {
      FunctionSignature *sig = spec.signature();
      if (!sig->isResolved())
        return nullptr;
      return FunctionType::New(sig);
    }

    case TOK_LABEL:
    case TOK_NAME:
    {
      NameProxy *proxy = spec.proxy();
      Symbol *sym = proxy->sym();
      if (!sym) {
        // This can happen if we use a type before it's been defined. We wait
        // until type resolution to try again.
        return nullptr;
      }

      TypeSymbol *ts = sym->asType();
      if (!ts) {
        cc_.report(proxy->loc(), rmsg::not_a_type) << sym->name();
        return nullptr;
      }

      // If we resolved a TypeSymbol, we must have allocated a Type object
      // (even if it's incomplete).
      assert(ts->type());
      return ts->type();
    }

    default:
      return nullptr;
  }
}
예제 #2
0
bool
NameResolver::canDefineMethodmap(MethodmapDecl *methodmap)
{
  // Methodmaps are only allowed in the global scope. They have very odd
  // semantics (by design, as part of the transitional syntax): they
  // create an enum, or they extend an existing enum, in any declaration
  // order.
  //
  // If the symbol already exists, it must be a direct enum type. We do
  // not accept typedefs.
  assert(getOrCreateScope() == globals_);

  Symbol *prev = globals_->lookup(methodmap->name());
  if (!prev)
    return true;

  TypeSymbol *sym = prev->asType();
  if (!sym) {
    cc_.report(methodmap->loc(), rmsg::methodmap_on_non_type)
      << sym->name();
    return false;
  }

  // Builtin types do not have AST nodes.
  if (!sym->node()) {
    cc_.report(methodmap->loc(), rmsg::methodmap_on_non_enum)
      << sym->name();
    return false;
  }

  EnumStatement *stmt = sym->node()->asEnumStatement();
  if (!stmt) {
    if (sym->node()->asMethodmapDecl()) {
      // We had something like:
      //   methodmap X {}
      //   methodmap X {}
      //
      // We can give a slightly more specific error for this case.
      cc_.report(methodmap->loc(), rmsg::methodmap_already_defined)
        << methodmap->name();
    } else {
      cc_.report(methodmap->loc(), rmsg::methodmap_on_non_enum)
        << sym->name();
    }
    return false;
  }

  // Mark that our enum statement has a methodmap.
  stmt->setMethodmap(methodmap);

  // Point the layout at the enum type.
  methodmap->setSymbol(sym);

  // Return false - symbol is already defined.
  return false;
}
예제 #3
0
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);
    }
}