blob: c8e3340e8c435e2eb6fa692e72b7f73a3c8ee5cc [file] [log] [blame]
//===-- Abstract Node Class Interface ---------------------------*- 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/Node.h
/// @author Reid Spencer <rspencer@reidspencer.com> (original author)
/// @date 2006/05/04
/// @since 0.1.0
/// @brief Declares the class hlvm::AST::Node and basic subclasses
//===----------------------------------------------------------------------===//
#ifndef HLVM_AST_NODE_H
#define HLVM_AST_NODE_H
#include <llvm/Support/Casting.h>
#include <hlvm/AST/Locator.h>
#include <vector>
namespace hlvm
{
class Type;
class AST;
class Bundle;
/// This enumeration is used to identify the various kinds of Abstract Syntax
/// Tre nodes. Its organization is very specific and dependent on the class
/// hierarchy. In order to use these values as ranges for class identification
/// (classof methods), we need to group things by inheritance rather than by
/// function. Items beginning with "First" or "Last" identify a useful range
/// of node types and do not introduce any value of their own.
/// @brief Identifiers of th AST Node Types.
enum NodeIDs
{
NoNodeID = 0, ///< Use this for an invalid node ID.
// SUBCLASSES OF NODE
TreeTopID, ///< The AST node which is always root of the tree
FirstNodeID = TreeTopID,
DocumentationID, ///< XHTML Documentation Node
NamedTypeID, ///< An association of a name with a type
FirstDocumentableID = NamedTypeID,
BundleID, ///< The Bundle Node (a group of other declarations)
ImportID, ///< A bundle's Import declaration
// SUBCLASSES OF TYPE
// Basic Types
AnyTypeID, ///< The Any Type (Union of any type)
FirstTypeID = AnyTypeID,
BooleanTypeID, ///< The Boolean Type (A simple on/off boolean value)
CharacterTypeID, ///< The Character Type (UTF-8 encoded character)
EnumerationTypeID, ///< The Enumeration Type (set of enumerated ids)
IntegerTypeID, ///< The Integer Type (A # of bits of integer data)
OpaqueTypeID, ///< A placeholder for unresolved types
RangeTypeID, ///< The Range Type (A Range of Integer Values)
RealTypeID, ///< The Real Number Type (Any Real Number)
RationalTypeID, ///< The Rational Number Type (p/q type number)
StringTypeID, ///< A string of characters type
// Uniform Container Types
PointerTypeID, ///< The Pointer Type (Pointer To object of Type)
FirstContainerTypeID = PointerTypeID,
FirstUniformContainerTypeID = PointerTypeID,
ArrayTypeID, ///< The Array Type (Linear array of some type)
VectorTypeID, ///< The Vector Type (Packed Fixed Size Vector)
LastUniformContainerTypeID = VectorTypeID,
// Disparate Container Types
StructureTypeID, ///< The Structure Type (Sequence of various types)
FirstDisparateContainerTypeID = StructureTypeID,
SignatureTypeID, ///< The Function Signature Type
ContinuationTypeID, ///< A Continuation Type (data to continuations)
LastDisparateContainerTypeID = ContinuationTypeID,
LastContainerTypeID = ContinuationTypeID,
// Runtime Types
BufferTypeID, ///< A buffer of octets for I/O
FirstRuntimeTypeID = BufferTypeID,
StreamTypeID, ///< A stream handle
TextTypeID, ///< A UTF-8 or UTF-16 encoded text string
LastRuntimeTypeID = TextTypeID,
LastTypeID = TextTypeID,
// Class Constructs (TBD)
InterfaceID, ///< The Interface Type (set of Signatures)
ClassID, ///< The Class Type (OO Class Definition)
MethodID, ///< The Method Node (define a method)
ImplementsID, ///< Specifies set of Interfaces implemented by class
// SUBCLASSES OF VALUE
ArgumentID, ///< An argument to a function
FirstValueID = ArgumentID,
// Constants
ConstantAnyID, ///< A constant any value
FirstConstantID = ConstantAnyID,
FirstConstantValueID = ConstantAnyID,
ConstantBooleanID, ///< A constant boolean value
ConstantCharacterID, ///< A constant UTF-8 character value
ConstantEnumeratorID, ///< A constant enumeration value
ConstantIntegerID, ///< A constant integer value
ConstantRealID, ///< A constant real value
ConstantStringID, ///< A constant string value
ConstantPointerID, ///< A constant pointer value
ConstantArrayID, ///< A constant array value
FirstConstantAggregateID = ConstantArrayID,
ConstantVectorID, ///< A constant vector value
ConstantStructureID, ///< A constant structure value
ConstantContinuationID, ///< A constant continuation value
LastConstantAggregateID = ConstantContinuationID,
ConstantExpressionID, ///< A constant expression
LastConstantValueID = ConstantExpressionID,
// Linkage Items
VariableID, ///< The Variable Node (a storage location)
FirstLinkableID = VariableID,
FunctionID, ///< The Function Node (a callable function)
ProgramID, ///< The Program Node (a program starting point)
LastLinkableID = ProgramID,
LastConstantID = ProgramID,
// Operator
BlockID, ///< A Block Of Operators
FirstOperatorID = BlockID,
// Nilary Operators (those taking no operands)
BreakOpID, ///< Break out of the enclosing block
FirstNilaryOperatorID = BreakOpID,
ContinueOpID, ///< Continue from start of enclosing loop
ReturnOpID, ///< Return to the function's caller
GetOpID, ///< Obtain value of Variable/Function/Constant
LastNilaryOperatorID = GetOpID,
// Control Flow Unary Operators
ResultOpID, ///< Specify the result of a block or function
FirstUnaryOperatorID = ResultOpID,
ThrowOpID, ///< Throw an exception out of the function
// Integer Arithmetic Unary Operators
NotOpID, ///< Not Unary Boolean Operator
NegateOpID, ///< Negation Unary Integer Operator
ComplementOpID, ///< Bitwise Complement Unary Integer Operator
PreIncrOpID, ///< Pre-Increment Unary Integer Operator
PostIncrOpID, ///< Post-Increment Unary Integer Operator
PreDecrOpID, ///< Pre-Decrement Unary Integer Operator
PostDecrOpID, ///< Post-Decrement Unary Integer Operator
SizeOfOpID, ///< Size of a constant
ConvertOpID, ///< Convert one type to another
// Real Arithmetic Unary Operators
IsPInfOpID, ///< Real Number Positive Infinity Test Operator
IsNInfOpID, ///< Real Number Negative Infinity Test Operator
IsNanOpID, ///< Real Number Not-A-Number Test Operator
TruncOpID, ///< Real Number Truncation Operator
RoundOpID, ///< Real Number Rounding Operator
FloorOpID, ///< Real Number Floor Operator
CeilingOpID, ///< Real Number Ceiling Operator
LogEOpID, ///< Real Number Base e (Euler's Number) logarithm
Log2OpID, ///< Real Number Base 2 logarithm Operator
Log10OpID, ///< Real Number Base 10 logarithm Operator
SquareRootOpID, ///< Real Number Square Root Operator
CubeRootOpID, ///< Real Number Cube Root Operator
FactorialOpID, ///< Real Number Factorial Operator
// Memory Unary Operators
LoadOpID, ///< The Load Operator (load a value from a location)
AllocateOpID, ///< The Allocate Memory Operator
DeallocateOpID, ///< The Deallocate Memory Operator
AutoVarOpID, ///< Declaration of an automatic (stack) variable
// Input/Output Unary Operators
TellOpID, ///< Tell the position of a stream
CloseOpID, ///< Close a stream previously opened.
// Other Unary Operators
LengthOpID, ///< Extract Length of a Text/Array/Vector
LastUnaryOperatorID = LengthOpID,
// Arithmetic Binary Operators
AddOpID, ///< Addition Binary Operator
FirstBinaryOperatorID = AddOpID,
SubtractOpID, ///< Subtraction Binary Operator
MultiplyOpID, ///< Multiplcation Binary Operator
DivideOpID, ///< Division Binary Operator
ModuloOpID, ///< Modulus Binary Operator
BAndOpID, ///< Bitwise And Binary Operator
BOrOpID, ///< Bitwise Or Binary Operator
BXorOpID, ///< Bitwise XOr Binary Operator
BNorOpID, ///< Bitwise Nor Binary Operator
// Boolean Binary Operators
AndOpID, ///< And Binary Boolean Operator
OrOpID, ///< Or Binary Boolean Operator
NorOpID, ///< Nor Binary Boolean Operator
XorOpID, ///< Xor Binary Boolean Operator
LessThanOpID, ///< < Binary Comparison Operator
GreaterThanOpID, ///< > Binary Comparison Operator
LessEqualOpID, ///< <= Binary Comparison Operator
GreaterEqualOpID, ///< >= Binary Comparison Operator
EqualityOpID, ///< == Binary Comparison Operator
InequalityOpID, ///< != Binary Comparison Operator
// Real Arithmetic Binary Operators
PowerOpID, ///< Real Number Power Operator
RootOpID, ///< Real Number Arbitrary Root Operator
GCDOpID, ///< Real Number Greatest Common Divisor Operator
LCMOpID, ///< Real Number Least Common Multiplicator Operator
// Memory Binary Operators
ReallocateOpID, ///< The Reallocate Memory Operator
StoreOpID, ///< The Store Operator (store a value to a location)
GetIndexOpID, ///< The GetIndex Operator for indexing an array
GetFieldOpID, ///< The GetField Operator for indexing an structure
// Binary Control Flow Operators
WhileOpID, ///< While expression is true loop
UnlessOpID, ///< Unless expression is true loop
UntilOpID, ///< Do block until expression is true loop
// Other Binary Operators
OpenOpID, ///< Open a stream from a URL
ReadOpID, ///< Read from a stream
WriteOpID, ///< Write to a stream
CreateContOpID, ///< The Create Continutation Operator
LastBinaryOperatorID = CreateContOpID,
// Ternary Operators
SelectOpID, ///< The select an alternate operator
FirstTernaryOperatorID = SelectOpID,
StrInsertOpID, ///< Insert(str1,where,str2)
StrEraseOpID, ///< Erase(str,at,len)
StrReplaceOpID, ///< Replace(str,at,len,what)
StrConcatOpID, ///< str3 = Concat(str1,str2)
PositionOpID, ///< Position a stream (stream,where,relative-to)
LoopOpID, ///< The General Purpose Loop Operator
LastTernaryOperatorID = LoopOpID,
// Multi Operators
CallOpID, ///< The Call Operator (n operands)
FirstMultiOperatorID = CallOpID,
InvokeOpID, ///< The Invoke Operator (n operands)
DispatchOpID, ///< The Object Method Dispatch Operator (n operands)
CallWithContOpID, ///< The Call with Continuation Operator (n operands)
SwitchOpID, ///< The Switch Operator (n operands)
LastMultiOperatorID = SwitchOpID,
LastOperatorID = SwitchOpID,
LastValueID = SwitchOpID,
LastDocumentableID = SwitchOpID,
LastNodeID = SwitchOpID,
NumNodeIDs ///< The number of node identifiers in the enum
};
/// This class is the abstract base class of all the Abstract Syntax Tree (AST)
/// node types. All other AST nodes are subclasses of this class. This class
/// must only provide functionality that is common to all AST Node subclasses.
/// It provides for class identification, insertion of nodes, management of a
/// set of flags,
/// @brief Abstract Base Class of All HLVM AST Nodes
class Node
{
/// @name Constructors
/// @{
protected:
Node(NodeIDs ID) : id(ID), flags(0), parent(0), loc(0) {}
public:
virtual ~Node();
/// @}
/// @name Accessors
/// @{
public:
/// Get the AST root node that this Node is part of.
AST* getRoot();
/// Return the bundle that contains this Node.
Bundle* getContainingBundle() const;
/// Get the type of node
NodeIDs getID() const { return NodeIDs(id); }
/// Get the parent node
Node* getParent() const { return parent; }
/// Get the flags
unsigned getFlags() const { return flags; }
/// Get the Locator
const Locator* getLocator() const { return loc; }
/// Determine if the node is a specific kind
bool is(NodeIDs kind) const { return id == unsigned(kind); }
/// Determine if the node is a Type
bool isType() const {
return id >= FirstTypeID &&
id <= LastTypeID; }
bool isIntegralType() const {
return (id == IntegerTypeID) || (id == RangeTypeID) ||
(id == EnumerationTypeID) || (id == BooleanTypeID) ||
(id == CharacterTypeID); }
bool isNumericType() const {
return isIntegralType() || id == RealTypeID; }
/// Determine if the node is a uniform container type
bool isUniformContainerType() const {
return id >= FirstUniformContainerTypeID &&
id <= LastUniformContainerTypeID;
}
/// Determine if the node is a disparate container type
bool isDisparateContainerType() const {
return id >= FirstDisparateContainerTypeID &&
id <= LastDisparateContainerTypeID; }
/// Determine if the node is a runtime type
bool isRuntimeType() const {
return id >= FirstRuntimeTypeID &&
id <= LastRuntimeTypeID; }
/// Determine if the node is a container type
bool isContainerType() const {
return id >= FirstContainerTypeID && id <= LastContainerTypeID;
}
/// Determine if the node is one of the Constant values.
bool isConstant() const {
return id >= FirstConstantID && id <= LastConstantID; }
/// Determine if the node is one of the Constant values.
bool isConstantValue() const {
return id >= FirstConstantValueID && id <= LastConstantValueID; }
/// Determine if the node is one of the ConstantAggregate values.
bool isConstantAggregate() const {
return id >= FirstConstantAggregateID && id <= LastConstantAggregateID; }
/// Determine if the node is a Linkable
bool isLinkable() const {
return id >= FirstLinkableID && id <= LastLinkableID; }
/// Determine if the node is any of the Operators
bool isOperator() const {
return id >= FirstOperatorID && id <= LastOperatorID; }
bool isTerminator() const {
return (id >= BreakOpID && id <= ReturnOpID) || (id == ThrowOpID); }
bool isLoop() const {
return id == LoopOpID || (id >= WhileOpID && id <= UntilOpID); }
bool isNilaryOperator() const {
return id >= FirstNilaryOperatorID && id <= LastNilaryOperatorID; }
bool isUnaryOperator() const {
return id >= FirstUnaryOperatorID && id <= LastUnaryOperatorID; }
bool isBinaryOperator() const {
return id >= FirstBinaryOperatorID && id <= LastBinaryOperatorID; }
bool isTernaryOperator() const {
return id >= FirstTernaryOperatorID && id <= LastTernaryOperatorID; }
bool isMultiOperator() const {
return id >= FirstMultiOperatorID && id <= LastMultiOperatorID; }
/// Determine if the node is a Documentable Node
bool isDocumentable() const {
return id >= FirstDocumentableID && id <= LastDocumentableID; }
/// Determine if the node is a Value
bool isValue() const {
return id >= FirstValueID && id <= LastValueID; }
bool isFunction() const
{ return id == FunctionID || id == ProgramID; }
/// Provide support for isa<X> and friends
static inline bool classof(const Node*) { return true; }
/// @}
/// @name Mutators
/// @{
public:
void setLocator(const Locator* l) { loc = l; }
void setFlags(uint16_t f) { flags = f; }
virtual void setParent(Node* parent);
protected:
virtual void insertChild(Node* child);
virtual void removeChild(Node* child);
/// @}
/// @name Data
/// @{
protected:
uint16_t id; ///< Really a value in NodeIDs
uint16_t flags; ///< 16 flags, subclass dependent interpretation
Node* parent; ///< The node that owns this node.
const Locator* loc; ///< The source location corresponding to node.
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents program
/// documentation. Documentation nodes may be attached to any Documentable which
/// is an abstract base class of nearly every type of AST node. This construct
/// permits documentation (not just comments) to be included directly into the
/// nodes of the Abstract Syntax Tree as first class objects, not just addenda.
/// Each Documentation node simply contains a block of text that provides the
/// documentation for the Documentable to which the Documentation is attached.
/// The intended use is that the text contain XHTML markup. In this way, an
/// automated documentation facility can translate the AST into XHTML
/// documentation with great accuracy in associating documentation with the
/// nodes of the AST. Since the documentation node can be associated with
/// nearly any kind of node, this affords a complete system for documenting
/// HLVM programs with XHTML markup. There is, however, no firm requirement
/// that XHTML be used for the documentation. Any kind of documentation that is
/// expressible in UTF-8 notation can be accommodated including other markup
/// languages or simple ASCII text.
/// @see Documentable
/// @brief AST Documentation Node
class Documentation : public Node
{
/// @name Constructors
/// @{
protected:
Documentation() : Node(DocumentationID) {}
virtual ~Documentation();
/// @}
/// @name Accessors
/// @{
public:
const std::string& getDoc() const { return doc; }
static inline bool classof(const Documentation*) { return true; }
static inline bool classof(const Node* N)
{ return N->is(DocumentationID); }
/// @}
/// @name Mutators
/// @{
public:
void setDoc(const std::string& d) { doc = d; }
void addDoc(const std::string& d) { doc += d; }
/// @}
/// @name Data
/// @{
protected:
std::string doc;
/// @}
friend class AST;
};
/// This class is an abstract base class in the Abstract Syntax Tree for any
/// node type that can be documented. That is, it provides a facility for
/// attaching a Documentation node. This is the base class of most definitions
/// in the AST.
/// @see Documentation
/// @brief AST Documentable Node
class Documentable : public Node
{
/// @name Constructors
/// @{
protected:
Documentable(NodeIDs id) : Node(id), doc(0) {}
public:
virtual ~Documentable();
/// @}
/// @name Accessors
/// @{
public:
/// Get the name of the node
inline Documentation* getDoc() const {
return const_cast<Documentation*>(doc); }
static inline bool classof(const Documentable*) { return true; }
static inline bool classof(const Node* N) { return N->isDocumentable(); }
/// @}
/// @name Mutators
/// @{
public:
void setDoc(Documentation* d) { doc = d; }
/// @}
/// @name Data
/// @{
protected:
Documentation* doc;///< All named nodes can have documentation
/// @}
friend class AST;
};
/// This class is an abstract base class in the Abstract Syntax Tree for things
/// that have a value at runtime. Every Value has a Type. All Operators, and
/// Linkables are Values.
/// @see Type
/// @see Linkable
/// @see Operator
/// @brief AST Value Node
class Value : public Documentable
{
/// @name Constructors
/// @{
protected:
Value(NodeIDs id) : Documentable(id), type(0) {}
public:
virtual ~Value();
/// @}
/// @name Accessors
/// @{
public:
// Get the type of the value
virtual const Type* getType() const { return type; }
template<class C>
bool typeis() const { return llvm::isa<C>(type); }
const Type* getConcreteType() const;
static inline bool classof(const Value*) { return true; }
static inline bool classof(const Node* N) { return N->isValue(); }
/// @}
/// @name Mutators
/// @{
public:
void setType(const Type* t) { type = t; }
virtual void resolveTypeTo(const Type* from, const Type* to);
/// @}
/// @name Data
/// @{
protected:
const Type* type; ///< The type of this value.
/// @}
friend class AST;
};
} // end hlvm namespace
#endif