blob: 2309dde1968a14b6460cde70aa84baa220b8383e [file] [log] [blame]
//===-- AST ContainerType Class ---------------------------------*- C++ -*-===//
//
// High Level Virtual Machine (HLVM)
//
// Copyright (C) 2006 Reid Spencer. All Rights Reserved.
//
// This software is free software; you can redistribute it and/or modify it
// under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 of the License, or (at
// your option) any later version.
//
// This software is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
// more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this library in the file named LICENSE.txt; if not, write to the
// Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
// MA 02110-1301 USA
//
//===----------------------------------------------------------------------===//
/// @file hlvm/AST/ContainerType.h
/// @author Reid Spencer <reid@hlvm.org> (original author)
/// @date 2006/05/04
/// @since 0.1.0
/// @brief Declares the class hlvm::AST::ContainerType
//===----------------------------------------------------------------------===//
#ifndef HLVM_AST_CONTAINERTYPE_H
#define HLVM_AST_CONTAINERTYPE_H
#include <hlvm/AST/Type.h>
namespace hlvm
{
/// This class provides an Abstract Syntax Tree node that represents a uniform
/// container type. Uniform container types are those types that reference
/// another type. They may have multiple elements but all elements are of the
/// same type, hence they are uniform. This is true of types such as
/// PointerType, ArrayType, and VectorTYpe.
/// @brief AST Abstract Uniform Container Type Node
class UniformContainerType : public Type
{
/// @name Constructors
/// @{
protected:
UniformContainerType(NodeIDs id) : Type(id), elemType(0) {}
virtual ~UniformContainerType();
/// @}
/// @name Accessors
/// @{
public:
const Type* getElementType() const { return elemType; }
virtual const char* getPrimitiveName() const; // asserting override
/// Methods to support type inquiry via isa, cast, dyn_cast
static inline bool classof(const UniformContainerType*) { return true; }
static inline bool classof(const Type* T) {
return T->isUniformContainerType();
}
/// @}
/// @name Mutators
/// @{
public:
virtual void resolveTypeTo(const Type* from, const Type* to);
void setElementType(const Type* t) { elemType = t; }
/// @}
/// @name Data
/// @{
protected:
const Type* elemType; ///< The contained types
/// @}
};
/// This class provides an Abstract Syntax Tree node that represents a storage
/// location that is a pointer to another storage location of a specific type.
/// PointerType is a UniformContainerType meaning that the referrent object is
/// of only one type.
/// @brief AST Pointer Type Node
class PointerType : public UniformContainerType
{
/// @name Constructors
/// @{
protected:
PointerType() : UniformContainerType(PointerTypeID) {}
virtual ~PointerType();
/// @}
/// @name Accessors
/// @{
public:
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const PointerType*) { return true; }
static inline bool classof(const Node* T) { return T->is(PointerTypeID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree note that represents an array of
/// some type. An array is a sequential layout of multiple elements all of the
/// same type. Arrays in HLVM are dynamically resizeable but the type
/// specification can indicate a maximum size beyond which the array cannot
/// grow. Setting the maximum size to 0 indicates that the size of the array
/// is unbounded and it may grow to the limits of available memory. This
/// usage is discouraged as knowing the maximum memory size can make the
/// implementation of the array more efficient in its use of memory and limit
/// the amount of reallocation necessary when the array changes size. An
/// ArrayType is a UniformContainerType because it contains a number of elements
/// all of uniform type.
/// @brief AST Array Type Node
class ArrayType : public UniformContainerType
{
/// @name Constructors
/// @{
protected:
ArrayType() : UniformContainerType(ArrayTypeID), maxSize(0) {}
virtual ~ArrayType();
/// @}
/// @name Accessors
/// @{
public:
/// Get the maximum size the array can grow to.
uint64_t getMaxSize() const { return maxSize; }
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const ArrayType*) { return true; }
static inline bool classof(const Node* T) { return T->is(ArrayTypeID); }
/// @}
/// @name Mutators
/// @{
public:
/// Set the maximum size the array can grow to.
void setMaxSize(uint64_t max) { maxSize = max; }
/// @}
/// @name Data
/// @{
protected:
uint64_t maxSize; ///< The maximum number of elements in the array
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree Node that represents a fixed
/// size, packed vector of some other type. Some languages call this an "array"
/// but arrays in HLVM can be dynamically resized. Vectors, however, cannot
/// be resized. Where possible, HLVM will attempt to generate code that makes
/// use of a machines vector instructions to process vector types. Except for
/// the fixed size, VectorType objects are identical in functionality to
/// ArrayType objects. VectorType is a UniformContainerType because it
/// represents a container of uniformly typed elements.
/// @brief AST Vector Type Node
class VectorType : public UniformContainerType
{
/// @name Constructors
/// @{
protected:
VectorType() : UniformContainerType(VectorTypeID), size(0) {}
virtual ~VectorType();
/// @}
/// @name Accessors
/// @{
public:
/// Get the maximum size the array can grow to.
uint64_t getSize() const { return size; }
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const VectorType*) { return true; }
static inline bool classof(const Node* T) { return T->is(VectorTypeID); }
/// @}
/// @name Mutators
/// @{
public:
/// Set the size of the vector.
void setSize(uint64_t max) { size = max; }
/// @}
/// @name Data
/// @{
protected:
uint64_t size; ///< The (fixed) size of the vector
/// @}
friend class AST;
};
/// This typedef is used to associate a name with a type. Although types have
/// names, this provides another name such as used in the fields of a structure
/// or the formal parameters of a function.
/// @see Type
/// @see StructureType
/// @see SignatureType
/// @see DisparateContainerType
/// @brief A Named Type
class NamedType : public Documentable
{
/// @name Constructors
/// @{
protected:
NamedType() : Documentable(NamedTypeID), name(), type(0) {}
virtual ~NamedType();
/// @}
/// @name Accessors
/// @{
public:
/// Get the maximum size the array can grow to.
const std::string& getName() const { return name; }
bool hasName() const { return !name.empty(); }
const Type* getType() const { return type; }
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const NamedType*) { return true; }
static inline bool classof(const Node* T) { return T->is(NamedTypeID); }
/// @}
/// @name Mutators
/// @{
public:
/// Set the size of the vector.
void setName(const std::string& N) { name = N; }
void setType(const Type* Ty) { type = Ty; }
void resolveTypeTo(const Type* from, const Type* to);
/// @}
/// @name Data
/// @{
protected:
std::string name;
const Type* type;
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a Type that
/// contains elements of potentially disparate other types.
/// @see ContinuationType
/// @see StructureType
/// @see SignatureType
/// @brief AST Abstract Disparate Container Type Node
class DisparateContainerType : public Type
{
/// @name Types
/// @{
public:
typedef std::vector<NamedType*> ContentsList;
typedef ContentsList::iterator iterator;
typedef ContentsList::const_iterator const_iterator;
/// @}
/// @name Constructors
/// @{
protected:
DisparateContainerType(NodeIDs id) : Type(id), contents() {}
virtual ~DisparateContainerType();
/// @}
/// @name Accessors
/// @{
public:
virtual const char* getPrimitiveName() const;
const NamedType* getField(unsigned index) const { return contents[index]; }
/// Return the index of a named field starting at 1. If the field is not
/// found, returns 0.
unsigned getFieldIndex(const std::string& fldname) const;
const Type* getFieldType(const std::string& fldname) const;
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const DisparateContainerType*) { return true; }
static inline bool classof(const Node* N) {
return N->isDisparateContainerType(); }
/// @}
/// @name Mutators
/// @{
public:
virtual void resolveTypeTo(const Type* from, const Type* to);
void setTypes(const std::vector<NamedType*>& Types) { contents = Types; }
void addType(NamedType* NT )
{ contents.push_back(NT); }
/// @}
/// @name Iterators
/// @{
public:
iterator begin() { return contents.begin(); }
const_iterator begin() const { return contents.begin(); }
iterator end () { return contents.end(); }
const_iterator end () const { return contents.end(); }
size_t size () const { return contents.size(); }
bool empty() const { return contents.empty(); }
NamedType* front() { return contents.front(); }
const NamedType* front() const { return contents.front(); }
NamedType* back() { return contents.back(); }
const NamedType* back() const { return contents.back(); }
/// @}
/// @name Data
/// @{
private:
ContentsList contents; ///< The contained types
/// @}
};
/// A convenience typedef so we can call NamedTypes as "Fields"
typedef NamedType Field;
/// This class provides an Abstract Syntax Tree node that represents an
/// sequence type. A sequence type is a type that lays out its elements in
/// sequential memory locations. Unlike ArrayType, SequenceType allows its
/// elements to be of disparate type. Consequently, StructureType is a
/// DisparateContainerType.
/// @brief AST Structure Type Node
class StructureType : public DisparateContainerType
{
/// @name Constructors
/// @{
protected:
StructureType(NodeIDs id = StructureTypeID ) : DisparateContainerType(id) {}
virtual ~StructureType();
/// @}
/// @name Accessors
/// @{
public:
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const StructureType*) { return true; }
static inline bool classof(const Node* T)
{ return T->is(StructureTypeID); }
/// @}
/// @name Mutators
/// @{
public:
void setFields(const std::vector<Field*>& fields) { setTypes(fields); }
void addField(Field* Fld ) { addType(Fld); }
/// @}
/// @name Data
/// @{
protected:
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents data held
/// for a continuation. A ContinutationType is a StructureType because it has
/// the same semantics as a structure. It allows the programmer to store various
/// bits of information that are to be restored at a later time, when the
/// continuation is called. In addition, HLVM will (transparently) associate
/// the runtime context for the continutation with the programmer's
/// ContinuationType.
/// @brief AST Continuation Type Node
class ContinuationType : public StructureType
{
/// @name Constructors
/// @{
protected:
ContinuationType() : StructureType(ContinuationTypeID) {}
virtual ~ContinuationType();
/// @}
/// @name Accessors
/// @{
public:
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const ContinuationType*) { return true; }
static inline bool classof(const Node* T)
{ return T->is(ContinuationTypeID); }
/// @}
friend class AST;
};
/// A convenience typedef so we can call NamedTypes as Parameters
typedef NamedType Parameter;
/// This class provides an Abstract Syntax Tree node that represents the call
/// signature of an HLVM function. A SignatureType encapsulates the
/// of varying type.
/// @see Function
/// @brief AST Signature Type Node
class SignatureType : public DisparateContainerType
{
/// @name Constructors
/// @{
protected:
SignatureType()
: DisparateContainerType(SignatureTypeID), result(0) {}
virtual ~SignatureType();
/// @}
/// @name Accessors
/// @{
public:
const Type* getResultType() const { return result; }
bool isVarArgs() const { return flags & IsVarArgsTF; }
/// Methods to support type inquiry via is, cast, dyn_cast
static inline bool classof(const SignatureType*) { return true; }
static inline bool classof(const Node* T)
{ return T->is(SignatureTypeID); }
/// @}
/// @name Mutators
/// @{
public:
void setResultType(const Type* ty) { result = ty; }
void setIsVarArgs(bool is) {
if (is) flags |= IsVarArgsTF; else flags &= ~IsVarArgsTF; }
void setParameters(const std::vector<Parameter*>& param) { setTypes(param);}
void addParameter(Parameter* param) { addType(param); }
virtual void resolveTypeTo(const Type* from, const Type* to);
/// @}
/// @name Data
/// @{
protected:
const Type* result; ///< The result type of the function signature
/// @}
friend class AST;
};
} // hlvm
#endif