mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-23 20:42:24 +00:00
Added the direct assignment operator to DECORATE
This commit is contained in:
parent
8437313e7c
commit
90cc79a902
3 changed files with 123 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
|
|
Loading…
Reference in a new issue