Add template algorithm sort

This commit is contained in:
drmortalwombat 2023-08-15 11:05:52 +02:00
parent ae2fbb6256
commit 50cc2afb52
11 changed files with 215 additions and 24 deletions

37
include/opp/algorithm.h Normal file
View File

@ -0,0 +1,37 @@
#ifndef OPP_ALGORITHM_H
#define OPP_ALGORITHM_H
template <class T>
inline void swap(T & x, T & y)
{
T t(x); x = y; y = t;
}
template<class T, class LT>
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<T, LT>(s, p);
p++;
s = p;
}
}
#endif

View File

@ -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)
{}

View File

@ -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

View File

@ -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];

View File

@ -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;
}

View File

@ -272,7 +272,7 @@ public:
TokenSequence * mTokens;
Parser * mParser;
GrowingArray<Declaration*> mCallers, mCalled;
GrowingArray<Declaration*> mCallers, mCalled, mFriends;
bool CanAssign(const Declaration* fromType) const;
bool IsSame(const Declaration* dec) const;

View File

@ -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");

View File

@ -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 (ptempl)
ptempl->mBase = ndec;
if (ptempl && mTemplateScope && ndec->mIdent)
{
if (ConsumeTokenIf(TK_CONST))
PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildConstPointer(ndec->mLocation));
else
PrependThisArgument(ndec->mBase, pthis);
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();

View File

@ -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);

View File

@ -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();

View File

@ -162,6 +162,7 @@ enum Token
TK_VIRTUAL,
TK_OPERATOR,
TK_TEMPLATE,
TK_FRIEND,
NUM_TOKENS
};