Add opp::function

This commit is contained in:
drmortalwombat 2024-05-25 21:25:02 +02:00
parent a22dfa6ba7
commit af38f64a99
10 changed files with 499 additions and 149 deletions

View File

@ -27,6 +27,9 @@ rem @echo off
@call :testh opp_list.cpp @call :testh opp_list.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :testh opp_functional.cpp
@if %errorlevel% neq 0 goto :error
@call :testh operatoroverload.cpp @call :testh operatoroverload.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error

View File

@ -0,0 +1,46 @@
#include <opp/functional.h>
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<int(int, int)> op;
Node * left, * right;
public:
BinaryNode(opp::function<int(int, int)> op_, Node * left_, Node * right_);
virtual int eval(void) const
{
return op(left->eval(), right->eval());
}
};
inline BinaryNode::BinaryNode(opp::function<int(int, int)> 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;
}

88
include/opp/functional.h Normal file
View File

@ -0,0 +1,88 @@
#ifndef OPP_FUNCTIONAL_H
#define OPP_FUNCTIONAL_H
namespace opp
{
template <class F>
class function;
template <class R, class ... P>
class function<R(P...)>
{
private:
struct callif
{
virtual R call(P...) = 0;
virtual ~callif() {}
virtual callif * clone(void) const = 0;
};
template<class CA>
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 <class F>
function(F f)
{
c = new callable<F>(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

View File

@ -206,7 +206,10 @@ void Expression::Dump(int ident) const
printf("INDEX"); printf("INDEX");
break; break;
case EX_QUALIFY: case EX_QUALIFY:
if (mDecValue->mIdent)
printf("QUALIFY<%s>", mDecValue->mIdent->mString); printf("QUALIFY<%s>", mDecValue->mIdent->mString);
else
printf("QUALIFY<%d>", mDecValue->mOffset);
break; break;
case EX_CALL: case EX_CALL:
printf("CALL"); printf("CALL");
@ -1463,6 +1466,8 @@ const Ident* Declaration::MangleIdent(void)
else if (mType == DT_PACK_TYPE) else if (mType == DT_PACK_TYPE)
{ {
Declaration* dec = mParams; Declaration* dec = mParams;
if (dec)
{
while (dec) while (dec)
{ {
const Ident* id = dec->MangleIdent(); const Ident* id = dec->MangleIdent();
@ -1480,6 +1485,9 @@ const Ident* Declaration::MangleIdent(void)
mMangleIdent = mMangleIdent->Mangle(","); mMangleIdent = mMangleIdent->Mangle(",");
} }
} }
else
mMangleIdent = Ident::Unique("void");
}
else else
mMangleIdent = mQualIdent; mMangleIdent = mQualIdent;
@ -1618,6 +1626,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec)
else else
tpdec->mIdent = pdec->mBase->mIdent; tpdec->mIdent = pdec->mBase->mIdent;
tpdec->mParams = phead; tpdec->mParams = phead;
tpdec->mFlags |= DTF_DEFINED;
mScope->Insert(tpdec->mIdent, tpdec); mScope->Insert(tpdec->mIdent, tpdec);
} }
else else
@ -1702,14 +1711,44 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
Declaration* fpdec = fdec->mParams; Declaration* fpdec = fdec->mParams;
Declaration* tpdec = tdec->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)) if (!ResolveTemplate(fpdec->mBase, tpdec->mBase))
return false; return false;
fpdec = fpdec->mNext; fpdec = fpdec->mNext;
tpdec = tpdec->mNext; tpdec = tpdec->mNext;
} }
if (fpdec || tpdec) if (fpdec)
return false; return false;
} }
else else
@ -1758,6 +1797,39 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec)
} }
else if (tdec->mType == DT_PACK_TEMPLATE) 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; return true;
} }
else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) 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; return false;
} }
else else
return tdec->CanAssign(fdec); return tdec->IsSame(fdec);
} }

View File

@ -47,6 +47,7 @@ enum DecType
DT_PACK_VARIABLE, DT_PACK_VARIABLE,
DT_PACK_ARGUMENT, DT_PACK_ARGUMENT,
DT_PACK_TYPE, DT_PACK_TYPE,
DT_PACK_ANON,
DT_VARIABLE, DT_VARIABLE,
DT_ARGUMENT, DT_ARGUMENT,

View File

