From a6a0c4b93c9b163cc185d59495720d9831efbacb Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 17 Oct 2016 20:33:35 +0200 Subject: [PATCH] - 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. --- src/scripting/codegeneration/codegen.cpp | 101 +++++++++++++++++++---- src/scripting/codegeneration/codegen.h | 28 +++++-- src/scripting/zscript/zcc_compile.cpp | 65 +++++++++++++++ 3 files changed, 174 insertions(+), 20 deletions(-) diff --git a/src/scripting/codegeneration/codegen.cpp b/src/scripting/codegeneration/codegen.cpp index c68fc3723..14f1627d9 100644 --- a/src/scripting/codegeneration/codegen.cpp +++ b/src/scripting/codegeneration/codegen.cpp @@ -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; } diff --git a/src/scripting/codegeneration/codegen.h b/src/scripting/codegeneration/codegen.h index 8d4936185..1a2d2045d 100644 --- a/src/scripting/codegeneration/codegen.h +++ b/src/scripting/codegeneration/codegen.h @@ -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); }; diff --git a/src/scripting/zscript/zcc_compile.cpp b/src/scripting/zscript/zcc_compile.cpp index 9d0ff5428..c55d6994a 100644 --- a/src/scripting/zscript/zcc_compile.cpp +++ b/src/scripting/zscript/zcc_compile.cpp @@ -2405,6 +2405,46 @@ FxExpression *ZCCCompiler::ConvertNode(ZCC_TreeNode *ast) } } + case AST_ExprUnary: + { + auto unary = static_cast(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(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); }