Prefix and inc operator overload

This commit is contained in:
drmortalwombat 2023-07-09 10:52:11 +02:00
parent 0bab98ccc6
commit 66631c915b
4 changed files with 312 additions and 3 deletions

View File

@ -1,5 +1,8 @@
rem @echo off rem @echo off
@call :test operatoroverload.cpp
@if %errorlevel% neq 0 goto :error
@call :test virtualdestruct.cpp @call :test virtualdestruct.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

View File

@ -0,0 +1,90 @@
#include <assert.h>
struct A
{
int n;
A(int n_)
: n(n_) {}
A(const A & a)
: n(a.n) {}
A operator+(const A & a) const
{
return A(n + a.n);
}
A operator-(const A & a) const
{
return A(n - a.n);
}
A & operator+=(const A & a)
{
n += a.n;
return *this;
}
A & operator-=(const A & a)
{
n -= a.n;
return *this;
}
A operator-(void) const
{
return A(-n);
}
A & operator++(void)
{
n++;
return *this;
}
A & operator--(void)
{
n--;
return *this;
}
A operator++(int);
A operator--(int);
};
A A::operator++(int)
{
A a(*this);
n++;
return a;
}
A A::operator--(int)
{
A a(*this);
n--;
return a;
}
int main(void)
{
A a(7), b(8), c(9);
assert((++a).n == 8);
assert(a.n == 8);
assert((--a).n == 7);
assert(a.n == 7);
assert((a++).n == 7);
assert(a.n == 8);
assert((a--).n == 8);
assert(a.n == 7);
assert((a + b - c + -a + -b - -c).n == 0);
return 0;
}

View File

