- handle all unary operators.

- handle all binary operators which are already implemented in the code generator.
- implemented sizeof/alignof operators in code generator.
- rewrote RequestAddress so that its return value is not the writability of an address but the mere existence. Also changed it to not output errors itself because those cannot be dealt with by the calling function.
This commit is contained in:
Christoph Oelckers 2016-10-17 20:33:35 +02:00
parent 23a2a19a78
commit a6a0c4b93c
3 changed files with 174 additions and 20 deletions

View file

@ -264,9 +264,9 @@ FxExpression *FxExpression::Resolve(FCompileContext &ctx)
//
//==========================================================================
bool FxExpression::RequestAddress()
bool FxExpression::RequestAddress(bool *writable)
{
ScriptPosition.Message(MSG_ERROR, "invalid dereference\n");
if (writable != nullptr) *writable = false;
return false;
}
@ -1488,6 +1488,67 @@ ExpEmit FxUnaryNotBoolean::Emit(VMFunctionBuilder *build)
return from;
}
//==========================================================================
//
//
//
//==========================================================================
FxSizeAlign::FxSizeAlign(FxExpression *operand, int which)
: FxExpression(operand->ScriptPosition)
{
Operand = operand;
Which = which;
}
//==========================================================================
//
//
//
//==========================================================================
FxSizeAlign::~FxSizeAlign()
{
SAFE_DELETE(Operand);
}
//==========================================================================
//
//
//
//==========================================================================
FxExpression *FxSizeAlign::Resolve(FCompileContext& ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(Operand, ctx);
auto type = Operand->ValueType;
if (Operand->isConstant())
{
ScriptPosition.Message(MSG_ERROR, "cannot determine %s of a constant", Which == 'a'? "alignment" : "size");
delete this;
return NULL;
}
else if (!Operand->RequestAddress(nullptr))
{
ScriptPosition.Message(MSG_ERROR, "Operand must be addressable to determine %s", Which == 'a' ? "alignment" : "size");
delete this;
return NULL;
}
else
{
FxExpression *x = new FxConstant(Which == 'a' ? int(type->Align) : int(type->Size), Operand->ScriptPosition);
delete this;
return x->Resolve(ctx);
}
}
ExpEmit FxSizeAlign::Emit(VMFunctionBuilder *build)
{
return ExpEmit();
}
//==========================================================================
//
// FxPreIncrDecr
@ -1506,10 +1567,11 @@ FxPreIncrDecr::~FxPreIncrDecr()
SAFE_DELETE(Base);
}
bool FxPreIncrDecr::RequestAddress()
bool FxPreIncrDecr::RequestAddress(bool *writable)
{
AddressRequested = true;
return AddressWritable;
if (writable != nullptr) *writable = AddressWritable;
return true;
}
FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx)
@ -1531,7 +1593,7 @@ FxExpression *FxPreIncrDecr::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
if (!(AddressWritable = Base->RequestAddress()))
if (!Base->RequestAddress(&AddressWritable) || !AddressWritable )
{
ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value");
delete this;
@ -1594,6 +1656,7 @@ FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx)
{
CHECKRESOLVED();
SAFE_RESOLVE(Base, ctx);
bool AddressWritable;
ValueType = Base->ValueType;
@ -1609,7 +1672,7 @@ FxExpression *FxPostIncrDecr::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
if (!Base->RequestAddress())
if (!Base->RequestAddress(&AddressWritable) || !AddressWritable)
{
ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value");
delete this;
@ -1667,10 +1730,11 @@ FxAssign::~FxAssign()
SAFE_DELETE(Right);
}
bool FxAssign::RequestAddress()
bool FxAssign::RequestAddress(bool *writable)
{
AddressRequested = true;
return AddressWritable;
if (writable != nullptr) *writable = AddressWritable;
return true;
}
FxExpression *FxAssign::Resolve(FCompileContext &ctx)
@ -1688,7 +1752,7 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx)
delete this;
return nullptr;
}
if (!(AddressWritable = Base->RequestAddress()))
if (!Base->RequestAddress(&AddressWritable) || !AddressWritable)
{
ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value");
delete this;
@ -3968,10 +4032,11 @@ FxClassMember::~FxClassMember()
//
//==========================================================================
bool FxClassMember::RequestAddress()
bool FxClassMember::RequestAddress(bool *writable)
{
AddressRequested = true;
return !!(~membervar->Flags & VARF_ReadOnly);
if (writable != nullptr) *writable = !(membervar->Flags & VARF_ReadOnly);
return true;
}
//==========================================================================
@ -4079,10 +4144,11 @@ FxArrayElement::~FxArrayElement()
//
//==========================================================================
bool FxArrayElement::RequestAddress()
bool FxArrayElement::RequestAddress(bool *writable)
{
AddressRequested = true;
return AddressWritable;
if (writable != nullptr) *writable = AddressWritable;
return true;
}
//==========================================================================
@ -4108,7 +4174,7 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
return NULL;
}
}
if (index->ValueType->GetRegType() != REGT_INT)
if (index->ValueType->GetRegType() != REGT_INT && index->ValueType != TypeName)
{
ScriptPosition.Message(MSG_ERROR, "Array index must be integer");
delete this;
@ -4141,7 +4207,12 @@ FxExpression *FxArrayElement::Resolve(FCompileContext &ctx)
delete this;
return NULL;
}
AddressWritable = Array->RequestAddress();
if (!Array->RequestAddress(&AddressWritable))
{
ScriptPosition.Message(MSG_ERROR, "Unable to dereference array.");
delete this;
return NULL;
}
return this;
}

