From af38f64a9935a273da3f827d28c1ba5f0ca786c4 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Sat, 25 May 2024 21:25:02 +0200 Subject: [PATCH] Add opp::function --- autotest/autotest.bat | 3 + autotest/opp_functional.cpp | 46 ++++ include/opp/functional.h | 88 ++++++++ oscar64/Declaration.cpp | 104 +++++++-- oscar64/Declaration.h | 1 + oscar64/InterCodeGenerator.cpp | 2 +- oscar64/NativeCodeGenerator.cpp | 2 +- oscar64/Parser.cpp | 367 ++++++++++++++++++++----------- oscar64/Parser.h | 7 +- oscar64setup/oscar64setup.vdproj | 28 ++- 10 files changed, 499 insertions(+), 149 deletions(-) create mode 100644 autotest/opp_functional.cpp create mode 100644 include/opp/functional.h diff --git a/autotest/autotest.bat b/autotest/autotest.bat index fd73e6d..29d507f 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -27,6 +27,9 @@ rem @echo off @call :testh opp_list.cpp @if %errorlevel% neq 0 goto :error +@call :testh opp_functional.cpp +@if %errorlevel% neq 0 goto :error + @call :testh operatoroverload.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_functional.cpp b/autotest/opp_functional.cpp new file mode 100644 index 0000000..497e69e --- /dev/null +++ b/autotest/opp_functional.cpp @@ -0,0 +1,46 @@ +#include + +class Node +{ +public: + virtual int eval(void) const = 0; +}; + +class ConstNode : public Node +{ +private: + int v; +public: + ConstNode(int v_) : v(v_) {} + virtual int eval(void) const + { + return v; + } +}; + +class BinaryNode : public Node +{ +private: + opp::function op; + Node * left, * right; +public: + BinaryNode(opp::function op_, Node * left_, Node * right_); + + virtual int eval(void) const + { + return op(left->eval(), right->eval()); + } +}; + +inline BinaryNode::BinaryNode(opp::function op_, Node * left_, Node * right_) + : op(op_), left(left_), right(right_) {} + +int main(void) +{ + Node * s1 = + new BinaryNode([=](int a, int b){return a + b;}, + new ConstNode(7), new ConstNode(11) + ); + + return s1->eval() - 18; +} diff --git a/include/opp/functional.h b/include/opp/functional.h new file mode 100644 index 0000000..96807c2 --- /dev/null +++ b/include/opp/functional.h @@ -0,0 +1,88 @@ +#ifndef OPP_FUNCTIONAL_H +#define OPP_FUNCTIONAL_H + +namespace opp +{ +template +class function; + +template +class function +{ +private: + struct callif + { + virtual R call(P...) = 0; + virtual ~callif() {} + virtual callif * clone(void) const = 0; + }; + + template + struct callable : callif + { + CA ca; + + callable(CA ca_) : ca(ca_) {} + + R call(P... p) {return ca(p...);} + + callif * clone(void) const + { + return new callable(ca); + } + }; + + callif * c; +public: + template + function(F f) + { + c = new callable(f); + } + + function(const function & f) + { + c = f.c->clone(); + } +#if 0 + function(function && f) + { + c = f.c; + f.c = nullptr; + } + + function & operator=(const function & f) + { + if (c != f.c) + { + delete c; + c = f.c; + } + return *this; + } + + function & operator=(function && f) + { + if (c != f.c) + { + c = f.c; + f.c = nullptr; + } + return *this; + } +#endif + ~function(void) + { + delete c; + } + + R operator()(P ... p) const + { + return c->call(p...); + } +}; + + +} + +#endif diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index bf87705..7cff5d9 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -206,7 +206,10 @@ void Expression::Dump(int ident) const printf("INDEX"); break; case EX_QUALIFY: - printf("QUALIFY<%s>", mDecValue->mIdent->mString); + if (mDecValue->mIdent) + printf("QUALIFY<%s>", mDecValue->mIdent->mString); + else + printf("QUALIFY<%d>", mDecValue->mOffset); break; case EX_CALL: printf("CALL"); @@ -1463,22 +1466,27 @@ const Ident* Declaration::MangleIdent(void) else if (mType == DT_PACK_TYPE) { Declaration* dec = mParams; - while (dec) + if (dec) { - const Ident* id = dec->MangleIdent(); - - if (id) + while (dec) { - if (mMangleIdent) - mMangleIdent = mMangleIdent->Mangle(id->mString); - else - mMangleIdent = id; - } + const Ident* id = dec->MangleIdent(); - dec = dec->mNext; - if (dec) - mMangleIdent = mMangleIdent->Mangle(","); + if (id) + { + if (mMangleIdent) + mMangleIdent = mMangleIdent->Mangle(id->mString); + else + mMangleIdent = id; + } + + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } } + else + mMangleIdent = Ident::Unique("void"); } else mMangleIdent = mQualIdent; @@ -1618,6 +1626,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) else tpdec->mIdent = pdec->mBase->mIdent; tpdec->mParams = phead; + tpdec->mFlags |= DTF_DEFINED; mScope->Insert(tpdec->mIdent, tpdec); } else @@ -1702,14 +1711,44 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) Declaration* fpdec = fdec->mParams; Declaration* tpdec = tdec->mParams; - while (fpdec && tpdec) + while (tpdec) { + if (tpdec->mBase->mType == DT_PACK_TEMPLATE) + { + if (fpdec->mBase->mType == DT_PACK_TEMPLATE) + mScope->Insert(tdec->mIdent, fpdec); + else + { + Declaration* ptdec = new Declaration(fdec->mLocation, DT_PACK_TYPE); + Declaration* ppdec = nullptr; + while (fpdec) + { + Declaration* pdec = fpdec->mBase->Clone(); + if (ppdec) + ppdec->mNext = pdec; + else + ptdec->mParams = pdec; + ppdec = pdec; + fpdec = fpdec->mNext; + } + + ptdec->mFlags |= DTF_DEFINED; + mScope->Insert(tpdec->mBase->mIdent, ptdec); + } + + return true; + } + + if (!fpdec) + return false; + if (!ResolveTemplate(fpdec->mBase, tpdec->mBase)) return false; + fpdec = fpdec->mNext; tpdec = tpdec->mNext; } - if (fpdec || tpdec) + if (fpdec) return false; } else @@ -1758,6 +1797,39 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) } else if (tdec->mType == DT_PACK_TEMPLATE) { + Declaration* pdec; + if (tdec->mBase) + { + pdec = mScope->Lookup(tdec->mBase->mIdent); + if (!pdec) + return false; + } + else if (fdec->mType == DT_PACK_TYPE) + { + mScope->Insert(tdec->mIdent, fdec); + } + else + { + pdec = mScope->Lookup(tdec->mIdent); + if (!pdec) + { + pdec = new Declaration(fdec->mLocation, DT_PACK_TYPE); + mScope->Insert(tdec->mIdent, pdec); + } + + if (!pdec->mParams) + { + pdec->mParams = fdec->Clone(); + } + else + { + Declaration* ppdec = pdec->mParams; + while (ppdec->mNext) + ppdec = ppdec->mNext; + ppdec->mNext = fdec->Clone(); + } + } + return true; } else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) @@ -1832,7 +1904,7 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) return false; } else - return tdec->CanAssign(fdec); + return tdec->IsSame(fdec); } diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 473c640..f37ab83 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -47,6 +47,7 @@ enum DecType DT_PACK_VARIABLE, DT_PACK_ARGUMENT, DT_PACK_TYPE, + DT_PACK_ANON, DT_VARIABLE, DT_ARGUMENT, diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 657bab3..6352928 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -305,7 +305,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p return v; } - else if (type->mType == DT_TYPE_STRUCT && type->mBase->IsSubType(v.mType)) + else if (type->mType == DT_TYPE_STRUCT && type->mBase && type->mBase->IsSubType(v.mType)) { v.mType = type; return v; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index caf07d0..be015f1 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -49030,7 +49030,7 @@ void NativeCodeProcedure::Optimize(void) } } - if (step > 4) + if (step > 4 && step != 6) { ResetVisited(); if (mEntryBlock->ShortcutBlockExit()) diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 05abd6b..53e3fd2 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -187,8 +187,22 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio } if (ptempl) + { ptempl->mBase = dec; + if (mScanner->mToken == TK_LESS_THAN) + { + int level = 0; + do { + if (mScanner->mToken == TK_LESS_THAN) + level++; + else if (mScanner->mToken == TK_GREATER_THAN) + level--; + mScanner->NextToken(); + } while (level > 0); + } + } + if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) { mScanner->NextToken(); @@ -286,7 +300,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio } else if (ConsumeTokenIf(TK_TEMPLATE)) { - ParseTemplateDeclaration(pthis); + Declaration * tdec = ParseTemplateDeclaration(pthis); } else { @@ -810,6 +824,20 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl dec = nullptr; } + if (!dec && mThisPointer && !mScope->Lookup(pident, SLEVEL_FUNCTION)) + { + int offset; + uint64 flags; + + if (mThisPointer->mType == DT_ARGUMENT) + dec = MemberLookup(mThisPointer->mBase->mBase, mScanner->mTokenIdent, offset, flags); + else if (mThisPointer->mType == DT_TYPE_POINTER) + dec = MemberLookup(mThisPointer->mBase, mScanner->mTokenIdent, offset, flags); + + if (dec && dec->mTemplate) + dec = ParseTemplateExpansion(dec->mTemplate, nullptr); + } + if (!dec) { dec = mScope->Lookup(pident); @@ -1138,8 +1166,8 @@ Declaration* Parser::ParsePostfixDeclaration(void) } else { - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); - dec = new Declaration(mScanner->mLocation, DT_ANON); + dec = new Declaration(mScanner->mLocation, DT_PACK_ANON); + dec->mIdent = mScanner->mTokenIdent; dec->mBase = nullptr; } } @@ -1254,8 +1282,10 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) } Declaration* bdec = ParseBaseTypeDeclaration(0, true); - Declaration* adec = ParsePostfixDeclaration(); +// if (bdec->mType == DT_PACK_TEMPLATE) +// ConsumeToken(TK_ELLIPSIS); + Declaration* adec = ParsePostfixDeclaration(); adec = ReverseDeclaration(adec, bdec); if (adec->mBase->mType == DT_TYPE_VOID) @@ -1269,7 +1299,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) if (!(adec->mBase->mFlags & DTF_DEFINED) && adec->mBase->mType != DT_TYPE_ARRAY && !adec->mBase->mTemplate) mErrors->Error(adec->mLocation, EERR_UNDEFINED_OBJECT, "Type of argument not defined"); - if (adec->mType == DT_PACK_VARIABLE) + if (adec->mType == DT_PACK_VARIABLE || adec->mType == DT_PACK_ANON) { adec->mType = DT_PACK_ARGUMENT; if (adec->mBase) @@ -3631,6 +3661,10 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) pex->mDecValue = nullptr; pex->mDecType = vdec->mBase; } + else if (pex->mType == EX_CONSTRUCT && !pdec->IsReference()) + { + pex->mLeft->mRight = nullptr; + } pdec = pdec->mNext; } @@ -5284,7 +5318,20 @@ Expression* Parser::ParseLambdaExpression(void) return vexp; } -Expression* Parser::ParseSimpleExpression(bool lhs) +Declaration* Parser::ParseTypeID(bool tid, Declaration* bdec) +{ + Declaration * dec = bdec ? bdec : ParseBaseTypeDeclaration(0, true); + + while (ConsumeTokenIf(TK_MUL)) + dec = dec->BuildPointer(mScanner->mLocation); + while (ConsumeTokenIf(TK_BINARY_AND)) + dec = dec->BuildReference(mScanner->mLocation); + if (tid && mScanner->mToken == TK_OPEN_PARENTHESIS) + dec = ParseFunctionDeclaration(dec); + return dec; +} + +Expression* Parser::ParseSimpleExpression(bool lhs, bool tid) { Declaration* dec = nullptr; Expression* exp = nullptr, * rexp = nullptr; @@ -5302,32 +5349,14 @@ Expression* Parser::ParseSimpleExpression(bool lhs) case TK_VOID: case TK_UNSIGNED: case TK_SIGNED: - if (lhs) - exp = ParseDeclarationExpression(nullptr); - else - { - 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: if (lhs) exp = ParseDeclarationExpression(nullptr); else { - mScanner->NextToken(); exp = new Expression(mScanner->mLocation, EX_TYPE); exp->mDecValue = nullptr; - exp->mDecType = ParseBaseTypeDeclaration(DTF_CONST, true); - while (ConsumeTokenIf(TK_MUL)) - exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation); - while (ConsumeTokenIf(TK_BINARY_AND)) - exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); + exp->mDecType = ParseTypeID(tid); } break; @@ -5677,11 +5706,7 @@ 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); + exp->mDecType = ParseTypeID(tid, dec); } } else if (dec->mType == DT_CONST_TEMPLATE) @@ -6069,6 +6094,20 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) { if (fdec->mTemplate) { + // this is a constructor, so avoid instantiating a single parameter with the type itself + // as this would only lead to misery and pain and a crashing recursion + if (fdec->mIdent->mString[0] == '+') + { + if (fdec->mBase->mParams && fdec->mBase->mParams->mNext && !fdec->mBase->mParams->mNext->mNext && + fdec->mBase->mParams->mNext->mBase->mType == DT_TYPE_TEMPLATE && + fdec->mBase->mParams->mBase->mBase) + { + if (pexp->mRight && pexp->mRight->mDecType->IsConstSame(fdec->mBase->mParams->mBase->mBase)) + return NOOVERLOAD; + printf("oopsie"); + } + } + Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); if (!tdec->CanResolveTemplate(pexp, fdec)) @@ -6309,7 +6348,8 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr; if (fcons) { - while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec))) + while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && + (fcons->mBase->mParams->mNext->mBase->mType == DT_TYPE_TEMPLATE || fcons->mBase->mParams->mNext->mBase->CanAssign(tdec)))) fcons = fcons->mNext; if (fcons) @@ -6374,10 +6414,12 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr; if (fcons) { +#if 0 while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec))) fcons = fcons->mNext; if (fcons) +#endif { Declaration* vdec = AllocTempVar(type->ToMutableType()); #if 0 @@ -6399,7 +6441,6 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); fexp->mLeft = cexp; - fexp->mRight = exp; Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); @@ -6415,6 +6456,8 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type) lexp->mRight = fexp->mRight; fexp->mRight = lexp; + fexp = ResolveOverloadCall(fexp); + Expression* dexp = nullptr; if (type->mDestructor) { @@ -6558,7 +6601,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) fdec = exp->mLeft->mDecValue; while (fdec) { - int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); + int d = OverloadDistance(fdec, exp->mRight); fdec = fdec->mNext; } #endif @@ -6568,6 +6611,8 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call", exp->mLeft->mDecValue->mQualIdent); else { + assert(dbest); + exp->mLeft->mDecValue = dbest; exp->mLeft->mDecType = dbest->mBase; exp->mDecType = dbest->mBase->mBase; @@ -6838,9 +6883,13 @@ Expression* Parser::ParsePostfixExpression(bool lhs) } nexp = ResolveOverloadCall(nexp); - nexp->mDecType = exp->mDecType->mBase; + Declaration* fdec = nexp->mLeft->mDecType; + if (fdec->mType == DT_TYPE_POINTER) + fdec = fdec->mBase; - if (nexp->mLeft->mDecType->mFlags & DTF_VIRTUAL) + nexp->mDecType = fdec->mBase; + + if (fdec->mFlags & DTF_VIRTUAL) { if (parentCall) exp->mDecType->mFlags |= DTF_STACKCALL; @@ -9372,7 +9421,7 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } -int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) +int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec, Declaration* xtdec) { Declaration* ptdec = tdec->mParams; Declaration* psdec = spec->mParams; @@ -9387,19 +9436,32 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) { if (ptdec->mBase) { - if (ptdec->mBase->mInteger != psdec->mBase->mInteger) - return NOOVERLOAD; + if (ptdec->mBase->mType == DT_CONST_INTEGER) + { + if (ptdec->mBase->mInteger != psdec->mBase->mInteger) + return NOOVERLOAD; + } + else if (ptdec->mBase->mType == DT_CONST_TEMPLATE) + { + Declaration* pdec = xtdec->mScope->Insert(ptdec->mBase->mIdent, psdec->mBase); + cost += 100; + } } else + { + Declaration* pdec = xtdec->mScope->Insert(ptdec->mIdent, psdec->mBase); cost += 100; + } } else if (ptdec->mType == DT_TYPE_TEMPLATE && psdec->mType == DT_TYPE_TEMPLATE) { if (ptdec->mBase) { - if (!ptdec->mBase->IsSame(psdec->mBase)) + if (!xtdec->ResolveTemplate(psdec->mBase, ptdec->mBase)) return NOOVERLOAD; } + else if (!xtdec->ResolveTemplate(psdec->mBase, ptdec)) + return NOOVERLOAD; else cost += 100; } @@ -9422,6 +9484,9 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) } else if (psdec->mBase) { + if (!xtdec->ResolveTemplate(psdec->mBase, ptdec)) + return NOOVERLOAD; + Declaration* dec = psdec->mBase->mParams; while (dec) { @@ -9437,6 +9502,14 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) ptdec = ptdec->mBase->mParams; continue; } + else if (psdec->mBase) + { + if (!xtdec->ResolveTemplate(psdec->mBase, ptdec)) + return NOOVERLOAD; + psdec = psdec->mNext; + cost += 200; + continue; + } else { while (psdec) @@ -9471,6 +9544,93 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) return cost; } +void Parser::ParseTemplateArguments(Declaration* tmpld, Declaration* tdec) +{ + ConsumeToken(TK_LESS_THAN); + + Declaration* tparm = tmpld->mParams; + Declaration* ppdec = nullptr; + + if (!ConsumeTokenIf(TK_GREATER_THAN)) + { + do + { + Expression* exp; + + if (tparm && tparm->mType == DT_TYPE_TEMPLATE) + exp = ParseSimpleExpression(false, true); + else + exp = ParseShiftExpression(false); + + Declaration* pdec = nullptr; + + if (exp->mType == EX_TYPE) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = exp->mDecType; + } + else if (exp->mType == EX_PACK_TYPE) + { + ConsumeToken(TK_ELLIPSIS); + + if (exp->mDecType->mType == DT_PACK_TYPE) + { + Declaration* ptdec = exp->mDecType->mParams; + while (ptdec) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = ptdec; + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; + } + + ptdec = ptdec->mNext; + } + continue; + } + else + { + pdec = new Declaration(exp->mLocation, DT_PACK_TEMPLATE); + pdec->mBase = exp->mDecType; + } + } + else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION) + { + pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); + pdec->mBase = exp->mDecValue; + } + else if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) + { + pdec = new Declaration(exp->mLocation, DT_CONST_TEMPLATE); + pdec->mBase = exp->mDecValue; + } + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Template specification expected"); + + if (pdec) + { + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; + } + + if (tparm) + tparm = tparm->mNext; + + } while (ConsumeTokenIf(TK_COMMA)); + + ConsumeToken(TK_GREATER_THAN); + } +} + Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) { Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); @@ -9512,79 +9672,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } else { - ConsumeToken(TK_LESS_THAN); - - Declaration* ppdec = nullptr; - - if (!ConsumeTokenIf(TK_GREATER_THAN)) - { - do - { - Expression* exp = ParseShiftExpression(false); - Declaration* pdec = nullptr; - - if (exp->mType == EX_TYPE) - { - pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); - pdec->mBase = exp->mDecType; - } - else if (exp->mType == EX_PACK_TYPE) - { - ConsumeToken(TK_ELLIPSIS); - - if (exp->mDecType->mType == DT_PACK_TYPE) - { - Declaration* ptdec = exp->mDecType->mParams; - while (ptdec) - { - pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); - pdec->mBase = ptdec; - - if (pdec) - { - if (ppdec) - ppdec->mNext = pdec; - else - tdec->mParams = pdec; - ppdec = pdec; - } - - ptdec = ptdec->mNext; - } - continue; - } - else - { - pdec = new Declaration(exp->mLocation, DT_PACK_TEMPLATE); - pdec->mBase = exp->mDecType; - } - } - else if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_FUNCTION) - { - pdec = new Declaration(exp->mLocation, DT_TYPE_TEMPLATE); - pdec->mBase = exp->mDecValue; - } - else if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) - { - pdec = new Declaration(exp->mLocation, DT_CONST_TEMPLATE); - pdec->mBase = exp->mDecValue; - } - else - mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Template specification expected"); - - if (pdec) - { - if (ppdec) - ppdec->mNext = pdec; - else - tdec->mParams = pdec; - ppdec = pdec; - } - - } while (ConsumeTokenIf(TK_COMMA)); - - ConsumeToken(TK_GREATER_THAN); - } + ParseTemplateArguments(tmpld, tdec); } while (!tmpld->mTokens) @@ -9616,11 +9704,16 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp Declaration* etdec = nullptr; Declaration* dec = tmpld; + Declaration* mxtdec = nullptr; while (dec) { - int dist = ExpansionDistance(dec, tdec); + Declaration* xtdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + xtdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + + int dist = ExpansionDistance(dec, tdec, xtdec); if (dist < mindist) { + mxtdec = xtdec; mindist = dist; etdec = dec; } @@ -9635,22 +9728,17 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tmpld = etdec; dec = tdec->mParams; - Declaration * pdec = tmpld->mParams; + Declaration * pdec = tmpld->mBase->mTemplate->mParams; Declaration * ppdec = nullptr; while (pdec) { + Declaration* rdec = mxtdec->mScope->Lookup(pdec->mIdent); if (pdec->mType == DT_PACK_TEMPLATE) { - if (!dec) + if (!rdec) { - Declaration* packd = new Declaration(tdec->mLocation, DT_PACK_TEMPLATE); - packd->mBase = new Declaration(tdec->mLocation, DT_PACK_TYPE); - if (ppdec) - ppdec->mNext = packd; - else - tdec->mParams = packd; - dec = packd; + rdec = new Declaration(tdec->mLocation, DT_PACK_TYPE); } else if (dec->mType != DT_PACK_TEMPLATE) { @@ -9678,13 +9766,10 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } } - if (dec) + if (rdec) { - dec->mIdent = pdec->mIdent; - tdec->mScope->Insert(dec->mIdent, dec->mBase); - - ppdec = dec; - dec = dec->mNext; +// rdec->mIdent = pdec->mIdent; + tdec->mScope->Insert(pdec->mIdent, rdec); } pdec = pdec->mNext; @@ -9871,7 +9956,19 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tpthis = tmpld->mClass; else if (expd && expd->mBase) tpthis = expd->mBase->BuildConstPointer(tdec->mLocation); +#if 0 + if (tpthis) + { + DeclarationScope* oscope = p->mScope; + tpthis->mBase->mScope->mParent = p->mScope; + p->mScope = tpthis->mBase->mScope; + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tpthis, tdec); + + p->mScope = oscope; + } + else +#endif tdec->mBase = p->ParseDeclaration(nullptr, true, false, tpthis, tdec); } @@ -10153,6 +10250,20 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi bdec->mQualIdent = mScope->Mangle(mScanner->mTokenIdent); bdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, bdec->mQualIdent); + mScanner->NextToken(); + if (mScanner->mToken == TK_LESS_THAN) + { + Declaration* ptdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + ptdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + + mTemplateScope = tdec->mScope; + ParseTemplateArguments(tdec, ptdec); + + ptdec->mBase = bdec; + ptdec->mParser = tdec->mParser; + tdec = ptdec; + } + while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE) mScanner->NextToken(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b20e19e..3a50cce 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -111,7 +111,8 @@ protected: void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); - int ExpansionDistance(Declaration* tdec, Declaration* spec); + int ExpansionDistance(Declaration* tdec, Declaration* spec, Declaration* xtdec); + void ParseTemplateArguments(Declaration* tmpld, Declaration* tdec); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); void CompleteTemplateExpansion(Declaration* tmpld); @@ -124,7 +125,9 @@ protected: Expression* ExpandPackExpression(Expression* exp, Expression* pack, Expression* item); Expression* ParseBinaryFoldExpression(Expression * exp); - Expression* ParseSimpleExpression(bool lhs); + Declaration* ParseTypeID(bool tid, Declaration * bdec = nullptr); + + Expression* ParseSimpleExpression(bool lhs, bool tid = false); Expression* ParsePrefixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs); Expression* ParseMulExpression(bool lhs); diff --git a/oscar64setup/oscar64setup.vdproj b/oscar64setup/oscar64setup.vdproj index be67ac8..f889e68 100644 --- a/oscar64setup/oscar64setup.vdproj +++ b/oscar64setup/oscar64setup.vdproj @@ -130,6 +130,12 @@ } "Entry" { + "MsmKey" = "8:_1328E18B9638422795616BABEAAFA600" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { "MsmKey" = "8:_1393003825B9451084DB314DD4267AD5" "OwnerKey" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED" @@ -1801,6 +1807,26 @@ "IsDependency" = "11:FALSE" "IsolateTo" = "8:" } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1328E18B9638422795616BABEAAFA600" + { + "SourcePath" = "8:..\\include\\opp\\functional.h" + "TargetName" = "8:functional.h" + "Tag" = "8:" + "Folder" = "8:_D76A1802AFD04C48A519C9F8700E53CC" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1393003825B9451084DB314DD4267AD5" { "SourcePath" = "8:..\\samples\\memmap\\allmem.c" @@ -6676,7 +6702,7 @@ { "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6" { - "SourcePath" = "8:..\\Releasex64\\oscar64.exe" + "SourcePath" = "8:..\\Debugx64\\oscar64.exe" "TargetName" = "8:" "Tag" = "8:" "Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"