
#include "expression.h"


Expression::~Expression()
{
}


ArithmeticExpressionConstant::ArithmeticExpressionConstant(int value)
{
    this->value = value;
}
void ArithmeticExpressionConstant::dump(std::ostream& os, int depth)
{
    for(int i = 0; i < depth; i++)
        os << "    ";
    os << "ArithmeticExpressionConstant " << value << std::endl;
}
llvm::Value* ArithmeticExpressionConstant::translate(TranslationContext* ctx)
{
    return ctx->builder->getInt32(value);
}


BooleanExpressionNot::BooleanExpressionNot(BooleanExpression* expr)
{
    this->expr = expr;
}
BooleanExpressionNot::~BooleanExpressionNot()
{
    delete expr;
}
void BooleanExpressionNot::dump(std::ostream& os, int depth)
{
    for(int i = 0; i < depth; i++)
        os << "    ";
    os << "BooleanExpressionNot" << std::endl;
    expr->dump(os, depth+1);
}
llvm::Value* BooleanExpressionNot::translate(TranslationContext* ctx)
{
    llvm::Value* ev = expr->translate(ctx);
    return ctx->builder->CreateNot(ev, "foo");
}


LValueIdentifier::LValueIdentifier(std::string* identifier)
{
    this->identifier = identifier;
}
LValueIdentifier::~LValueIdentifier()
{
    delete identifier;
}
void LValueIdentifier::dump(std::ostream& os, int depth)
{
    for(int i = 0; i < depth; i++)
        os << "    ";
    os << "LValueIdentifier " << *identifier << std::endl;
}

llvm::Value* LValueIdentifier::translate(TranslationContext* ctx)
{
    SymbolTableEntry* entry = ctx->symboltable->lookup(*identifier);
    return ctx->builder->CreateLoad( entry->type, entry->ref, entry->name );
}

llvm::Value* LValueIdentifier::translateLValue(TranslationContext* ctx)
{
    SymbolTableEntry* entry = ctx->symboltable->lookup(*identifier);
    return entry->ref;
}




#define BINOP_DEF(C,B,LT,RT, LL) \
    C :: C(LT l, RT r) \
    : B() \
    { \
        this -> l = l; \
        this -> r = r; \
    } \
    C :: ~C() \
    { \
        delete l; \
        delete r; \
    } \
    void C :: dump(std::ostream& os, int depth) \
    { \
        for(int i = 0; i < depth; i++) \
            os << "    "; \
        os << #C << std::endl; \
        l->dump(os, depth+1); \
        r->dump(os, depth+1); \
    } \
    llvm::Value* C :: translate(TranslationContext* ctx) \
    { \
        llvm::Value* lv = l -> translate(ctx); \
        llvm::Value* rv = r -> translate(ctx); \
        return ctx -> builder -> LL (lv, rv, "foo"); \
    }

#define BOOLEXP_DEF(C, LL) \
    BINOP_DEF(C, BooleanExpression, BooleanExpression*, BooleanExpression*, LL)
BOOLEXP_DEF(BooleanExpressionAnd,          CreateAnd)
BOOLEXP_DEF(BooleanExpressionOr,           CreateOr)

#define RELEXP_DEF(C, LL) \
    BINOP_DEF(C, RelationExpression, ArithmeticExpression*, ArithmeticExpression*, LL)
RELEXP_DEF(RelationExpressionLess,         CreateICmpSLT)
RELEXP_DEF(RelationExpressionLessEqual,    CreateICmpSLE)
RELEXP_DEF(RelationExpressionEqual,        CreateICmpEQ)
RELEXP_DEF(RelationExpressionUnequal,      CreateICmpNE)
RELEXP_DEF(RelationExpressionGreaterEqual, CreateICmpSGE)
RELEXP_DEF(RelationExpressionGreater,      CreateICmpSGT)

#define ARITHEXP_DEF(C, LL) \
    BINOP_DEF(C, ArithmeticExpression, ArithmeticExpression*, ArithmeticExpression*, LL)
ARITHEXP_DEF(ArithmeticExpressionPlus,     CreateAdd)
ARITHEXP_DEF(ArithmeticExpressionMinus,    CreateSub)
ARITHEXP_DEF(ArithmeticExpressionMultiply, CreateMul)
ARITHEXP_DEF(ArithmeticExpressionDivide,   CreateSDiv)
ARITHEXP_DEF(ArithmeticExpressionModulus,  CreateSRem)
