2014-10-07 18:15:46 +00:00
|
|
|
#include "Expression.h"
|
2014-10-07 22:41:40 +00:00
|
|
|
#include "ResourceCompiler.h"
|
|
|
|
#include <cassert>
|
|
|
|
#include <iostream>
|
2014-10-12 17:16:02 +00:00
|
|
|
#include <fstream>
|
2014-10-30 01:56:49 +00:00
|
|
|
#include "Diagnostic.h"
|
2014-10-07 18:15:46 +00:00
|
|
|
|
2014-10-07 22:41:40 +00:00
|
|
|
int Expression::evaluateInt(ResourceCompiler *ctx)
|
2014-10-07 18:15:46 +00:00
|
|
|
{
|
2014-10-30 01:56:49 +00:00
|
|
|
error(ctx, "Expected an integer or integer expression here.");
|
|
|
|
return 0;
|
2014-10-07 18:15:46 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 23:17:39 +00:00
|
|
|
std::string Expression::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
2014-10-30 01:56:49 +00:00
|
|
|
error(ctx, "Expected a string or string expression here.");
|
|
|
|
return "";
|
2014-10-07 23:17:39 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 18:15:46 +00:00
|
|
|
Expression::~Expression()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-30 01:56:49 +00:00
|
|
|
void Expression::error(ResourceCompiler *ctx, std::string err)
|
|
|
|
{
|
|
|
|
ctx->problem(Diagnostic(Diagnostic::Severity::error, err, location));
|
|
|
|
}
|
|
|
|
|
2014-10-07 18:15:46 +00:00
|
|
|
|
|
|
|
StringExpr::~StringExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:17:39 +00:00
|
|
|
std::string StringExpr::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
2014-10-07 18:15:46 +00:00
|
|
|
|
|
|
|
IntExpr::~IntExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-07 22:41:40 +00:00
|
|
|
int IntExpr::evaluateInt(ResourceCompiler *ctx)
|
2014-10-07 18:15:46 +00:00
|
|
|
{
|
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CompoundExpr::addItem(ExprPtr item)
|
|
|
|
{
|
|
|
|
items.push_back(item);
|
|
|
|
}
|
|
|
|
|
|
|
|
CompoundExpr::~CompoundExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BinaryExpr::~BinaryExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-07 22:41:40 +00:00
|
|
|
int BinaryExpr::evaluateInt(ResourceCompiler *ctx)
|
2014-10-07 18:15:46 +00:00
|
|
|
{
|
|
|
|
switch(op)
|
|
|
|
{
|
|
|
|
case BinaryOp::XOR:
|
|
|
|
return a->evaluateInt(ctx) ^ b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::OR:
|
|
|
|
return a->evaluateInt(ctx) | b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::AND:
|
|
|
|
return a->evaluateInt(ctx) & b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::SHIFTLEFT:
|
|
|
|
return a->evaluateInt(ctx) << b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::SHIFTRIGHT:
|
|
|
|
return a->evaluateInt(ctx) >> b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::EQUAL:
|
|
|
|
return a->evaluateInt(ctx) == b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::NOTEQUAL:
|
|
|
|
return a->evaluateInt(ctx) != b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::PLUS:
|
|
|
|
return a->evaluateInt(ctx) + b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::MINUS:
|
|
|
|
return a->evaluateInt(ctx) - b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::MULTIPLY:
|
|
|
|
return a->evaluateInt(ctx) * b->evaluateInt(ctx);
|
|
|
|
case BinaryOp::DIVIDE:
|
|
|
|
return a->evaluateInt(ctx) / b->evaluateInt(ctx);
|
2014-10-12 17:16:02 +00:00
|
|
|
default:
|
2014-10-30 01:56:49 +00:00
|
|
|
error(ctx, "Expected an integer or integer expression here.");
|
|
|
|
return 0;
|
2014-10-12 17:16:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string BinaryExpr::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
switch(op)
|
|
|
|
{
|
|
|
|
case BinaryOp::CONCAT:
|
|
|
|
return a->evaluateString(ctx) + b->evaluateString(ctx);
|
|
|
|
default:
|
2014-10-30 01:56:49 +00:00
|
|
|
error(ctx, "Expected a string or string expression here.");
|
|
|
|
return "";
|
2014-10-07 18:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
UnaryExpr::~UnaryExpr()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-07 22:41:40 +00:00
|
|
|
int UnaryExpr::evaluateInt(ResourceCompiler *ctx)
|
2014-10-07 18:15:46 +00:00
|
|
|
{
|
|
|
|
switch(op)
|
|
|
|
{
|
|
|
|
case UnaryOp::MINUS:
|
|
|
|
return -a->evaluateInt(ctx);
|
|
|
|
case UnaryOp::COMPLEMENT:
|
|
|
|
return ~a->evaluateInt(ctx);
|
2014-10-28 23:45:10 +00:00
|
|
|
default:
|
2014-10-30 01:56:49 +00:00
|
|
|
error(ctx, "Expected an integer or integer expression here.");
|
|
|
|
return 0;
|
2014-10-07 18:15:46 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-07 22:41:40 +00:00
|
|
|
|
|
|
|
|
2014-10-30 01:56:49 +00:00
|
|
|
IdentifierExpr::IdentifierExpr(std::string id, yy::location loc)
|
|
|
|
: Expression(loc), id(id)
|
2014-10-07 22:41:40 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
void IdentifierExpr::addArgument(ExprPtr e)
|
|
|
|
{
|
|
|
|
arguments.push_back(e);
|
|
|
|
}
|
|
|
|
|
2014-10-07 23:55:54 +00:00
|
|
|
ExprPtr IdentifierExpr::lookup(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
Subscripts sub;
|
|
|
|
for(auto arg : arguments)
|
|
|
|
sub.addSubscript(arg->evaluateInt(ctx));
|
|
|
|
ExprPtr val = ctx->lookupIdentifier(id, sub);
|
2014-10-30 01:56:49 +00:00
|
|
|
if(!val)
|
|
|
|
error(ctx, "Identifier \"" + id + "\" is not defined.");
|
2014-10-07 23:55:54 +00:00
|
|
|
return val;
|
|
|
|
}
|
|
|
|
|
2014-10-07 22:41:40 +00:00
|
|
|
int IdentifierExpr::evaluateInt(ResourceCompiler *ctx)
|
|
|
|
{
|
2014-10-13 22:11:21 +00:00
|
|
|
if(ctx->isPrePass())
|
|
|
|
return 0;
|
2014-10-30 01:56:49 +00:00
|
|
|
if(ExprPtr e = lookup(ctx))
|
|
|
|
return e->evaluateInt(ctx);
|
|
|
|
else
|
|
|
|
return 0;
|
2014-10-07 22:41:40 +00:00
|
|
|
}
|
2014-10-07 23:17:17 +00:00
|
|
|
|
2014-10-07 23:37:51 +00:00
|
|
|
std::string IdentifierExpr::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
2014-10-30 01:56:49 +00:00
|
|
|
if(ExprPtr e = lookup(ctx))
|
|
|
|
return e->evaluateString(ctx);
|
|
|
|
else
|
|
|
|
return "";
|
2014-10-07 23:37:51 +00:00
|
|
|
}
|
|
|
|
|
2014-10-07 23:17:17 +00:00
|
|
|
|
2014-10-30 01:56:49 +00:00
|
|
|
CaseExpr::CaseExpr(const std::string &tag, CompoundExprPtr expr, yy::location loc)
|
|
|
|
: Expression(loc), tag(tag), expr(expr)
|
2014-10-07 23:17:17 +00:00
|
|
|
{
|
|
|
|
}
|
2014-10-12 17:16:02 +00:00
|
|
|
|
|
|
|
|
|
|
|
int CountOfExpr::evaluateInt(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
assert(arg->arguments.size() == 0);
|
|
|
|
return ctx->getArrayCount(arg->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ArrayIndexExpr::evaluateInt(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
assert(arg->arguments.size() == 0);
|
|
|
|
return ctx->getArrayIndex(arg->id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string ReadExpr::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
std::string filename = arg->evaluateString(ctx);
|
|
|
|
std::ifstream instream(filename);
|
2018-01-07 11:59:21 +00:00
|
|
|
if(!instream)
|
|
|
|
{
|
|
|
|
ctx->problem(Diagnostic(Diagnostic::Severity::error, "could not $$read file " + filename, location));
|
|
|
|
}
|
2014-10-12 17:16:02 +00:00
|
|
|
return std::string(std::istreambuf_iterator<char>(instream.rdbuf()),
|
|
|
|
std::istreambuf_iterator<char>());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int UnimplementedExpr::evaluateInt(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
std::cerr << msg << std::endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string UnimplementedExpr::evaluateString(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
std::cerr << msg << std::endl;
|
|
|
|
return "";
|
|
|
|
}
|
2014-10-13 22:11:21 +00:00
|
|
|
|
|
|
|
|
2014-10-30 01:56:49 +00:00
|
|
|
PeekExpr::PeekExpr(ExprPtr addr, ExprPtr offset, ExprPtr size, yy::location loc)
|
|
|
|
: Expression(loc), addr(addr), offset(offset), size(size)
|
2014-10-13 22:11:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2014-10-30 01:56:49 +00:00
|
|
|
PeekExpr::PeekExpr(ExprPtr addr, int size, yy::location loc)
|
|
|
|
: Expression(loc),
|
|
|
|
addr(addr),
|
|
|
|
offset(std::make_shared<IntExpr>(0,loc)),
|
|
|
|
size(std::make_shared<IntExpr>(size,loc))
|
2014-10-13 22:11:21 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
int PeekExpr::evaluateInt(ResourceCompiler *ctx)
|
|
|
|
{
|
|
|
|
int p = addr->evaluateInt(ctx) + offset->evaluateInt(ctx);
|
|
|
|
int s = size->evaluateInt(ctx);
|
|
|
|
|
|
|
|
return ctx->peek(p, s);
|
|
|
|
}
|