From 50cc2afb52157c7be4dd8b2d900d9b38a1c0566b Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Tue, 15 Aug 2023 11:05:52 +0200 Subject: [PATCH] Add template algorithm sort --- include/opp/algorithm.h | 37 ++++++++++++ include/opp/string.cpp | 5 ++ include/opp/string.h | 4 ++ include/opp/vector.h | 30 ++++++++++ oscar64/Declaration.cpp | 26 ++++++++- oscar64/Declaration.h | 2 +- oscar64/InterCodeGenerator.cpp | 24 ++++++++ oscar64/Parser.cpp | 103 +++++++++++++++++++++++++++------ oscar64/Parser.h | 4 +- oscar64/Scanner.cpp | 3 + oscar64/Scanner.h | 1 + 11 files changed, 215 insertions(+), 24 deletions(-) create mode 100644 include/opp/algorithm.h diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h new file mode 100644 index 0000000..b5586b2 --- /dev/null +++ b/include/opp/algorithm.h @@ -0,0 +1,37 @@ +#ifndef OPP_ALGORITHM_H +#define OPP_ALGORITHM_H + +template +inline void swap(T & x, T & y) +{ + T t(x); x = y; y = t; +} + +template +void sort(T s, T e) +{ + while (s != e) + { + auto p = s; + auto q = s; + + q++; + while (q != e) + { + if (LT(*q, *p)) + { + swap(*q, *p); + p++; + swap(*q, *p); + } + q++; + } + + sort(s, p); + p++; + s = p; + } +} + + +#endif diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 0c5821d..a8476dd 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -16,6 +16,11 @@ static inline char sstrlen(const char * sp) return n; } +inline void swap(string & u, string & v) +{ + char * p = u.cstr; u.cstr = v.cstr; v.cstr = p; +} + string::string(void) : cstr(nullptr) {} diff --git a/include/opp/string.h b/include/opp/string.h index 856edf6..bcf58cd 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -6,6 +6,8 @@ class string private: char * cstr; + friend void swap(string & u, string & v); + public: string(void); string(const string & s); @@ -70,6 +72,8 @@ protected: string(char l, char * b); }; +void swap(string & u, string & v); + #pragma compile("string.cpp") #endif diff --git a/include/opp/vector.h b/include/opp/vector.h index 98f9e12..f5fbdde 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -70,6 +70,36 @@ public: return _data[at]; } + T * begin(void) + { + return _data; + } + + const T * begin(void) const + { + return _data; + } + + const T * cbegin(void) const + { + return _data; + } + + T * end(void) + { + return _data + _size; + } + + const T * end(void) const + { + return _data + _size; + } + + const T * cend(void) const + { + return _data + _size; + } + T & front(void) { return _data[0]; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 36a0980..255de13 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -842,7 +842,7 @@ Declaration::Declaration(const Location& loc, DecType type) mDefaultConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr), mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(nullptr), mVTable(nullptr), mTemplate(nullptr), - mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), + mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mFriends(nullptr), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) {} @@ -947,6 +947,10 @@ const Ident* Declaration::MangleIdent(void) sprintf_s(buffer, "%d", (int)mInteger); mMangleIdent = Ident::Unique(buffer); } + else if (mType == DT_CONST_FUNCTION) + { + mMangleIdent = mQualIdent; + } else if (mType == DT_TYPE_INTEGER) { char buffer[20]; @@ -1532,7 +1536,7 @@ bool Declaration::IsTemplateSameParams(const Declaration* dec, const Declaration bool Declaration::IsSameParams(const Declaration* dec) const { - if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) { Declaration* ld = mParams, * rd = dec->mParams; while (ld && rd) @@ -1545,6 +1549,24 @@ bool Declaration::IsSameParams(const Declaration* dec) const return !ld && !rd; } + else if (mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) + { + Declaration* ld = mParams, * rd = dec->mParams; + while (ld && rd) + { + if (ld->mType == DT_CONST_FUNCTION && rd->mType == DT_CONST_FUNCTION) + { + if (ld->mValue != rd->mValue) + return false; + } + else if (!ld->mBase->IsSame(rd->mBase)) + return false; + ld = ld->mNext; + rd = rd->mNext; + } + + return !ld && !rd; + } else return false; } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index d26e15d..084d7df 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -272,7 +272,7 @@ public: TokenSequence * mTokens; Parser * mParser; - GrowingArray mCallers, mCalled; + GrowingArray mCallers, mCalled, mFriends; bool CanAssign(const Declaration* fromType) const; bool IsSame(const Declaration* dec) const; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 1af651e..2b674f2 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -162,6 +162,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p { mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign numeric value to pointer"); } + else if( type->mType == DT_TYPE_BOOL && v.mType->mType == DT_TYPE_POINTER) + { + InterInstruction* zins = new InterInstruction(exp->mLocation, IC_CONSTANT); + zins->mDst.mType = IT_POINTER; + zins->mDst.mTemp = proc->AddTemporary(IT_POINTER); + zins->mConst.mType = IT_POINTER; + zins->mConst.mMemory = IM_ABSOLUTE; + zins->mConst.mIntConst = 0; + block->Append(zins); + + InterInstruction* cins = new InterInstruction(exp->mLocation, IC_RELATIONAL_OPERATOR); + cins->mOperator = IA_CMPNE; + cins->mSrc[0].mType = IT_POINTER; + cins->mSrc[0].mTemp = v.mTemp; + cins->mSrc[1].mType = IT_POINTER; + cins->mSrc[1].mTemp = zins->mDst.mTemp; + cins->mDst.mType = IT_BOOL; + cins->mDst.mTemp = proc->AddTemporary(IT_BOOL); + block->Append(cins); + v.mTemp = cins->mDst.mTemp; + v.mType = type; + } else if (v.mType->mSize < type->mSize) { if (v.mType->mSize == 1 && type->mSize == 2) @@ -3697,6 +3719,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (!procType->mBase || procType->mBase->mType == DT_TYPE_VOID) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Function has void return type"); + else if (procType->mBase->mType == DT_TYPE_BOOL && (vr.mType->IsIntegerType() || vr.mType->mType == DT_TYPE_POINTER)) + ; else if (!procType->mBase->CanAssign(vr.mType)) mErrors->Error(exp->mLocation, EERR_INVALID_RETURN, "Cannot return incompatible type"); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 6c4686e..3b94c1d 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -19,6 +19,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn mInlineCall = false; mCompilerOptionSP = 0; mThisPointer = nullptr; + mFunction = nullptr; for (int i = 0; i < 256; i++) mCharMap[i] = i; @@ -248,6 +249,13 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) flags |= DTF_PRIVATE | DTF_PROTECTED; ConsumeToken(TK_COLON); } + else if (ConsumeTokenIf(TK_FRIEND)) + { + mScope = oscope; + Declaration* fdec = ParseDeclaration(nullptr, true, false); + dec->mFriends.Push(fdec); + mScope = dec->mScope; + } else if (ConsumeTokenIf(TK_CLOSE_BRACE)) { break; @@ -3210,7 +3218,7 @@ void Parser::ParseVariableInit(Declaration* ndec) mErrors->Error(pexp->mLocation, EERR_INCOMPATIBLE_TYPES, "Can not initialize variable with expression", ndec->mIdent); } -Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis) +Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool expression, Declaration* pthis, Declaration* ptempl) { bool definingType = false, destructor = false; uint64 storageFlags = 0, typeFlags = 0; @@ -3734,14 +3742,30 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } else { - if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) - { - if (ConsumeTokenIf(TK_CONST)) - PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); - else - PrependThisArgument(ndec->mBase, pthis); + if (ptempl) + ptempl->mBase = ndec; + + if (ptempl && mTemplateScope && ndec->mIdent) + { + if (!strstr(ndec->mQualIdent->mString, mTemplateScope->mName->mString)) + { + ndec->mIdent = ndec->mIdent->Mangle(mTemplateScope->mName->mString); + ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); + } } + if (ndec->mBase->mType == DT_TYPE_FUNCTION) + { + if (pthis) + { + if (ConsumeTokenIf(TK_CONST)) + PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation)); + else + PrependThisArgument(ndec->mBase, pthis); + } + } + + if (variable) { ndec->mFlags |= storageFlags; @@ -3776,11 +3800,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mIdent == ndec->mQualIdent) { Declaration* ldec = mScope->Insert(ndec->mIdent, pdec ? pdec : ndec); +#if 0 if (ldec && ldec->mTemplate && mTemplateScope) { ndec->mQualIdent = ndec->mQualIdent->Mangle(mTemplateScope->mName->mString); } - else if (ldec && ldec != pdec) + else +#endif + + if (ldec && ldec != pdec) mErrors->Error(ndec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate definition"); } else if (!pdec) @@ -4085,14 +4113,16 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ndec->mBase->mType == DT_TYPE_FUNCTION) { if (ndec->mFlags & DTF_DEFINED) - mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition"); + mErrors->Error(mScanner->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate function definition", ndec->mQualIdent); ndec->mCompilerOptions = mCompilerOptions; ndec->mBase->mCompilerOptions = mCompilerOptions; ndec->mVarIndex = -1; + mFunction = ndec; ndec->mValue = ParseFunction(ndec->mBase); + mFunction = nullptr; if (pthis) ndec->mFlags |= DTF_REQUEST_INLINE; @@ -4309,6 +4339,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; exp->mDecType = ParseBaseTypeDeclaration(0, true); + while (ConsumeTokenIf(TK_MUL)) + exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } break; case TK_CONST: @@ -4555,6 +4589,10 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; exp->mDecType = dec; + while (ConsumeTokenIf(TK_MUL)) + exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } } else if (dec->mType == DT_ELEMENT) @@ -4737,7 +4775,12 @@ Expression* Parser::ParseQualify(Expression* exp) if (tp && tp->mType == DT_ARGUMENT) tp = tp->mBase; if (!(tp && tp->mBase->IsConstSame(dtype))) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); + { + if (dtype->mFriends.Contains(mFunction)) + ; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not visible", ident); + } } mScanner->NextToken(); @@ -4952,7 +4995,13 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else if (ptype->IsSame(ex->mDecType)) ; else if (CanCoerceExpression(ex, ptype)) + { dist += 512; + if (ptype->mType == DT_TYPE_REFERENCE) + dist += 4; + else if (ptype->mType == DT_TYPE_RVALUEREF) + dist += 2; + } else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->mType == DT_TYPE_STRUCT && etype->mType == DT_TYPE_STRUCT) { if (ex->IsLValue()) @@ -5247,7 +5296,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec) { int d = OverloadDistance(fdec, exp->mRight); - if (d < ibest) + if (d == NOOVERLOAD) + ; + else if (d < ibest) { dbest = fdec; pbest = exp->mRight; @@ -5262,7 +5313,9 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) while (fdec2) { int d = OverloadDistance(fdec2, exp2->mRight); - if (d < ibest) + if (d == NOOVERLOAD) + ; + else if (d < ibest) { dbest = fdec2; pbest = exp2->mRight; @@ -6244,6 +6297,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (exp->mType == EX_ASSIGNMENT) { Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { const Ident* opident = nullptr; @@ -6320,7 +6376,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); @@ -7138,7 +7194,10 @@ Expression* Parser::ParseStatement(void) exp = new Expression(mScanner->mLocation, EX_RETURN); if (mScanner->mToken != TK_SEMICOLON) { - exp->mLeft = CleanupExpression(ParseRExpression()); + exp->mLeft = ParseRExpression(); + if (mReturnType) + exp->mLeft = CoerceExpression(exp->mLeft, mReturnType); + exp->mLeft = CleanupExpression(exp->mLeft); if (exp->mLeft->mType == EX_CONSTRUCT && mReturnType && mReturnType->mType == DT_TYPE_STRUCT) { Expression* cexp = exp->mLeft->mLeft->mLeft; @@ -7325,8 +7384,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp { if (exp->mType == EX_TYPE) epdec->mBase = exp->mDecType; + else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION) + epdec->mBase = exp->mDecValue; else + { mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent); + epdec->mBase = TheVoidTypeDeclaration; + } } else { @@ -7367,14 +7431,13 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp p->mScanner->Replay(tmpld->mTokens); tdec->mScope->mName = tdec->MangleIdent(); - - p->mTemplateScope = tdec->mScope; - tdec->mBase = p->ParseDeclaration(nullptr, true, false); - p->mTemplateScope = nullptr; - tdec->mNext = tmpld->mNext; tmpld->mNext = tdec; + p->mTemplateScope = tdec->mScope; + tdec->mBase = p->ParseDeclaration(nullptr, true, false, nullptr, tdec); + p->mTemplateScope = nullptr; + if (tdec->mBase->mType == DT_ANON) { tdec->mBase = tdec->mBase->mBase; @@ -7533,6 +7596,8 @@ void Parser::ParseTemplateDeclaration(void) // Function template mTemplateScope = tdec->mScope; + ConsumeTokenIf(TK_INLINE); + Declaration* bdec = ParseBaseTypeDeclaration(0, false); Declaration* adec = ParsePostfixDeclaration(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 892c52b..2eb21bc 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -15,7 +15,7 @@ public: DeclarationScope * mGlobals, * mScope, * mTemplateScope; int mLocalIndex; CompilationUnits * mCompilationUnits; - Declaration * mThisPointer, * mReturnType; + Declaration * mThisPointer, * mReturnType, * mFunction; LinkerSection * mCodeSection, * mDataSection, * mBSSection; @@ -58,7 +58,7 @@ protected: Expression* CleanupExpression(Expression* exp); Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); - Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr); + Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr, Declaration * ptempl = nullptr); Declaration* ParseStructDeclaration(uint64 flags, DecType dt); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 88e63f8..4514311 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -163,6 +163,7 @@ const char* TokenNames[] = "'virtual'", "'operator'", "'template'", + "'friend'", }; @@ -1511,6 +1512,8 @@ void Scanner::NextRawToken(void) mToken = TK_VIRTUAL; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "template")) mToken = TK_TEMPLATE; + else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "friend")) + mToken = TK_FRIEND; else if ((mCompilerOptions & COPT_CPLUSPLUS) && !strcmp(tkident, "operator")) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 984fcf3..98b5756 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -162,6 +162,7 @@ enum Token TK_VIRTUAL, TK_OPERATOR, TK_TEMPLATE, + TK_FRIEND, NUM_TOKENS };