View file

@ -212,7 +212,7 @@ public:
virtual FxExpression *Resolve(FCompileContext &ctx);
virtual bool isConstant() const;
virtual bool RequestAddress();
virtual bool RequestAddress(bool *writable);
virtual PPrototype *ReturnProto();
virtual VMFunction *GetDirectFunction();
bool IsNumeric() const { return ValueType != TypeName && (ValueType->GetRegType() == REGT_INT || ValueType->GetRegType() == REGT_FLOAT); }
@ -553,6 +553,24 @@ public:
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
// FxSign
//
//==========================================================================
class FxSizeAlign : public FxExpression
{
FxExpression *Operand;
int Which;
public:
FxSizeAlign(FxExpression*, int which);
~FxSizeAlign();
FxExpression *Resolve(FCompileContext&);
ExpEmit Emit(VMFunctionBuilder *build);
};
//==========================================================================
//
// FxPreIncrDecr
@ -570,7 +588,7 @@ public:
FxPreIncrDecr(FxExpression *base, int token);
~FxPreIncrDecr();
FxExpression *Resolve(FCompileContext&);
bool RequestAddress();
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
};
@ -609,7 +627,7 @@ public:
FxAssign(FxExpression *base, FxExpression *right);
~FxAssign();
FxExpression *Resolve(FCompileContext&);
bool RequestAddress();
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
ExpEmit Address;
@ -932,7 +950,7 @@ public:
FxClassMember(FxExpression*, PField*, const FScriptPosition&);
~FxClassMember();
FxExpression *Resolve(FCompileContext&);
bool RequestAddress();
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
};
@ -967,7 +985,7 @@ public:
FxArrayElement(FxExpression*, FxExpression*);
~FxArrayElement();
FxExpression *Resolve(FCompileContext&);
bool RequestAddress();
bool RequestAddress(bool *writable);
ExpEmit Emit(VMFunctionBuilder *build);
};

View file

@ -2405,6 +2405,46 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
}
}
case AST_ExprUnary:
{
auto unary = static_cast<ZCC_ExprUnary *>(ast);
auto operand = ConvertNode(unary->Operand);
auto op = unary->Operation;
switch (op)
{
case PEX_PostDec:
case PEX_PostInc:
return new FxPostIncrDecr(operand, op == PEX_PostDec ? TK_Decr : TK_Incr);
case PEX_PreDec:
case PEX_PreInc:
return new FxPreIncrDecr(operand, op == PEX_PostDec ? TK_Decr : TK_Incr);
case PEX_Negate:
return new FxMinusSign(operand);
case PEX_AntiNegate:
return new FxPlusSign(operand);
case PEX_BitNot:
return new FxUnaryNotBitwise(operand);
case PEX_BoolNot:
return new FxUnaryNotBoolean(operand);
case PEX_SizeOf:
case PEX_AlignOf:
return new FxSizeAlign(operand, op == PEX_AlignOf ? 'a' : 's');
default:
assert(0 && "Unknown unary operator."); // should never happen
Error(unary, "Unknown unary operator ID #%d", op);
return new FxNop(*ast);
}
break;
}
case AST_ExprBinary:
{
auto binary = static_cast<ZCC_ExprBinary *>(ast);
@ -2433,6 +2473,31 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast)
case PEX_BitXor:
return new FxBinaryInt(op == PEX_LeftShift ? TK_LShift : op == PEX_RightShift ? TK_RShift : op == PEX_URightShift? TK_URShift : op == PEX_BitAnd ? '&' : op == PEX_BitOr ? '|' : '^', left, right);
case PEX_BoolOr:
case PEX_BoolAnd:
return new FxBinaryLogical(op == PEX_BoolAnd ? TK_AndAnd : TK_OrOr, left, right);
case PEX_LT:
case PEX_LTEQ:
case PEX_GT:
case PEX_GTEQ:
return new FxCompareRel(op == PEX_LT ? '<' : op == PEX_RightShift ? '>' : op == PEX_LTEQ ? TK_Leq : TK_Geq, left, right);
case PEX_EQEQ:
case PEX_NEQ:
return new FxCompareEq(op == PEX_NEQ ? TK_Neq : TK_Eq, left, right);
// todo: These do not have representations in DECORATE and no implementation exists yet.
case PEX_LTGTEQ:
case PEX_Concat:
case PEX_Is:
// more esoteric operators
case PEX_APREQ:
// vector operations will be done later.
case PEX_CrossProduct:
case PEX_DotProduct:
default:
I_Error("Binary operator %d not implemented yet", op);
}