Index operator overload

This commit is contained in:
drmortalwombat 2023-07-02 18:21:40 +02:00
parent 7f6cf654f6
commit ef0a79b8f0
5 changed files with 97 additions and 8 deletions

View File

@ -61,6 +61,7 @@ Supported Features:
* operator overloading (not complete yet) * operator overloading (not complete yet)
* single inheritance of class and struct * single inheritance of class and struct
* const member functions * const member functions
* new, delete, new[] and delete[]
## Installation and Usage ## Installation and Usage

View File

@ -38,6 +38,17 @@ static inline InterType InterTypeOf(const Declaration* dec)
} }
} }
InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v)
{
if (v.mType->mType == DT_TYPE_REFERENCE)
{
v.mType = v.mType->mBase;
v.mReference++;
}
return v;
}
InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level) InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level)
{ {
while (v.mReference > level) while (v.mReference > level)
@ -1617,6 +1628,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
} }
if (exp->mType == EX_ASSIGNMENT)
{
vl = ToValue(proc, exp, block, vl);
vr = ToValue(proc, exp, block, vr);
}
if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB)))
{ {
if (!vl.mType->CanAssign(vr.mType)) if (!vl.mType->CanAssign(vr.mType))
@ -1631,6 +1648,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
exp->mRight->mDecValue->mLinkerObject->mFlags |= LOBJF_CONST; exp->mRight->mDecValue->mLinkerObject->mFlags |= LOBJF_CONST;
} }
if (vl.mType->mType == DT_TYPE_REFERENCE) if (vl.mType->mType == DT_TYPE_REFERENCE)
{ {
vr = Dereference(proc, exp, block, vr, 1); vr = Dereference(proc, exp, block, vr, 1);
@ -1661,6 +1679,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
else if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION) else if (vl.mType->mType == DT_TYPE_STRUCT || vl.mType->mType == DT_TYPE_ARRAY || vl.mType->mType == DT_TYPE_UNION)
{ {
vr = ToValue(proc, exp, block, vr);
vr = Dereference(proc, exp, block, vr, 1); vr = Dereference(proc, exp, block, vr, 1);
vl = Dereference(proc, exp, block, vl, 1); vl = Dereference(proc, exp, block, vl, 1);
@ -1689,6 +1709,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
else else
{ {
vr = ToValue(proc, exp, block, vr);
if (vl.mType->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)) if (vl.mType->mType == DT_TYPE_POINTER && (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION))
{ {
vr = Dereference(proc, exp, block, vr, 1); vr = Dereference(proc, exp, block, vr, 1);
@ -1864,6 +1886,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vr = ToValue(proc, exp, block, vr);
int stride = vl.mType->Stride(); int stride = vl.mType->Stride();
if (vl.mType->mType == DT_TYPE_ARRAY && exp->mRight->mType == EX_CONSTANT && exp->mRight->mDecValue->mType == DT_CONST_INTEGER) if (vl.mType->mType == DT_TYPE_ARRAY && exp->mRight->mType == EX_CONSTANT && exp->mRight->mDecValue->mType == DT_CONST_INTEGER)
@ -1919,6 +1944,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_QUALIFY: case EX_QUALIFY:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vl = Dereference(proc, exp, block, vl, 1); vl = Dereference(proc, exp, block, vl, 1);
if (vl.mReference != 1) if (vl.mReference != 1)
@ -1947,6 +1975,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vr = ToValue(proc, exp, block, vr);
vr = Dereference(proc, exp, block, vr); vr = Dereference(proc, exp, block, vr);
InterInstruction * ins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_BINARY_OPERATOR);
@ -2243,6 +2275,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_PREINCDEC: case EX_PREINCDEC:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vl = Dereference(proc, exp, block, vl, 1); vl = Dereference(proc, exp, block, vl, 1);
if (vl.mReference != 1) if (vl.mReference != 1)
@ -2304,6 +2337,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_POSTINCDEC: case EX_POSTINCDEC:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vl = Dereference(proc, exp, block, vl, 1); vl = Dereference(proc, exp, block, vl, 1);
if (vl.mReference != 1) if (vl.mReference != 1)
@ -2363,6 +2397,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_PREFIX: case EX_PREFIX:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_UNARY_OPERATOR);
@ -2468,10 +2503,13 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
case EX_RELATIONAL: case EX_RELATIONAL:
{ {
vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); vl = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper);
vl = ToValue(proc, exp, block, vl);
vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0); vl = Dereference(proc, exp, block, vl, vl.mType->mType == DT_TYPE_ARRAY ? 1 : 0);
vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper); vr = TranslateExpression(procType, proc, block, exp->mRight, destack, breakBlock, continueBlock, inlineMapper);
vr = ToValue(proc, exp, block, vr);
vr = Dereference(proc, exp, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0); vr = Dereference(proc, exp, block, vr, vr.mType->mType == DT_TYPE_ARRAY ? 1 : 0);
InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); InterInstruction * ins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR);
Declaration* dtype = TheSignedIntTypeDeclaration; Declaration* dtype = TheSignedIntTypeDeclaration;

