diff --git a/src/thingdef/thingdef_exp.cpp b/src/thingdef/thingdef_exp.cpp index 12dd5957ef..ffe7bf11ae 100644 --- a/src/thingdef/thingdef_exp.cpp +++ b/src/thingdef/thingdef_exp.cpp @@ -96,18 +96,23 @@ FxExpression *ParseExpression (FScanner &sc, PClassActor *cls, bool mustresolve) static FxExpression *ParseExpressionM (FScanner &sc, PClassActor *cls) { - FxExpression *condition = ParseExpressionL (sc, cls); + FxExpression *base = ParseExpressionL (sc, cls); if (sc.CheckToken('?')) { FxExpression *truex = ParseExpressionM (sc, cls); sc.MustGetToken(':'); FxExpression *falsex = ParseExpressionM (sc, cls); - return new FxConditional(condition, truex, falsex); + return new FxConditional(base, truex, falsex); + } + else if (sc.CheckToken('=')) + { + FxExpression *right = ParseExpressionM(sc, cls); + return new FxAssign(base, right); } else { - return condition; + return base; } } diff --git a/src/thingdef/thingdef_exp.h b/src/thingdef/thingdef_exp.h index 25c4b3afb1..1284f364d2 100644 --- a/src/thingdef/thingdef_exp.h +++ b/src/thingdef/thingdef_exp.h @@ -508,6 +508,27 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxAssign +// +//========================================================================== + +class FxAssign : public FxExpression +{ + FxExpression *Base; + FxExpression *Right; + bool AddressRequested; + bool AddressWritable; + +public: + FxAssign(FxExpression *base, FxExpression *right); + ~FxAssign(); + FxExpression *Resolve(FCompileContext&); + bool RequestAddress(); + ExpEmit Emit(VMFunctionBuilder *build); +}; + //========================================================================== // // FxBinary diff --git a/src/thingdef/thingdef_expression.cpp b/src/thingdef/thingdef_expression.cpp index 63b6be9ca9..34a2c0f95b 100644 --- a/src/thingdef/thingdef_expression.cpp +++ b/src/thingdef/thingdef_expression.cpp @@ -1048,6 +1048,100 @@ ExpEmit FxPostIncrDecr::Emit(VMFunctionBuilder *build) return out; } +//========================================================================== +// +// FxAssign +// +//========================================================================== + +FxAssign::FxAssign(FxExpression *base, FxExpression *right) +: FxExpression(base->ScriptPosition), Base(base), Right(right) +{ + AddressRequested = false; + AddressWritable = false; +} + +FxAssign::~FxAssign() +{ + SAFE_DELETE(Base); + SAFE_DELETE(Right); +} + +bool FxAssign::RequestAddress() +{ + AddressRequested = true; + return AddressWritable; +} + +FxExpression *FxAssign::Resolve(FCompileContext &ctx) +{ + CHECKRESOLVED(); + SAFE_RESOLVE(Base, ctx); + SAFE_RESOLVE(Right, ctx); + + ValueType = Base->ValueType; + + if (!Base->IsNumeric() || !Right->IsNumeric()) + { + ScriptPosition.Message(MSG_ERROR, "Numeric type expected"); + delete this; + return nullptr; + } + if (!(AddressWritable = Base->RequestAddress())) + { + ScriptPosition.Message(MSG_ERROR, "Expression must be a modifiable value"); + delete this; + return nullptr; + } + + if (Right->ValueType != ValueType) + { + if (ValueType == TypeBool) + { + Right = new FxBoolCast(Right); + } + else if (ValueType->GetRegType() == REGT_INT) + { + Right = new FxIntCast(Right); + } + else + { + Right = new FxFloatCast(Right); + } + SAFE_RESOLVE(Right, ctx); + } + + return this; +} + +ExpEmit FxAssign::Emit(VMFunctionBuilder *build) +{ + assert(ValueType == Base->ValueType && IsNumeric()); + assert(ValueType->GetRegType() == Right->ValueType->GetRegType()); + + ExpEmit pointer = Base->Emit(build); + ExpEmit result = Right->Emit(build); + + if (result.Konst) + { + ExpEmit temp(build, result.RegType); + build->Emit(result.RegType == REGT_FLOAT ? OP_LKF : OP_LK, temp.RegNum, result.RegNum); + result.Free(build); + result = temp; + } + + build->Emit(ValueType->GetStoreOp(), pointer.RegNum, result.RegNum, build->GetConstantInt(0)); + + if (AddressRequested) + { + result.Free(build); + return pointer; + } + + pointer.Free(build); + return result; +} + //========================================================================== // //