From 9e92c2863aa07412632d3a2ef7386fe92534a409 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sun, 18 Jun 2023 14:41:23 +0200 Subject: [PATCH] Add member functions in cpp mode --- oscar64/Declaration.h | 2 + oscar64/Errors.h | 1 + oscar64/Parser.cpp | 298 +++++++++++++++++++++++++++++++++--------- oscar64/Parser.h | 4 +- oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + 6 files changed, 247 insertions(+), 62 deletions(-) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 350d2bd..51707af 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -92,6 +92,8 @@ static const uint64 DTF_FUNC_PURE = (1ULL << 39); static const uint64 DTF_FPARAM_CONST = (1ULL << 40); static const uint64 DTF_FPARAM_NOCONST = (1ULL << 41); +static const uint64 DTF_FUNC_THIS = (1ULL << 42); + static const uint64 DTF_VAR_ALIASING = (1ULL << 48); diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 23724de..3285f68 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -72,6 +72,7 @@ enum ErrorID ERRR_CANNOT_FIND_BANK_OF_EXPRESSION, ERRO_NOT_A_NAMESPACE, ERRO_NOT_A_BASE_CLASS, + ERRO_THIS_OUTSIDE_OF_METHOD, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 0be34af..73f96d6 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -17,6 +17,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mUnrollLoopPage = false; mInlineCall = false; mCompilerOptionSP = 0; + mThisPointer = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -64,7 +65,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) { dec->mIdent = structName; dec->mQualIdent = mScope->Mangle(structName); - dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, structName); } if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) @@ -85,51 +86,82 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) if (mScanner->mToken == TK_OPEN_BRACE) { + Declaration* othis = mThisPointer; + + mThisPointer = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + mThisPointer->mFlags |= DTF_CONST | DTF_DEFINED; + mThisPointer->mBase = dec; + mThisPointer->mSize = 2; + mScanner->NextToken(); Declaration* mlast = nullptr; for (;;) { Declaration* mdec = ParseDeclaration(nullptr, false, false); + mdec->mQualIdent = dec->mScope->Mangle(mdec->mIdent); + int offset = dec->mSize; if (dt == DT_TYPE_UNION) offset = 0; - while (mdec) + if (mdec->mBase->mType == DT_TYPE_FUNCTION) { - if (!(mdec->mBase->mFlags & DTF_DEFINED)) - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + mdec->mType = DT_CONST_FUNCTION; + mdec->mSection = mCodeSection; + mdec->mFlags |= DTF_GLOBAL; + mdec->mBase->mFlags |= DTF_FUNC_THIS; - if (mdec->mType != DT_VARIABLE) - { - mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); - break; - } - - mdec->mType = DT_ELEMENT; - mdec->mOffset = offset; - - offset += mdec->mBase->mSize; - if (offset > dec->mSize) - dec->mSize = offset; + if (mCompilerOptions & COPT_NATIVE) + mdec->mFlags |= DTF_NATIVE; if (dec->mScope->Insert(mdec->mIdent, mdec)) mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - if (mlast) - mlast->mNext = mdec; - else - dec->mParams = mdec; - mlast = mdec; - mdec = mdec->mNext; - } + if (mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); - if (mScanner->mToken == TK_SEMICOLON) - mScanner->NextToken(); + if (!(mdec->mFlags & DTF_DEFINED)) + ConsumeToken(TK_SEMICOLON); + } else { - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); - break; + while (mdec) + { + if (!(mdec->mBase->mFlags & DTF_DEFINED)) + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Undefined type used in struct member declaration"); + + if (mdec->mType != DT_VARIABLE) + { + mErrors->Error(mdec->mLocation, EERR_UNDEFINED_OBJECT, "Named structure element expected"); + break; + } + + mdec->mType = DT_ELEMENT; + mdec->mOffset = offset; + + offset += mdec->mBase->mSize; + if (offset > dec->mSize) + dec->mSize = offset; + + if (dec->mScope->Insert(mdec->mIdent, mdec)) + mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); + + if (mlast) + mlast->mNext = mdec; + else + dec->mParams = mdec; + mlast = mdec; + mdec = mdec->mNext; + } + + if (mScanner->mToken == TK_SEMICOLON) + mScanner->NextToken(); + else + { + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "';' expected"); + break; + } } if (mScanner->mToken == TK_CLOSE_BRACE) @@ -145,6 +177,8 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) dec->mParams = nullptr; dec->mFlags |= DTF_DEFINED; + + mThisPointer = othis; } return dec; @@ -493,6 +527,21 @@ Declaration* Parser::ParsePostfixDeclaration(void) dec->mSection = mBSSection; dec->mBase = nullptr; mScanner->NextToken(); + while (ConsumeTokenIf(TK_COLCOLON)) + { + if (mScanner->mToken == TK_IDENT) + { + dec->mIdent = mScanner->mTokenIdent; + + char buffer[200]; + strcpy_s(buffer, dec->mQualIdent->mString); + strcat_s(buffer, "::"); + strcat_s(buffer, dec->mIdent->mString); + dec->mQualIdent = Ident::Unique(buffer); + + mScanner->NextToken(); + } + } } else { @@ -594,6 +643,7 @@ Declaration* Parser::ParsePostfixDeclaration(void) else mScanner->NextToken(); ndec->mBase = dec; + ndec->mFlags |= DTF_DEFINED; dec = ndec; } else @@ -1216,6 +1266,29 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { + if (ndec->mBase->mType == DT_TYPE_FUNCTION && mThisPointer) + { + Declaration* adec = new Declaration(ndec->mLocation, DT_ARGUMENT); + + adec->mVarIndex = 0; + adec->mOffset = 0; + adec->mBase = mThisPointer; + adec->mSize = adec->mBase->mSize; + adec->mNext = ndec->mBase->mParams; + adec->mIdent = adec->mQualIdent = Ident::Unique("this"); + + Declaration* p = adec->mBase->mParams; + while (p) + { + p->mVarIndex += 2; + p = p->mNext; + } + + ndec->mBase->mParams = adec; + + ndec->mBase->mFlags |= DTF_FUNC_THIS; + } + if (variable) { ndec->mFlags |= storageFlags; @@ -1258,6 +1331,23 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex { if (pdec->mType == DT_CONST_FUNCTION && ndec->mBase->mType == DT_TYPE_FUNCTION) { + if (pdec->mBase->mFlags & DTF_FUNC_THIS) + { + Declaration* adec = pdec->mBase->mParams->Clone(); + adec->mNext = ndec->mBase->mParams; + + Declaration* p = adec->mBase->mParams; + while (p) + { + p->mVarIndex += 2; + p = p->mNext; + } + + ndec->mBase->mParams = adec; + + ndec->mBase->mFlags |= DTF_FUNC_THIS; + } + if (!ndec->mBase->IsSame(pdec->mBase)) mErrors->Error(ndec->mLocation, EERR_DECLARATION_DIFFERS, "Function declaration differs", ndec->mIdent); else if (ndec->mFlags & ~pdec->mFlags & (DTF_HWINTERRUPT | DTF_INTERRUPT | DTF_FASTCALL | DTF_NATIVE)) @@ -1389,9 +1479,12 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex ndec->mBase->mCompilerOptions = mCompilerOptions; ndec->mVarIndex = -1; + ndec->mValue = ParseFunction(ndec->mBase); + ndec->mFlags |= DTF_DEFINED; ndec->mNumVars = mLocalIndex; + } return rdec; } @@ -1664,6 +1757,18 @@ Expression* Parser::ParseSimpleExpression(void) exp->mDecValue = dec; exp->mDecType = dec->mBase; + mScanner->NextToken(); + break; + case TK_THIS: + if (mThisPointer) + { + exp = new Expression(mScanner->mLocation, EX_VARIABLE); + exp->mDecType = mThisPointer->mBase; + exp->mDecValue = mThisPointer; + } + else + mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method"); + mScanner->NextToken(); break; case TK_IDENT: @@ -1791,6 +1896,88 @@ Expression* Parser::ParseSimpleExpression(void) } +Expression* Parser::ParseQualify(Expression* exp) +{ + Declaration* dtype = exp->mDecType; + + if (dtype->mType == DT_TYPE_REFERENCE) + dtype = dtype->mBase; + + if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_QUALIFY); + nexp->mLeft = exp; + if (mScanner->mToken == TK_IDENT) + { + Declaration* mdec = dtype->mScope->Lookup(mScanner->mTokenIdent); + + if (mdec) + { + mScanner->NextToken(); + if (mdec->mType == DT_ELEMENT) + { + nexp->mDecValue = mdec; + nexp->mDecType = mdec->mBase; + if (exp->mDecType->mFlags & DTF_CONST) + nexp->mDecType = nexp->mDecType->ToConstType(); + + exp = nexp->ConstantFold(mErrors); + } + else if (mdec->mType == DT_CONST_FUNCTION) + { + ConsumeToken(TK_OPEN_PARENTHESIS); + + nexp = new Expression(mScanner->mLocation, EX_CALL); + if (mInlineCall) + nexp->mType = EX_INLINE; + mInlineCall = false; + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + if (ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + nexp->mRight = nullptr; + else + { + nexp->mRight = ParseListExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp; + + if (nexp->mRight) + { + Expression* lexp = new Expression(nexp->mLocation, EX_SEQUENCE); + lexp->mLeft = texp; + lexp->mRight = nexp->mRight; + nexp->mRight = lexp; + } + else + nexp->mRight = texp; + + exp = nexp; + } + } + else + { + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); + mScanner->NextToken(); + } + + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Struct member identifier expected"); + } + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Struct expected"); + + return exp; +} + Expression* Parser::ParsePostfixExpression(void) { Expression* exp = ParseSimpleExpression(); @@ -1867,6 +2054,8 @@ Expression* Parser::ParsePostfixExpression(void) dexp->mDecType = exp->mDecType->mBase; dexp->mLeft = exp; + exp = ParseQualify(dexp); +/* if (dexp->mDecType->mType == DT_TYPE_STRUCT || dexp->mDecType->mType == DT_TYPE_UNION) { Expression* nexp = new Expression(mScanner->mLocation, EX_QUALIFY); @@ -1876,12 +2065,19 @@ Expression* Parser::ParsePostfixExpression(void) Declaration* mdec = dexp->mDecType->mScope->Lookup(mScanner->mTokenIdent); if (mdec) { - nexp->mDecValue = mdec; - nexp->mDecType = mdec->mBase; - if (exp->mDecType->mFlags & DTF_CONST) - nexp->mDecType = nexp->mDecType->ToConstType(); + if (mdec->mType == DT_ELEMENT) + { + nexp->mDecValue = mdec; + nexp->mDecType = mdec->mBase; + if (exp->mDecType->mFlags & DTF_CONST) + nexp->mDecType = nexp->mDecType->ToConstType(); - exp = nexp->ConstantFold(mErrors); + exp = nexp->ConstantFold(mErrors); + } + else if (mdec->mType == DT_CONST_FUNCTION) + { + assert(false); + } } else mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); @@ -1892,6 +2088,7 @@ Expression* Parser::ParsePostfixExpression(void) } else mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Struct expected"); +*/ } else mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Pointer expected"); @@ -1899,36 +2096,8 @@ Expression* Parser::ParsePostfixExpression(void) else if (mScanner->mToken == TK_DOT) { mScanner->NextToken(); - Declaration* dtype = exp->mDecType; - if (dtype->mType == DT_TYPE_REFERENCE) - dtype = dtype->mBase; - - if (dtype->mType == DT_TYPE_STRUCT || dtype->mType == DT_TYPE_UNION) - { - Expression* nexp = new Expression(mScanner->mLocation, EX_QUALIFY); - nexp->mLeft = exp; - if (mScanner->mToken == TK_IDENT) - { - Declaration* mdec = dtype->mScope->Lookup(mScanner->mTokenIdent); - if (mdec) - { - nexp->mDecValue = mdec; - nexp->mDecType = mdec->mBase; - if (exp->mDecType->mFlags & DTF_CONST) - nexp->mDecType = nexp->mDecType->ToConstType(); - - exp = nexp->ConstantFold(mErrors); - } - else - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); - mScanner->NextToken(); - } - else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Struct member identifier expected"); - } - else - mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Struct expected"); + exp = ParseQualify(exp); } else return exp; @@ -2284,6 +2453,11 @@ Expression* Parser::ParseListExpression(void) Expression* Parser::ParseFunction(Declaration * dec) { + Declaration* othis = mThisPointer; + if (dec->mFlags & DTF_FUNC_THIS) + mThisPointer = dec->mParams; + + DeclarationScope* scope = new DeclarationScope(mScope, SLEVEL_FUNCTION); mScope = scope; @@ -2301,6 +2475,8 @@ Expression* Parser::ParseFunction(Declaration * dec) mScope->End(mScanner->mLocation); mScope = mScope->mParent; + mThisPointer = othis; + return exp; } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 406bede..45277f4 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -13,7 +13,7 @@ public: DeclarationScope * mGlobals, * mScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mNamespace; + Declaration * mThisPointer; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -64,6 +64,8 @@ protected: Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); + Expression* ParseQualify(Expression * exp); + Expression* ParseSimpleExpression(void); Expression* ParsePrefixExpression(void); Expression* ParsePostfixExpression(void); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index c5467f1..923167c 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -152,6 +152,7 @@ const char* TokenNames[] = "'namespace'", "'using'", + "'this'", "'::'" }; @@ -1391,6 +1392,8 @@ void Scanner::NextRawToken(void) mToken = TK_NAMESPACE; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "using")) mToken = TK_USING; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "this")) + mToken = TK_THIS; else { mToken = TK_IDENT; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index b150d14..08a4992 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -151,6 +151,7 @@ enum Token TK_NAMESPACE, TK_USING, + TK_THIS, TK_COLCOLON, NUM_TOKENS