// CPPExpr.h: Expression support classes
#ifndef INCL_CPPEXPR_H
#define INCL_CPPEXPR_H
#ifdef _MSC_VER
#pragma warning (disable:4786) // long debug names
#pragma warning (disable:4146) // unary minus operator applied to unsigned type
#pragma warning (disable:4018) // '>' : signed/unsigned mismatch
#endif
#include "CPPExprIncomplete.h"
#include "CPPDeclIncomplete.h"
#include "CPPTypeIncomplete.h"
#include "CPPScopeIncomplete.h"
#include "tokens.h"
#include "JLStr.h"
#include "assert.h"
////////////////////////////////////////////////////////////////
// Base expression class.
////////////////////////////////////////////////////////////////
class CPPExpr : public VRefCount {
public:
enum Flavor {
Binary, // all binary ops except [], ()
Unary, // all prefix unary ops
Conditional, // conditional
Literal, // literal constant
SizeofExpr, // sizeof(expr)
SizeofType, // sizeof(type)
Id, // Id for which name lookup was unique
IdLazy, // Id with deferred name lookup
IdUndefined, // Id that could not be found (for templates)
Cast, // Cast expression
TemplatePlaceholder, // Template placeholder value
New, // new
Delete, // delete
FunctionCall, // f(args)
Postop, // postfix ++, --
This, // "this"
ArraySubscript // array[subscript]
};
CPPExpr(Flavor flavor_) : flavor(flavor_) {}
virtual ~CPPExpr() {}
Flavor GetFlavor() const { return flavor; }
// Evaluate the expression as a constant-expression
// Returns false if the expression is not constant
virtual bool EvaluateConstant(
double& result,
bool& resultIsInteger
) const { return false; }
virtual JLStr Format() const { return JLStr(); }
// Is this expression a template placeholder?
virtual bool IsPlaceholder() const { return false; }
// Get the type of the expression, or a nil ref if the type is invalid
// or cannot be determined.
virtual CPPTypeRefI GetType() {
// Type of expressions is undefined (nil) unless subclass overrides
return CPPTypeRefI();
}
protected:
// Data
Flavor flavor;
private:
// Do not allow copy/assignment.
CPPExpr(const CPPExpr& rhs);
CPPExpr& operator=(const CPPExpr& rhs);
};
////////////////////////////////////////////////////////////////
// Binary-operation expression class
////////////////////////////////////////////////////////////////
class CPPExprBinary : public CPPExpr {
public:
CPPExprBinary(
CPPExprRefI lhs_,
CPPExprRefI rhs_,
ANTLRTokenType opToken_
) :
CPPExpr(Binary),
lhs(lhs_),
rhs(rhs_),
opToken(opToken_)
{}
virtual ~CPPExprBinary() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual CPPTypeRefI GetType();
virtual JLStr Format() const;
CPPExprRefI GetLhs() const { assertValid(); return lhs; }
CPPExprRefI GetRhs() const { assertValid(); return rhs; }
ANTLRTokenType GetOpToken() const { assertValid(); return opToken; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Binary); }
CPPExprRef lhs;
CPPExprRef rhs;
ANTLRTokenType opToken;
};
////////////////////////////////////////////////////////////////
// Unary-operation expression class
////////////////////////////////////////////////////////////////
class CPPExprUnary : public CPPExpr {
public:
CPPExprUnary(
CPPExprRefI rhs_,
ANTLRTokenType opToken_
) :
CPPExpr(Unary),
rhs(rhs_),
opToken(opToken_)
{}
virtual ~CPPExprUnary() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
CPPExprRefI GetRhs() const { assertValid(); return rhs; }
ANTLRTokenType GetOpToken() const { assertValid(); return opToken; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Unary); }
CPPExprRef rhs;
ANTLRTokenType opToken;
};
////////////////////////////////////////////////////////////////
// Conditional expression class
////////////////////////////////////////////////////////////////
class CPPExprConditional : public CPPExpr {
public:
CPPExprConditional(
CPPExprRefI condition_,
CPPExprRefI lhs_,
CPPExprRefI rhs_
) :
CPPExpr(Conditional),
condition(condition_),
lhs(lhs_),
rhs(rhs_)
{}
virtual ~CPPExprConditional() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
CPPExprRefI GetCondition() const { assertValid(); return condition; }
CPPExprRefI GetLhs() const { assertValid(); return lhs; }
CPPExprRefI GetRhs() const { assertValid(); return rhs; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Conditional); }
CPPExprRef condition;
CPPExprRef lhs;
CPPExprRef rhs;
};
////////////////////////////////////////////////////////////////
// Literal expression class
////////////////////////////////////////////////////////////////
class CPPExprLiteral : public CPPExpr {
public:
CPPExprLiteral(
ANTLRTokenType tokType_,
const JLStr& tokText_
);
virtual ~CPPExprLiteral() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const { return tokText; }
ANTLRTokenType GetTokenType() const { assertValid(); return tokType; }
const JLStr& GetTokenText() const { assertValid(); return tokText; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Literal); }
ANTLRTokenType tokType;
JLStr tokText;
};
////////////////////////////////////////////////////////////////
// sizeof expression classes
////////////////////////////////////////////////////////////////
class CPPExprSizeofExpr : public CPPExpr {
public:
CPPExprSizeofExpr(
CPPExprRefI expr_
) :
CPPExpr(SizeofExpr),
expr(expr_)
{}
virtual ~CPPExprSizeofExpr() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
CPPExprRefI GetExpr() const { return expr; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == SizeofExpr); }
CPPExprRef expr;
};
class CPPExprSizeofType : public CPPExpr {
public:
CPPExprSizeofType(
CPPTypeRefI type_
) :
CPPExpr(SizeofType),
type(type_)
{}
virtual ~CPPExprSizeofType() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
CPPTypeRefI GetType() const { assertValid(); return type; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == SizeofType); }
CPPTypeRefI type;
};
////////////////////////////////////////////////////////////////
// id expression class
////////////////////////////////////////////////////////////////
class CPPExprId : public CPPExpr {
public:
CPPExprId(
CPPDeclRefI decl_
) :
CPPExpr(Id),
decl(decl_)
{}
virtual ~CPPExprId() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
virtual CPPTypeRefI GetType();
CPPDeclRefI GetDecl() const { assertValid(); return decl; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Id); }
CPPDeclRefI decl;
};
////////////////////////////////////////////////////////////////
// id expression class for identifiers that were multiply-defined
// at the time of name lookup. This allows deferral of the
// overload resolution
////////////////////////////////////////////////////////////////
class CPPExprIdLazy : public CPPExpr {
public:
CPPExprIdLazy(
const JLStr& name_,
CPPDeclListRefI& declList_
) :
name(name_),
CPPExpr(IdLazy),
declList(declList_)
{}
virtual ~CPPExprIdLazy() {}
virtual JLStr Format() const { return name; }
const JLStr& GetName() const { return name; }
const CPPDeclListRefI GetDecls() const { assertValid(); return declList; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == IdLazy); }
// Name of the declaration
JLStr name;
// List of all decls under that name
CPPDeclListRefI declList;
};
////////////////////////////////////////////////////////////////
// id expression class for identifiers that were not found
// in the scope context. Only applies to identifiers found
// in template declarations.
////////////////////////////////////////////////////////////////
class CPPExprIdUndefined : public CPPExpr {
public:
CPPExprIdUndefined(
const JLStr& name_
) :
CPPExpr(IdUndefined),
name(name_)
{}
virtual ~CPPExprIdUndefined() {}
virtual JLStr Format() const { return name; }
const JLStr& GetName() const { assertValid(); return name; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == IdUndefined); }
JLStr name;
};
////////////////////////////////////////////////////////////////
// id expression class
////////////////////////////////////////////////////////////////
class CPPExprCast : public CPPExpr {
public:
enum CastFlavor { Const, Static, Dynamic, Reinterpret, Traditional, FunctionLike };
CPPExprCast(
CastFlavor castFlavor_,
CPPTypeRefI type_,
CPPExprRefI rhs_
) :
CPPExpr(Cast),
castFlavor(castFlavor_),
type(type_),
rhs(rhs_)
{}
virtual ~CPPExprCast() {}
virtual bool EvaluateConstant(double& result, bool& resultIsInteger) const;
virtual JLStr Format() const;
virtual CPPTypeRefI GetType() { return type; }
CastFlavor GetCastFlavor() const { assertValid(); return castFlavor; }
CPPExprRefI GetRhs() const { assertValid(); return rhs; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Cast); }
CastFlavor castFlavor;
CPPTypeRefI type;
CPPExprRefI rhs;
};
////////////////////////////////////////////////////////////////
// template placeholder value class
////////////////////////////////////////////////////////////////
class CPPExprTemplatePlaceholder : public CPPExpr {
public:
CPPExprTemplatePlaceholder(
short parameterIdx_,
short templateLevel_
) :
CPPExpr(TemplatePlaceholder),
parameterIdx(parameterIdx_),
templateLevel(templateLevel_)
{}
virtual JLStr Format() const;
virtual bool IsPlaceholder() const { return true; }
short GetParameterIdx() const { assertValid(); return parameterIdx; }
short GetTemplateLevel() const { assertValid(); return templateLevel; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == TemplatePlaceholder); }
// The index of the parameter in its list (zero-based)
short parameterIdx;
// The level of template nesting of the parameter (zero-based)
short templateLevel;
};
////////////////////////////////////////////////////////////////
// new expression class
////////////////////////////////////////////////////////////////
class CPPExprNew : public CPPExpr {
public:
CPPExprNew(
CPPExprRefI placementExpr_,
CPPTypeRefI rawType_,
CPPTypeRefI arrayType_,
CPPExprRefI arraySizeExpr_,
CPPExprRefI initExpr_
) :
CPPExpr(New),
placementExpr(placementExpr_),
rawType(rawType_),
arrayType(arrayType_),
arraySizeExpr(arraySizeExpr_),
initExpr(initExpr_)
{
}
virtual JLStr Format() const;
virtual CPPTypeRefI GetType() { return arrayType; }
CPPExprRefI GetPlacementExpr() const { assertValid(); return placementExpr; }
CPPTypeRefI GetArrayType() const { assertValid(); return arrayType; }
CPPExprRefI GetArraySizeExpr() const { assertValid(); return arraySizeExpr; }
CPPExprRefI GetInitExpr() const { assertValid(); return initExpr; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == New); }
CPPExprRefI placementExpr; // placement expression if non-nul
CPPTypeRefI rawType; // type to allocate
CPPTypeRefI arrayType; // type of any resulting array
CPPExprRefI arraySizeExpr; // array size expression if non-nil
CPPExprRefI initExpr; // initializer if non-nil
};
////////////////////////////////////////////////////////////////
// delete expression class
////////////////////////////////////////////////////////////////
class CPPExprDelete : public CPPExpr {
public:
CPPExprDelete(
CPPExprRefI exprToDelete_,
bool deleteArray_
) :
CPPExpr(Delete),
exprToDelete(exprToDelete_),
deleteArray(deleteArray_)
{
}
virtual JLStr Format() const;
CPPExprRefI GetExprToDelete() const { assertValid(); return exprToDelete; }
bool GetDeleteArray() const { assertValid(); return deleteArray; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Delete); }
CPPExprRefI exprToDelete;
bool deleteArray;
};
////////////////////////////////////////////////////////////////
// function call expression class
////////////////////////////////////////////////////////////////
class CPPExprFunctionCall : public CPPExpr {
public:
CPPExprFunctionCall(
CPPExprRefI exprFunction_,
CPPExprRefI exprArgList_
) :
CPPExpr(FunctionCall),
exprFunction(exprFunction_),
exprArgList(exprArgList_)
{
}
virtual JLStr Format() const;
virtual CPPTypeRefI GetType();
CPPExprRefI GetExprFunction() const { assertValid(); return exprFunction; }
CPPExprRefI GetExprArgList() const { assertValid(); return exprArgList; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == FunctionCall); }
CPPExprRefI exprFunction;
CPPExprRefI exprArgList;
};
////////////////////////////////////////////////////////////////
// post-op expression
////////////////////////////////////////////////////////////////
class CPPExprPostop : public CPPExpr {
public:
CPPExprPostop(
CPPExprRefI lhs_,
ANTLRTokenType opToken_
) :
CPPExpr(Postop),
lhs(lhs_),
opToken(opToken_)
{
}
virtual JLStr Format() const;
CPPExprRefI GetLhs() const { assertValid(); return lhs; }
ANTLRTokenType GetOpToken() const { assertValid(); return opToken; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == Postop); }
CPPExprRefI lhs;
ANTLRTokenType opToken;
};
////////////////////////////////////////////////////////////////
// "this" expression
////////////////////////////////////////////////////////////////
class CPPExprThis : public CPPExpr {
public:
CPPExprThis() : CPPExpr(This) {}
virtual JLStr Format() const { return "this"; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == This); }
};
////////////////////////////////////////////////////////////////
// array-subscript expression
////////////////////////////////////////////////////////////////
class CPPExprArraySubscript : public CPPExpr {
public:
CPPExprArraySubscript(
CPPExprRefI lhs_,
CPPExprRefI exprSubscript_
) :
CPPExpr(ArraySubscript),
lhs(lhs_),
exprSubscript(exprSubscript_)
{}
virtual JLStr Format() const;
virtual CPPTypeRefI GetType();
CPPExprRefI GetLhs() const { assertValid(); return lhs; }
CPPExprRefI GetExprSubscript() const { assertValid(); return exprSubscript; }
private:
// Catch bad downcast
void assertValid() const { assert(flavor == ArraySubscript); }
CPPExprRefI lhs;
CPPExprRefI exprSubscript;
};
#endif