SemanticAnalysis::SemanticAnalysis(CompileContext &cc, TranslationUnit *tu)
    : cc_(cc),
      pool_(cc.pool()),
      types_(cc.types()),
      tu_(tu),
      funcstate_(nullptr)
{
}
Example #2
0
bool
VarDeclSpecHelper::receiveConstQualifier(CompileContext &cc, const SourceLocation &constLoc, Type *type)
{
  VariableSymbol *sym = decl_->sym();
  if (sym->isArgument()) {
    if (!!(sym->storage_flags() & StorageFlags::byref)) {
      cc.report(constLoc, rmsg::const_ref_has_no_meaning) << type;
      return true;
    }
    if (!type->passesByReference()) {
      cc.report(constLoc, rmsg::const_has_no_meaning) << type;
      return true;
    }
  } else if (TypeSupportsCompileTimeInterning(type)) {
    sym->storage_flags() |= StorageFlags::constval;
  }

  sym->storage_flags() |= StorageFlags::readonly;
  return true;
}
Example #3
0
SemanticAnalysis::SemanticAnalysis(CompileContext &cc, TranslationUnit *unit)
 : pool_(cc.pool()),
   cc_(cc),
   unit_(unit),
   scope_(unit_->globalScope()),
   fun_(nullptr),
   loop_(nullptr),
   hir_(nullptr),
   outp_(nullptr)
{
}
Example #4
0
NameResolver::NameResolver(CompileContext &cc)
 : cc_(cc),
   pool_(cc.pool()),
   tr_(cc),
   layout_scope_(nullptr)
{
  atom_String_ = cc_.add("String");
  atom_Float_ = cc_.add("Float");
  atom_any_ = cc_.add("any");
  atom_Function_ = cc_.add("Function");
  atom_bool_ = cc_.add("bool");
}
Example #5
0
bool ASTType::resolveType(CompileContext& context, const ASTTypeVariables* ptypevariables)
{
   if ( ptypevariables != NULL )
   {
      const ASTTypeVariable* ptypevariable = ptypevariables->find(mObjectName);
      if ( ptypevariable != NULL )
      {
         mKind = ASTType::eGeneric;
         mpTypeVariable = ptypevariable;

         return true;
      }
   }
      
   if ( mKind == eObject )
   {
      for ( int index = 0; index < mTypeArguments.size(); index++ )
      {
         if ( !mTypeArguments[index].resolveType(context, ptypevariables) )
         {
            return false;
         }
      }

      mpObjectClass = &context.resolveClass(mObjectName);
   }
   else if ( mKind == eArray )
   {
      mpObjectClass = &context.resolveClass(UTEXT("system.InternalArray"));
      return mpArrayType->resolveType(context, ptypevariables);
   }
   else if ( mKind == eString )
   {
      mpObjectClass = &context.resolveClass(UTEXT("system.InternalString"));
   }

   return true;
}
Example #6
0
 Analyzer(CompileContext &cc, Comments &comments)
  : cc_(cc),
    pool_(cc.pool()),
    comments_(comments)
 {
   atom_name_ = cc_.add("name");
   atom_kind_ = cc_.add("kind");
   atom_returnType_ = cc_.add("returnType");
   atom_type_ = cc_.add("type");
   atom_parameters_ = cc_.add("arguments");
   atom_doc_start_ = cc_.add("docStart");
   atom_doc_end_ = cc_.add("docEnd");
   atom_properties_ = cc_.add("properties");
   atom_methods_ = cc_.add("methods");
   atom_getter_ = cc_.add("getter");
   atom_setter_ = cc_.add("setter");
   atom_entries_ = cc_.add("entries");
   atom_constants_ = cc_.add("constants");
   atom_decl_ = cc_.add("decl");
 }
Example #7
0
// Type Resolution ensures that any type specifier has a bound type, and that
// any constant expression has a constant value.
//
// This pass involves a recursive walk through the AST. Unlike other passes,
// it may recursively resolve other unrelated AST nodes. For example,
// 
//   typedef A = B;
//   typedef B = int;
//
// In order to resolve "A", we will recursively resolve "B". If we have a
// recursive type, we have to prevent infintie recursion and report an error.
// Recursive types always occur through name resolution, and there are many
// patterns in which they can occur.
//
// ---- CONSTANT RECURSION ----
//
// The first form of recursion we're concerned about is 'constant recursion'.
// This occurs when resolving a constant expression, it is mutually dependent
// on another constant expression. There are a few ways to do this. The first
// is via enum values:
//
//    1: enum X {
//    2:   A = B,
//    3:   B,
//    4: };
//
// On line 2, resolving the type of 'A' depends on resolving 'B'. We cannot
// resolve 'B' without knowing the type of 'A'.
//
// Another form of constant recursion is through constant definitions:
//
//    1: const int A = B;
//    2: const int B = A;
//
// ---- TYPE RECURSION ----
//
// We classify type recursion in two forms. The first is simple type recursion,
// when a typedef refers to itself. These cycles are easy to break, and we
// break them in visitTypedef() via a placeholder type. An example:
//
//    typedef A = B
//    typedef B = A
//
// While visit "A", we will create a blank TypedefType object. We will then
// visit B, which will build a TypedefType object wrapping A. Once back in A,
// we do a quick check that A does not depend on itself for computing a
// canonical type.
//
// The other form of type recursive is size-dependent types. An easy example of
// this in C would be:
//
//    struct X {
//      X x;
//    };
//
// To allocate a struct we must be able to compute its size. But here, its size
// infinitely expands, and so the type is not resolveable. Another case where
// this can happen is with the `sizeof` constexpr. For example,
//
//    int X[sizeof(Y)] = 10;
//    int Y[sizeof(X)] = 20;
//
// Here, the size of `x` is dependent on computing its own size. We will break
// this cycle when calling resolveType for sizeof(X), since we will not have
// finished resolving the type of X. In the future, we may be able to reach
// something like this through typedefs as well:
//
//    typedef X = int[sizeof(Y)];
//    typedef Y = int[sizeof(X)];
//
// This cycle would be broken by sizeof() itself, since it checks whether or
// not it is trying to compute an unresolved type.
//
// Types can generally reference themselves as long as they do not create size
// dependencies, and in the case of typedefs, as long as we can resolve them to
// a canonical type that is not a typedef.
//
TypeResolver::TypeResolver(CompileContext &cc)
 : pool_(cc.pool()),
   cc_(cc)
{
}