@ -305,7 +305,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::CoerceType(InterCodeProcedure* p
return v; 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; v.mType = type;
return v; return v;

View File

@ -49030,7 +49030,7 @@ void NativeCodeProcedure::Optimize(void)
} }
} }
if (step > 4) if (step > 4 && step != 6)
{ {
ResetVisited(); ResetVisited();
if (mEntryBlock->ShortcutBlockExit()) if (mEntryBlock->ShortcutBlockExit())

View File

@ -187,8 +187,22 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
} }
if (ptempl) if (ptempl)
{
ptempl->mBase = dec; 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) if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON)
{ {
mScanner->NextToken(); mScanner->NextToken();
@ -286,7 +300,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio
} }
else if (ConsumeTokenIf(TK_TEMPLATE)) else if (ConsumeTokenIf(TK_TEMPLATE))
{ {
ParseTemplateDeclaration(pthis); Declaration * tdec = ParseTemplateDeclaration(pthis);
} }
else else
{ {
@ -810,6 +824,20 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl
dec = nullptr; 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) if (!dec)
{ {
dec = mScope->Lookup(pident); dec = mScope->Lookup(pident);
@ -1138,8 +1166,8 @@ Declaration* Parser::ParsePostfixDeclaration(void)
} }
else else
{ {
mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); dec = new Declaration(mScanner->mLocation, DT_PACK_ANON);
dec = new Declaration(mScanner->mLocation, DT_ANON); dec->mIdent = mScanner->mTokenIdent;
dec->mBase = nullptr; dec->mBase = nullptr;
} }
} }
@ -1254,8 +1282,10 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec)
} }
Declaration* bdec = ParseBaseTypeDeclaration(0, true); Declaration* bdec = ParseBaseTypeDeclaration(0, true);
Declaration* adec = ParsePostfixDeclaration(); // if (bdec->mType == DT_PACK_TEMPLATE)
// ConsumeToken(TK_ELLIPSIS);
Declaration* adec = ParsePostfixDeclaration();
adec = ReverseDeclaration(adec, bdec); adec = ReverseDeclaration(adec, bdec);
if (adec->mBase->mType == DT_TYPE_VOID) 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) 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"); 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; adec->mType = DT_PACK_ARGUMENT;
if (adec->mBase) if (adec->mBase)
@ -3631,6 +3661,10 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
pex->mDecValue = nullptr; pex->mDecValue = nullptr;
pex->mDecType = vdec->mBase; pex->mDecType = vdec->mBase;
} }
else if (pex->mType == EX_CONSTRUCT && !pdec->IsReference())
{
pex->mLeft->mRight = nullptr;
}
pdec = pdec->mNext; pdec = pdec->mNext;
} }
@ -5284,7 +5318,20 @@ Expression* Parser::ParseLambdaExpression(void)
return vexp; 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; Declaration* dec = nullptr;
Expression* exp = nullptr, * rexp = nullptr; Expression* exp = nullptr, * rexp = nullptr;
@ -5302,32 +5349,14 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
case TK_VOID: case TK_VOID:
case TK_UNSIGNED: case TK_UNSIGNED:
case TK_SIGNED: 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: case TK_CONST:
if (lhs) if (lhs)
exp = ParseDeclarationExpression(nullptr); exp = ParseDeclarationExpression(nullptr);
else else
{ {
mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_TYPE); exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr; exp->mDecValue = nullptr;
exp->mDecType = ParseBaseTypeDeclaration(DTF_CONST, true); exp->mDecType = ParseTypeID(tid);
while (ConsumeTokenIf(TK_MUL))
exp->mDecType = exp->mDecType->BuildPointer(mScanner->mLocation);
while (ConsumeTokenIf(TK_BINARY_AND))
exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation);
} }
break; break;
@ -5677,11 +5706,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
{ {
exp = new Expression(mScanner->mLocation, EX_TYPE); exp = new Expression(mScanner->mLocation, EX_TYPE);
exp->mDecValue = nullptr; exp->mDecValue = nullptr;
exp->mDecType = dec; exp->mDecType = ParseTypeID(tid, 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_CONST_TEMPLATE) else if (dec->mType == DT_CONST_TEMPLATE)
@ -6069,6 +6094,20 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
{ {
if (fdec->mTemplate) 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); Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
if (!tdec->CanResolveTemplate(pexp, fdec)) 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; Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr;
if (fcons) 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; fcons = fcons->mNext;
if (fcons) if (fcons)
@ -6374,10 +6414,12 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr; Declaration* fcons = type->mScope ? type->mScope->Lookup(type->mIdent->PreMangle("+")) : nullptr;
if (fcons) 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))) while (fcons && !(fcons->mBase->mParams && fcons->mBase->mParams->mNext && !fcons->mBase->mParams->mNext->mNext && fcons->mBase->mParams->mNext->mBase->CanAssign(tdec)))
fcons = fcons->mNext; fcons = fcons->mNext;
if (fcons) if (fcons)
#endif
{ {
Declaration* vdec = AllocTempVar(type->ToMutableType()); Declaration* vdec = AllocTempVar(type->ToMutableType());
#if 0 #if 0
@ -6399,7 +6441,6 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL); Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp; fexp->mLeft = cexp;
fexp->mRight = exp; fexp->mRight = exp;
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX); Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
@ -6415,6 +6456,8 @@ Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
lexp->mRight = fexp->mRight; lexp->mRight = fexp->mRight;
fexp->mRight = lexp; fexp->mRight = lexp;
fexp = ResolveOverloadCall(fexp);
Expression* dexp = nullptr; Expression* dexp = nullptr;
if (type->mDestructor) if (type->mDestructor)
{ {
@ -6558,7 +6601,7 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
fdec = exp->mLeft->mDecValue; fdec = exp->mLeft->mDecValue;
while (fdec) while (fdec)
{ {
int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); int d = OverloadDistance(fdec, exp->mRight);
fdec = fdec->mNext; fdec = fdec->mNext;
} }
#endif #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); mErrors->Error(exp->mLocation, ERRO_AMBIGUOUS_FUNCTION_CALL, "Ambiguous function call", exp->mLeft->mDecValue->mQualIdent);
else else
{ {
assert(dbest);
exp->mLeft->mDecValue = dbest; exp->mLeft->mDecValue = dbest;
exp->mLeft->mDecType = dbest->mBase; exp->mLeft->mDecType = dbest->mBase;
exp->mDecType = dbest->mBase->mBase; exp->mDecType = dbest->mBase->mBase;
@ -6838,9 +6883,13 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
} }
nexp = ResolveOverloadCall(nexp); 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) if (parentCall)
exp->mDecType->mFlags |= DTF_STACKCALL; exp->mDecType->mFlags |= DTF_STACKCALL;
@ -9372,7 +9421,7 @@ Expression* Parser::ParseSwitchStatement(void)
return sexp; return sexp;
} }
int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec, Declaration* xtdec)
{ {
Declaration* ptdec = tdec->mParams; Declaration* ptdec = tdec->mParams;
Declaration* psdec = spec->mParams; Declaration* psdec = spec->mParams;
@ -9386,20 +9435,33 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec)
if (ptdec->mType == DT_CONST_TEMPLATE && psdec->mType == DT_CONST_TEMPLATE) if (ptdec->mType == DT_CONST_TEMPLATE && psdec->mType == DT_CONST_TEMPLATE)
{ {
if (ptdec->mBase) if (ptdec->mBase)
{
if (ptdec->mBase->mType == DT_CONST_INTEGER)
{ {
if (ptdec->mBase->mInteger != psdec->mBase->mInteger) if (ptdec->mBase->mInteger != psdec->mBase->mInteger)
return NOOVERLOAD; return NOOVERLOAD;
} }
else else if (ptdec->mBase->mType == DT_CONST_TEMPLATE)
{
Declaration* pdec = xtdec->mScope->Insert(ptdec->mBase->mIdent, psdec->mBase);
cost += 100; 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) else if (ptdec->mType == DT_TYPE_TEMPLATE && psdec->mType == DT_TYPE_TEMPLATE)
{ {
if (ptdec->mBase) if (ptdec->mBase)
{ {
if (!ptdec->mBase->IsSame(psdec->mBase)) if (!xtdec->ResolveTemplate(psdec->mBase, ptdec->mBase))
return NOOVERLOAD; return NOOVERLOAD;
} }
else if (!xtdec->ResolveTemplate(psdec->mBase, ptdec))
return NOOVERLOAD;
else else
cost += 100; cost += 100;
} }
@ -9422,6 +9484,9 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec)
} }
else if (psdec->mBase) else if (psdec->mBase)
{ {
if (!xtdec->ResolveTemplate(psdec->mBase, ptdec))
return NOOVERLOAD;
Declaration* dec = psdec->mBase->mParams; Declaration* dec = psdec->mBase->mParams;
while (dec) while (dec)
{ {
@ -9437,6 +9502,14 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec)
ptdec = ptdec->mBase->mParams; ptdec = ptdec->mBase->mParams;
continue; continue;
} }
else if (psdec->mBase)
{
if (!xtdec->ResolveTemplate(psdec->mBase, ptdec))
return NOOVERLOAD;
psdec = psdec->mNext;
cost += 200;
continue;
}
else else
{ {
while (psdec) while (psdec)
@ -9471,56 +9544,24 @@ int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec)
return cost; return cost;
} }
Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) void Parser::ParseTemplateArguments(Declaration* tmpld, Declaration* tdec)
{
Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
#if 1
if (expd)
{
if (tmpld->mBase->mType == DT_TEMPLATE)
{
Parser* p = tmpld->mBase->mParser->Clone();
p->mScanner->Replay(tmpld->mBase->mTokens);
tdec = tmpld->mBase->Clone();
tdec->mScope->mName = expd->mScope->mName;
tdec->mScope->mParent = expd->mScope;
p->ParseTemplateDeclarationBody(tdec, nullptr);
return tdec;
}
Declaration* ppdec = nullptr;
Declaration* dec = expd->mParams;
while (dec)
{
Declaration* epdec = dec->Clone();
if (ppdec)
ppdec->mNext = epdec;
else
tdec->mParams = epdec;
ppdec = epdec;
dec = dec->mNext;
}
}
else
{ {
ConsumeToken(TK_LESS_THAN); ConsumeToken(TK_LESS_THAN);
Declaration* tparm = tmpld->mParams;
Declaration* ppdec = nullptr; Declaration* ppdec = nullptr;
if (!ConsumeTokenIf(TK_GREATER_THAN)) if (!ConsumeTokenIf(TK_GREATER_THAN))
{ {
do do
{ {
Expression* exp = ParseShiftExpression(false); Expression* exp;
if (tparm && tparm->mType == DT_TYPE_TEMPLATE)
exp = ParseSimpleExpression(false, true);
else
exp = ParseShiftExpression(false);
Declaration* pdec = nullptr; Declaration* pdec = nullptr;
if (exp->mType == EX_TYPE) if (exp->mType == EX_TYPE)
@ -9581,12 +9622,59 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
ppdec = pdec; ppdec = pdec;
} }
if (tparm)
tparm = tparm->mNext;
} while (ConsumeTokenIf(TK_COMMA)); } while (ConsumeTokenIf(TK_COMMA));
ConsumeToken(TK_GREATER_THAN); ConsumeToken(TK_GREATER_THAN);
} }
} }
Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd)
{
Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
#if 1
if (expd)
{
if (tmpld->mBase->mType == DT_TEMPLATE)
{
Parser* p = tmpld->mBase->mParser->Clone();
p->mScanner->Replay(tmpld->mBase->mTokens);
tdec = tmpld->mBase->Clone();
tdec->mScope->mName = expd->mScope->mName;
tdec->mScope->mParent = expd->mScope;
p->ParseTemplateDeclarationBody(tdec, nullptr);
return tdec;
}
Declaration* ppdec = nullptr;
Declaration* dec = expd->mParams;
while (dec)
{
Declaration* epdec = dec->Clone();
if (ppdec)
ppdec->mNext = epdec;
else
tdec->mParams = epdec;
ppdec = epdec;
dec = dec->mNext;
}
}
else
{
ParseTemplateArguments(tmpld, tdec);
}
while (!tmpld->mTokens) while (!tmpld->mTokens)
tmpld = tmpld->mNext; tmpld = tmpld->mNext;
@ -9616,11 +9704,16 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
Declaration* etdec = nullptr; Declaration* etdec = nullptr;
Declaration* dec = tmpld; Declaration* dec = tmpld;
Declaration* mxtdec = nullptr;
while (dec) 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) if (dist < mindist)
{ {
mxtdec = xtdec;
mindist = dist; mindist = dist;
etdec = dec; etdec = dec;
} }
@ -9635,22 +9728,17 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
tmpld = etdec; tmpld = etdec;
dec = tdec->mParams; dec = tdec->mParams;
Declaration * pdec = tmpld->mParams; Declaration * pdec = tmpld->mBase->mTemplate->mParams;
Declaration * ppdec = nullptr; Declaration * ppdec = nullptr;
while (pdec) while (pdec)
{ {
Declaration* rdec = mxtdec->mScope->Lookup(pdec->mIdent);
if (pdec->mType == DT_PACK_TEMPLATE) if (pdec->mType == DT_PACK_TEMPLATE)
{ {
if (!dec) if (!rdec)
{ {
Declaration* packd = new Declaration(tdec->mLocation, DT_PACK_TEMPLATE); rdec = new Declaration(tdec->mLocation, DT_PACK_TYPE);
packd->mBase = new Declaration(tdec->mLocation, DT_PACK_TYPE);
if (ppdec)
ppdec->mNext = packd;
else
tdec->mParams = packd;
dec = packd;
} }
else if (dec->mType != DT_PACK_TEMPLATE) 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; // rdec->mIdent = pdec->mIdent;
tdec->mScope->Insert(dec->mIdent, dec->mBase); tdec->mScope->Insert(pdec->mIdent, rdec);
ppdec = dec;
dec = dec->mNext;
} }
pdec = pdec->mNext; pdec = pdec->mNext;
@ -9871,8 +9956,20 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp
tpthis = tmpld->mClass; tpthis = tmpld->mClass;
else if (expd && expd->mBase) else if (expd && expd->mBase)
tpthis = expd->mBase->BuildConstPointer(tdec->mLocation); 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); tdec->mBase = p->ParseDeclaration(nullptr, true, false, tpthis, tdec);
p->mScope = oscope;
}
else
#endif
tdec->mBase = p->ParseDeclaration(nullptr, true, false, tpthis, tdec);
} }
p->mTemplateScope = nullptr; p->mTemplateScope = nullptr;
@ -10153,6 +10250,20 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi
bdec->mQualIdent = mScope->Mangle(mScanner->mTokenIdent); bdec->mQualIdent = mScope->Mangle(mScanner->mTokenIdent);
bdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, bdec->mQualIdent); 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) while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE)
mScanner->NextToken(); mScanner->NextToken();

