Exemplo n.º 1
0
const ASTTypeVariable& ASTType::getTypeVariable() const
{
   ASSERT(isGeneric());
   if ( mKind == eArray )
   {
      return mpArrayType->getTypeVariable();
   }
   return *mpTypeVariable;
}
Exemplo n.º 2
0
static void reportType (tokenInfo *const token)
{
    vStringUpper (token->string);
    if (vStringLength (token->string) > 0  && ! isGeneric (token)  &&
            (SelfReferences || strcmp (vStringValue (
                                           token->string), vStringValue (token->className)) != 0) &&
            ! stringListHas (ReferencedTypes, vStringValue (token->string)))
    {
        printf ("%s\n", vStringValue (token->string));
        stringListAdd (ReferencedTypes, vStringNewCopy (token->string));
    }
}
Exemplo n.º 3
0
void Tree::lookupAndSetTypeDefinitionInCurrentTree(
    Type* type,
    const NameBindings& scope,
    const Location& location) {

    auto definition = scope.lookupType(type->getName());
    if (definition == nullptr) {
        Trace::error("Unknown type: " + type->getName(), location);
    }

    type->setDefinition(definition);

    auto classDefinition = definition->dynCast<ClassDefinition>();
    if (classDefinition != nullptr && classDefinition == getCurrentClass()) {
        classDefinition->setRecursive(true);
    }

    if (type->isFunction()) {
        auto signature = type->getFunctionSignature();
        lookupAndSetTypeDefinitionInCurrentTree(signature->getReturnType(),
                                                scope,
                                                location);
        for (auto argumentType: signature->getArguments()) {
            lookupAndSetTypeDefinitionInCurrentTree(argumentType,
                                                    scope,
                                                    location);
        }
    }

    if (type->hasGenericTypeParameters()) {
        // The type has generic type parameters. This means the type must refer
        // to a generic class.
        if (classDefinition == nullptr) {
            Trace::error("Only classes can take type parameters: " +
                          type->getName(),
                          location);
        }

        if (!classDefinition->isGeneric()) {
            Trace::error("Only generic classes can take type parameters: " +
                          type->getName(),
                          location);
        }

        for (auto typeParameter: type->getGenericTypeParameters()) {
            lookupAndSetTypeDefinitionInCurrentTree(typeParameter,
                                                    scope,
                                                    location);
        }
    }
}
Exemplo n.º 4
0
ClassDefinition* Tree::startClass(
    const Identifier& name,
    const GenericTypeParameterList& genericTypeParameters,
    const IdentifierList& parents,
    ClassDefinition::Properties& properties,
    const Location& location) {

    NameBindings* containingNameBindings = &globalNameBindings;
    auto containingClass = getCurrentClass();
    if (containingClass != nullptr) {
        containingNameBindings = &(containingClass->getNameBindings());
    }

    auto newClass = ClassDefinition::create(name,
                                            genericTypeParameters,
                                            parents,
                                            containingNameBindings,
                                            properties,
                                            location);
    if (containingClass != nullptr) {
        newClass->setIsImported(containingClass->isImported());
    }

    if (!containingNameBindings->insertClass(name, newClass)) {
        Trace::error("Class already declared at the same scope: " + name,
                     location);
    }

    if (!newClass->isGeneric()) {
        // For generic message classes, the empty copy constructor will be
        // generated when the concrete class is created from the generic one.
        if (newClass->needsCloneMethod()) {
            // The body of the copy constructor will be generated later by the
            // CloneGenerator, here we just generate an empty copy constructor.
            // The reason for generating an empty copy constructor at this stage
            // is that the copy constructor needs to be in the name bindings of
            // the new class before any other class can inherit from it.
            // Otherwise, the copy constructor will not be in the name bindings
            // of the derived class since name bindings are copied from the base
            // class to the derived class.
            newClass->generateEmptyCopyConstructor();
            CloneGenerator::generateEmptyCloneMethod(newClass);
        }
    }

    openClasses.push_back(newClass);
    return newClass;
}
Exemplo n.º 5
0
Type* Tree::makeGenericTypeConcreteInCurrentTree(
    Type* type,
    const NameBindings& scope,
    const Location& location) {

    if (type->isFunction()) {
        makeSignatureTypesConcrete(type->getFunctionSignature(),
                                   scope,
                                   location);
    }

    auto typeDefinition = type->getDefinition();
    assert(typeDefinition != nullptr);
    if (typeDefinition->isGenericTypeParameter()) {
        // Since the type is a generic type parameter, we must lookup the type
        // definition even though the type already has a definition. This is
        // because the generic type parameter definitions are cloned when a
        // concrete class is generated from a generic class, and the type needs
        // to refer to the cloned generic type parameter definition.
        lookupAndSetTypeDefinitionInCurrentTree(type, scope, location);
        return type->getConcreteTypeAssignedToGenericTypeParameter();
    }

    if (type->hasGenericTypeParameters()) {
        // The type has type parameters. For example, the type could be like 
        // this: 'Foo<T>' where T is a generic type parameter which we have to
        // map to a concrete type. Or, the type could be like this 'Foo<int>'.
        // In all cases we must make sure that the definition of the type is
        // the generated concrete class.
        assert(typeDefinition->getKind() == Definition::Class);
        auto classDef = typeDefinition->cast<ClassDefinition>();
        if (classDef->isGeneric()) {
            // The class is still a generic, which means we must get the
            // generated concrete class.
            typeDefinition = getConcreteClassFromTypeParameterList(type,
                                                                   scope,
                                                                   classDef,
                                                                   location);
            type->setDefinition(typeDefinition);
            return type;
        }
        // The class is not generic so it is already the generated concrete
        // class. Do nothing.
    }

    return nullptr;
}
Exemplo n.º 6
0
/// \brief Test whether that is greater than this type
bool ASTType::greater(const ASTType& that) const
{
   if ( isNull() && (that.isObject() || that.isArray() || that.isString() || that.isGeneric()) )
   {
      return true;
   }
   else if ( isObject() && that.isObject() )
   {
      // check if 'that' is a extending or implemented this

      if ( !(mTypeArguments == that.mTypeArguments) )
      {
         return false;
      }

      return getObjectClass().isBase(that.getObjectClass()) 
          || getObjectClass().isImplementing(that.getObjectClass());
   }
   else if ( isArray() && that.isArray() )
   {
      return mpArrayType->equals(*that.mpArrayType) && mArrayDimension == that.mArrayDimension;
   }
   else if ( isGeneric() )
   {
      if ( that.isObject() )
      {
          return that.getObjectName() == UTEXT("system.Object"); // object is greater than a generic (its da uber type)
      }
      else if ( that.isGeneric() )
      {
         return mObjectName == that.mObjectName;
      }
   }
   else if ( !isObject() && !that.isObject() )
   {
      switch ( that.mKind )
      {
         case eBoolean:
            return mKind == eBoolean;

         case eInt:
            return mKind == eInt;

         case eReal:
            return mKind == eInt || mKind == eReal;

         case eChar:
            return mKind == eChar;

         case eString:
            return mKind == eString || mKind == eInt || mKind == eReal || mKind == eBoolean || mKind == eChar;
            
         default:
            break;
      }
   }

   // no implicit primitive to basic or vs yet

   return false;
}