diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index ffe7bf11a..991e9b947 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -112,7 +112,67 @@ static FxExpression *ParseExpressionM (FScanner &sc, PClassActor *cls) } else { - return base; + FxBinary *exp; + FxAssignSelf *left = new FxAssignSelf(sc); + + sc.GetToken(); + switch (sc.TokenType) + { + case TK_AddEq: + exp = new FxAddSub('+', left, nullptr); + break; + + case TK_SubEq: + exp = new FxAddSub('-', left, nullptr); + break; + + case TK_MulEq: + exp = new FxMulDiv('*', left, nullptr); + break; + + case TK_DivEq: + exp = new FxMulDiv('/', left, nullptr); + break; + + case TK_ModEq: + exp = new FxMulDiv('%', left, nullptr); + break; + + case TK_LShiftEq: + exp = new FxBinaryInt(TK_LShift, left, nullptr); + break; + + case TK_RShiftEq: + exp = new FxBinaryInt(TK_RShift, left, nullptr); + break; + + case TK_URShiftEq: + exp = new FxBinaryInt(TK_URShift, left, nullptr); + break; + + case TK_AndEq: + exp = new FxBinaryInt('&', left, nullptr); + break; + + case TK_XorEq: + exp = new FxBinaryInt('^', left, nullptr); + break; + + case TK_OrEq: + exp = new FxBinaryInt('|', left, nullptr); + break; + + default: + sc.UnGet(); + delete left; + return base; + } + + exp->right = ParseExpressionM(sc, cls); + + FxAssign *ret = new FxAssign(base, exp); + left->Assignment = ret; + return ret; } } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 1284f364d..7ec542772 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -527,6 +527,24 @@ public: FxExpression *Resolve(FCompileContext&); bool RequestAddress(); ExpEmit Emit(VMFunctionBuilder *build); + + ExpEmit Address; +}; + +//========================================================================== +// +// FxAssignSelf +// +//========================================================================== + +class FxAssignSelf : public FxExpression +{ +public: + FxAssign *Assignment; + + FxAssignSelf(const FScriptPosition &pos); + FxExpression *Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder *build); }; //========================================================================== diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 34a2c0f95..07f4d9fdf 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1077,10 +1077,11 @@ FxExpression *FxAssign::Resolve(FCompileContext &ctx) { CHECKRESOLVED(); SAFE_RESOLVE(Base, ctx); - SAFE_RESOLVE(Right, ctx); ValueType = Base->ValueType; + SAFE_RESOLVE(Right, ctx); + if (!Base->IsNumeric() || !Right->IsNumeric()) { ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); @@ -1120,8 +1121,10 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); ExpEmit pointer = Base->Emit(build); - ExpEmit result = Right->Emit(build); + Address = pointer; + ExpEmit result = Right->Emit(build); + if (result.Konst) { ExpEmit temp(build, result.RegType); @@ -1142,6 +1145,39 @@ ExpEmit FxAssign::Emit(VMFunctionBuilder *build) return result; } +//========================================================================== +// +// FxAssignSelf +// +//========================================================================== + +FxAssignSelf::FxAssignSelf(const FScriptPosition &pos) +: FxExpression(pos) +{ + Assignment = nullptr; +} + +FxExpression *FxAssignSelf::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + + // This should never happen if FxAssignSelf is used correctly + assert(Assignment != nullptr); + + ValueType = Assignment->ValueType; + + return this; +} + +ExpEmit FxAssignSelf::Emit(VMFunctionBuilder *build) +{ + assert(ValueType = Assignment->ValueType); + ExpEmit pointer = Assignment->Address; // FxAssign should have already emitted it + ExpEmit out(build, ValueType->GetRegType()); + build->Emit(ValueType->GetLoadOp(), out.RegNum, pointer.RegNum, build->GetConstantInt(0)); + return out; +} + //========================================================================== // //