View File

@ -111,7 +111,8 @@ protected:
void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis);
Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); 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); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd);
void CompleteTemplateExpansion(Declaration* tmpld); void CompleteTemplateExpansion(Declaration* tmpld);
@ -124,7 +125,9 @@ protected:
Expression* ExpandPackExpression(Expression* exp, Expression* pack, Expression* item); Expression* ExpandPackExpression(Expression* exp, Expression* pack, Expression* item);
Expression* ParseBinaryFoldExpression(Expression * exp); 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* ParsePrefixExpression(bool lhs);
Expression* ParsePostfixExpression(bool lhs); Expression* ParsePostfixExpression(bool lhs);
Expression* ParseMulExpression(bool lhs); Expression* ParseMulExpression(bool lhs);

View File

@ -130,6 +130,12 @@
} }
"Entry" "Entry"
{ {
"MsmKey" = "8:_1328E18B9638422795616BABEAAFA600"
"OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED"
}
"Entry"
{
"MsmKey" = "8:_1393003825B9451084DB314DD4267AD5" "MsmKey" = "8:_1393003825B9451084DB314DD4267AD5"
"OwnerKey" = "8:_UNDEFINED" "OwnerKey" = "8:_UNDEFINED"
"MsmSig" = "8:_UNDEFINED" "MsmSig" = "8:_UNDEFINED"
@ -1801,6 +1807,26 @@
"IsDependency" = "11:FALSE" "IsDependency" = "11:FALSE"
"IsolateTo" = "8:" "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" "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1393003825B9451084DB314DD4267AD5"
{ {
"SourcePath" = "8:..\\samples\\memmap\\allmem.c" "SourcePath" = "8:..\\samples\\memmap\\allmem.c"
@ -6676,7 +6702,7 @@
{ {
"{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6" "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_FB2E467BC172457785F4279BB0BFE8B6"
{ {
"SourcePath" = "8:..\\Releasex64\\oscar64.exe" "SourcePath" = "8:..\\Debugx64\\oscar64.exe"
"TargetName" = "8:" "TargetName" = "8:"
"Tag" = "8:" "Tag" = "8:"
"Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4" "Folder" = "8:_607E75AF0E2A4CB9908C4C39DF8FE6E4"