@ -2693,7 +2693,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
{ {
Expression* lexp = nullptr, * rexp = nullptr; Expression* lexp = nullptr, * rexp = nullptr;
if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL) if (exp->mType == EX_PREFIX && exp->mToken == TK_BINARY_AND && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE)
{ {
lexp = AddFunctionCallRefReturned(exp->mLeft); lexp = AddFunctionCallRefReturned(exp->mLeft);
@ -2714,7 +2714,58 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
vexp->mDecType = rtdec; vexp->mDecType = rtdec;
vexp->mDecValue = vdec; vexp->mDecValue = vdec;
Expression * pex = new Expression(exp->mLocation, EX_INITIALIZATION); Expression* pex = new Expression(exp->mLocation, EX_INITIALIZATION);
pex->mToken = TK_ASSIGN;
pex->mLeft = vexp;
pex->mRight = exp->mLeft;
pex->mDecValue = nullptr;
pex->mDecType = vdec->mBase;
exp->mLeft = pex;
if (rtdec->mDestructor)
{
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = vexp;
texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = vdec->mBase;
texp->mDecType->mSize = 2;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = rtdec->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = texp;
rexp = ConcatExpression(rexp, dexp);
}
}
else if (exp->mType == EX_QUALIFY && exp->mLeft->mType == EX_CALL && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE)
{
lexp = AddFunctionCallRefReturned(exp->mLeft);
// Returning a value object for pass by address
// add a temporary variable
int nindex = mLocalIndex++;
Declaration* rtdec = exp->mLeft->mDecType;
Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE);
vdec->mVarIndex = nindex;
vdec->mBase = rtdec;
vdec->mSize = rtdec->mSize;
Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE);
vexp->mDecType = rtdec;
vexp->mDecValue = vdec;
Expression* pex = new Expression(exp->mLocation, EX_INITIALIZATION);
pex->mToken = TK_ASSIGN; pex->mToken = TK_ASSIGN;
pex->mLeft = vexp; pex->mLeft = vexp;
pex->mRight = exp->mLeft; pex->mRight = exp->mLeft;
@ -4614,8 +4665,8 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
nexp->mToken = mScanner->mToken; nexp->mToken = mScanner->mToken;
nexp->mLeft = exp; nexp->mLeft = exp;
nexp->mDecType = exp->mDecType; nexp->mDecType = exp->mDecType;
exp = nexp;
mScanner->NextToken(); mScanner->NextToken();
exp = CheckOperatorOverload(nexp);
} }
else if (mScanner->mToken == TK_ARROW) else if (mScanner->mToken == TK_ARROW)
{ {
@ -4698,6 +4749,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
mScanner->NextToken(); mScanner->NextToken();
nexp->mLeft = ParsePrefixExpression(false);; nexp->mLeft = ParsePrefixExpression(false);;
nexp->mDecType = nexp->mLeft->mDecType; nexp->mDecType = nexp->mLeft->mDecType;
nexp = CheckOperatorOverload(nexp);
} }
else if (mScanner->mToken == TK_NEW) else if (mScanner->mToken == TK_NEW)
{ {
@ -5002,6 +5054,7 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
else else
nexp->mDecType = nexp->mLeft->mDecType; nexp->mDecType = nexp->mLeft->mDecType;
} }
nexp = CheckOperatorOverload(nexp);
return nexp->ConstantFold(mErrors); return nexp->ConstantFold(mErrors);
} }
else else
@ -5384,6 +5437,108 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
} }
} }
} }
else if (exp->mType == EX_PREINCDEC)
{
const Ident* opident = nullptr;
switch (exp->mToken)
{
case TK_INC:
opident = Ident::Unique("operator++");
break;
case TK_DEC:
opident = Ident::Unique("operator--");
break;
}
if (opident)
{
Declaration* tdec = exp->mLeft->mDecType;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(opident);
if (mdec)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_CALL);
nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = mdec->mBase;
nexp->mLeft->mDecValue = mdec;
nexp->mDecType = mdec->mBase;
nexp->mRight = exp->mRight;
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mLeft->mDecType;
texp->mDecType->mSize = 2;
nexp->mRight = texp;
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp;
}
}
}
}
else if (exp->mType == EX_POSTINCDEC)
{
const Ident* opident = nullptr;
switch (exp->mToken)
{
case TK_INC:
opident = Ident::Unique("operator++");
break;
case TK_DEC:
opident = Ident::Unique("operator--");
break;
}
if (opident)
{
Declaration* tdec = exp->mLeft->mDecType;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(opident);
if (mdec)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_CALL);
nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = mdec->mBase;
nexp->mLeft->mDecValue = mdec;
nexp->mDecType = mdec->mBase;
nexp->mRight = exp->mRight;
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mLeft->mDecType;
texp->mDecType->mSize = 2;
Expression* lexp = new Expression(nexp->mLocation, EX_LIST);
lexp->mLeft = texp;
lexp->mRight = new Expression(nexp->mLocation, EX_CONSTANT);
lexp->mRight->mDecType = TheSignedIntTypeDeclaration;
lexp->mRight->mDecValue = new Declaration(nexp->mLocation, DT_CONST_INTEGER);
lexp->mRight->mDecValue->mBase = TheSignedIntTypeDeclaration;
nexp->mRight = lexp;
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp;
}
}
}
}
else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL) else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL)
{ {
const Ident* opident = nullptr; const Ident* opident = nullptr;
@ -5472,6 +5627,60 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
ResolveOverloadCall(nexp->mLeft, nexp->mRight); ResolveOverloadCall(nexp->mLeft, nexp->mRight);
nexp->mDecType = nexp->mLeft->mDecType->mBase; nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp;
}
}
}
}
else if (exp->mType == EX_PREFIX)
{
const Ident* opident = nullptr;
switch (exp->mToken)
{
case TK_ADD:
opident = Ident::Unique("operator+");
break;
case TK_SUB:
opident = Ident::Unique("operator-");
break;
case TK_MUL:
opident = Ident::Unique("operator*");
break;
case TK_BINARY_NOT:
opident = Ident::Unique("operator~");
break;
}
if (opident)
{
Declaration* tdec = exp->mLeft->mDecType;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(opident);
if (mdec)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_CALL);
nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = mdec->mBase;
nexp->mLeft->mDecValue = mdec;
nexp->mDecType = mdec->mBase;
nexp->mRight = exp->mRight;
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mLeft->mDecType;
texp->mDecType->mSize = 2;
nexp->mRight = texp;
ResolveOverloadCall(nexp->mLeft, nexp->mRight);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp; exp = nexp;
} }
} }

View File

@ -1507,6 +1507,13 @@ void Scanner::NextRawToken(void)
mTokenIdent = Ident::Unique("operator<="); mTokenIdent = Ident::Unique("operator<=");
break; break;
case TK_INC:
mTokenIdent = Ident::Unique("operator++");
break;
case TK_DEC:
mTokenIdent = Ident::Unique("operator--");
break;
case TK_OPEN_BRACKET: case TK_OPEN_BRACKET:
NextRawToken(); NextRawToken();
if (mToken != TK_CLOSE_BRACKET) if (mToken != TK_CLOSE_BRACKET)