blob: c64db41c15845fa6e42723a55aba32597c37131b [file] [log] [blame]
//===-- AST Control Flow Operators ------------------------------*- 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/ControlFlow.h
/// @author Reid Spencer <rspencer@reidspencer.com> (original author)
/// @date 2006/05/25
/// @since 0.1.0
/// @brief Declares the AST Control flow classes (Loop, If, Call, Return, etc.)
//===----------------------------------------------------------------------===//
#ifndef HLVM_AST_CONTROLFLOW_H
#define HLVM_AST_CONTROLFLOW_H
#include <hlvm/AST/Operator.h>
namespace hlvm
{
/// This class provides an Abstract Syntax Tree node that represents a select
/// operator. The select operator is a ternary operator that evaluates its first
/// operand as a boolean. If the result is true, the second operand is evaluated
/// and its result is the result of the select operator. If the result of the
/// first operand is false, the third operand is evaluated and its result is the
/// result of the select operator. This is similar to the ternary operator in
/// other languages, such as ?: in C. It also fulfills the purpose of an "if"
/// statement except it is more generalized because the operator has a result
/// value whereas most "if" statements do not. The second and third operands
/// can be any type but they must both be the same type. If the second and
/// third operands are blocks, and neither contains a result operator, the
/// result of those blocks has type "void" and consequently so does the result
/// of the select operator.
/// @brief AST Select Operator Node
class SelectOp : public TernaryOperator
{
/// @name Constructors
/// @{
protected:
SelectOp() : TernaryOperator(SelectOpID) {}
virtual ~SelectOp();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const SelectOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(SelectOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a switch
/// statement. THis is one of the more complicated operators in HLVM. The switch
/// operator can have an unlimited number of operands. Its first operand is an
/// expression to evaluate of any simple or primary type. This is the control
/// expression. The remaining operands must be in pairs. The first operand of
/// the pair is an operator to match agains the control expression. The second
/// operand of the pair is an operator to execute if the first operand of the
/// pair matched. This is very analagous to a switch statement in other
/// languages except that it has fewer restrictions. It is not limited to
/// integer types, but only to those types with a collation order. Its "case
/// statements" are not limited to constant values but can be full expressions
/// or even blocks of operators. Of course, constant values will execute faster.
/// @brief AST Switch Operator Node
class SwitchOp : public MultiOperator
{
/// @name Constructors
/// @{
protected:
SwitchOp() : MultiOperator(SwitchOpID) {}
virtual ~SwitchOp();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const SwitchOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(SwitchOpID); }
/// @}
friend class AST;
};
/// This class prvoides an Abstract Syntax Tree node that represents a loop
/// construct with two operands. The first operand is a boolean expression
/// that is tested before each iteration. If the expression evaluates to false,
/// the loop terminates. The second operand is the expression or block to be
/// executed on each iteration. This is similar to a "while" loop in other
/// languages, hence the name. If the second operand declares a result, then
/// the value of that result on the final iteration is the value of the loop.
/// Otherwise the WhileOp may not be used as a value (has type void).
/// @brief AST While Loop Operator Node
class WhileOp : public BinaryOperator
{
/// @name Constructors
/// @{
protected:
WhileOp() : BinaryOperator(WhileOpID) {}
virtual ~WhileOp();
/// @}
/// @name Accessors
/// @{
public:
virtual const Type* getType() const;
static inline bool classof(const WhileOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(WhileOpID); }
/// @}
friend class AST;
};
/// This class prvoides an Abstract Syntax Tree node that represents a loop
/// construct with two operands. The first operand is a boolean expression
/// that is tested before each iteration. If the expression evaluates to true,
/// the loop terminates. The second operand is the expression or block to be
/// executed on each iteration. This is similar to a "while" loop in other
/// languages, except the logic of the control expression is inverted. If the
/// second operand declares a result, then the value of that result on the
/// final iteration is the value of the loop. Otherwise the UnlessOp may
/// not be used as a value (has type void).
/// @brief AST Unless Loop Operator Node
class UnlessOp : public BinaryOperator
{
/// @name Constructors
/// @{
protected:
UnlessOp() : BinaryOperator(UnlessOpID) {}
virtual ~UnlessOp();
/// @}
/// @name Accessors
/// @{
public:
virtual const Type* getType() const;
static inline bool classof(const UnlessOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(UnlessOpID); }
/// @}
friend class AST;
};
/// This class prvoides an Abstract Syntax Tree node that represents a loop
/// construct with two operands. The second operand is a boolean expression
/// that is tested after each iteration. If the expression evaluates to true,
/// the loop terminates. The first operand is the expression or block to be
/// executed on each iteration. This is similar to a "do" loop in other
/// languages. If the first operand declares a result, then the value of that
/// result on the final iteration is the value of the loop. Otherwise the
/// UntilOp may not be used as a value (has type void).
/// @brief AST Unless Loop Operator Node
class UntilOp : public BinaryOperator
{
/// @name Constructors
/// @{
protected:
UntilOp() : BinaryOperator(UntilOpID) {}
virtual ~UntilOp();
/// @}
/// @name Accessors
/// @{
public:
virtual const Type* getType() const;
static inline bool classof(const UntilOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(UntilOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a
/// generalized loop construct for HLVM. The LoopOp takes three operands, as
/// follows:
/// -# a boolean expression to be evaluated before each iteration begins that
/// controls loop termination
/// -# an operator (typically a block) to be evaluated on each iteration of the
/// loop. This is the main body of the loop
/// -# a boolean expression to be evaluated after each iteration ends that
/// controls loop termination
/// This construct is similar to combining a WhileOp with an UntilOp.
/// @brief AST Loop Operator Node
class LoopOp : public TernaryOperator
{
/// @name Constructors
/// @{
protected:
LoopOp() : TernaryOperator(LoopOpID) {}
virtual ~LoopOp();
/// @}
/// @name Accessors
/// @{
public:
virtual const Type* getType() const;
static inline bool classof(const LoopOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(LoopOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a return
/// operator. The return operator returns from the function that contains it.
/// The ReturnOp takes one operand which is the value to return to the caller
/// of the Function.
/// @brief AST Return Operator Node
class ReturnOp : public NilaryOperator
{
/// @name Constructors
/// @{
protected:
ReturnOp() : NilaryOperator(ReturnOpID) {}
virtual ~ReturnOp();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const ReturnOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(ReturnOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a break
/// operator. A BreakOp causes control to flow to the operator immediately
/// following the enclosing block. The enclosing block can be any kind of block.
/// If a BreakOp occurs in the main block of a function, it is equivalent to
/// returning void from that function. If the function doesn't return void, it
/// is an error.
/// @brief AST Break Operator Node
class BreakOp : public NilaryOperator
{
/// @name Constructors
/// @{
protected:
BreakOp() : NilaryOperator(BreakOpID) {}
virtual ~BreakOp();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const BreakOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(BreakOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a continue
/// operator. A ContinueOp causes control to flow back to the start of the
/// the enclosing block. The enclosing block is not required to be a loop. If
/// the enclosing block is a loop, continuation first evaluates any exit
/// criteria, then evaluates any entry criteria, and finally re-enters the body
/// of the loop. This ensures that loop termination conditions are checked
/// before continuing.
/// @brief AST Continue Operator Node
class ContinueOp : public NilaryOperator
{
/// @name Constructors
/// @{
public:
static ContinueOp* create();
protected:
ContinueOp() : NilaryOperator(ContinueOpID) {}
virtual ~ContinueOp();
/// @}
/// @name Accessors
/// @{
public:
static inline bool classof(const ContinueOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(ContinueOpID); }
/// @}
friend class AST;
};
/// This class provides an Abstract Syntax Tree node that represents a function
/// call operator. A CallOp invokes a function, possibly passing it arguments,
/// and obtains the result of that function. The value of the CallOp becomes the
/// result of the called function.
/// @brief AST Call Operator Node
class CallOp : public MultiOperator
{
/// @name Constructors
/// @{
public:
static CallOp* create();
protected:
CallOp() : MultiOperator(CallOpID) {}
virtual ~CallOp();
/// @}
/// @name Accessors
/// @{
public:
/// Returns the type of the value of the call. This is the same as the
/// result type of the function's signature.
const Type* getType() const;
Function* getCalledFunction() const;
static inline bool classof(const CallOp*) { return true; }
static inline bool classof(const Node* N) { return N->is(CallOpID); }
/// @}
friend class AST;
};
} // end hlvm namespace
#endif