View File

@ -76,6 +76,7 @@ protected:
void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock); void BuildSwitchTree(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock* block, ExValue v, const SwitchNodeArray& nodes, int left, int right, InterCodeBasicBlock* dblock);
ExValue ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v);
ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0); ExValue Dereference(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, int level = 0);
ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true); ExValue CoerceType(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v, Declaration * type, bool checkTrunc = true);
ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr); ExValue TranslateExpression(Declaration * procType, InterCodeProcedure * proc, InterCodeBasicBlock*& block, Expression* exp, DestructStack*& destack, const BranchTarget & breakBlock, const BranchTarget& continueBlock, InlineMapper * inlineMapper, ExValue * lrexp = nullptr);

View File

@ -4256,19 +4256,24 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
for (;;) for (;;)
{ {
if (mScanner->mToken == TK_OPEN_BRACKET) if (ConsumeTokenIf(TK_OPEN_BRACKET))
{ {
if (exp->mDecType->mType != DT_TYPE_ARRAY && exp->mDecType->mType != DT_TYPE_POINTER)
mErrors->Error(mScanner->mLocation, EERR_INVALID_INDEX, "Array expected for indexing");
mScanner->NextToken();
Expression* nexp = new Expression(mScanner->mLocation, EX_INDEX); Expression* nexp = new Expression(mScanner->mLocation, EX_INDEX);
nexp->mLeft = exp; nexp->mLeft = exp;
nexp->mRight = ParseExpression(false); nexp->mRight = ParseExpression(false);
if (mScanner->mToken == TK_CLOSE_BRACKET) ConsumeToken(TK_CLOSE_BRACKET);
mScanner->NextToken();
if (exp->mDecType->mType == DT_TYPE_STRUCT)
{
nexp = CheckOperatorOverload(nexp);
}
else if (exp->mDecType->mType == DT_TYPE_ARRAY || exp->mDecType->mType == DT_TYPE_POINTER)
{
nexp->mDecType = exp->mDecType->mBase;
}
else else
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "']' expected"); mErrors->Error(mScanner->mLocation, EERR_INVALID_INDEX, "Array expected for indexing");
nexp->mDecType = exp->mDecType->mBase;
if (!nexp->mDecType) if (!nexp->mDecType)
nexp->mDecType = TheVoidTypeDeclaration; nexp->mDecType = TheVoidTypeDeclaration;
exp = nexp; exp = nexp;
@ -5139,6 +5144,43 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
} }
} }
} }
else if (exp->mType == EX_INDEX)
{
Declaration* tdec = exp->mLeft->mDecType;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator[]"));
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 = nexp->mRight;
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;

View File

@ -1504,6 +1504,13 @@ void Scanner::NextRawToken(void)
mTokenIdent = Ident::Unique("operator<="); mTokenIdent = Ident::Unique("operator<=");
break; break;
case TK_OPEN_BRACKET:
NextRawToken();
if (mToken != TK_CLOSE_BRACKET)
mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "']' expected");
mTokenIdent = Ident::Unique("operator[]");
break;
default: default:
mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token");
} }