Add lambda

This commit is contained in:
drmortalwombat 2023-09-12 15:36:24 +02:00
parent c926456560
commit 2b51f20b1c
11 changed files with 376 additions and 10 deletions

View File

@ -8,7 +8,7 @@
#include <string.h> #include <string.h>
CompilationUnits::CompilationUnits(Errors* errors) CompilationUnits::CompilationUnits(Errors* errors)
: mErrors(errors), mReferenced(nullptr) : mErrors(errors), mReferenced(nullptr), mUniqueID(0)
{ {
mCompilationUnits = nullptr; mCompilationUnits = nullptr;
mPendingUnits = nullptr; mPendingUnits = nullptr;
@ -27,6 +27,12 @@ CompilationUnits::~CompilationUnits(void)
} }
int CompilationUnits::UniqueID(void)
{
return mUniqueID++;
}
void CompilationUnits::AddReferenced(Declaration* ref) void CompilationUnits::AddReferenced(Declaration* ref)
{ {
mReferenced.Push(ref); mReferenced.Push(ref);

View File

@ -31,6 +31,10 @@ public:
LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack, * mSectionZeroPage, * mSectionLowCode, * mSectionBoot; LinkerSection* mSectionCode, * mSectionData, * mSectionBSS, * mSectionHeap, * mSectionStack, * mSectionZeroPage, * mSectionLowCode, * mSectionBoot;
Linker* mLinker; Linker* mLinker;
int mUniqueID;
int UniqueID(void);
bool AddUnit(Location & location, const char* name, const char * from); bool AddUnit(Location & location, const char* name, const char * from);
CompilationUnit* PendingUnit(void); CompilationUnit* PendingUnit(void);

View File

@ -839,7 +839,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalUnary(Expression* exp, con
case TK_MUL: case TK_MUL:
return vl.GetPtr(); return vl.GetPtr();
case TK_NEW: case TK_NEW:
v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, vl.GetInt()))); v.PutPtr(Value(NewValue(exp, exp->mDecType->mBase, int(vl.GetInt()))));
break; break;
case TK_DELETE: case TK_DELETE:
DeleteValue(vl.GetPtr().mBaseValue); DeleteValue(vl.GetPtr().mBaseValue);
@ -1266,7 +1266,9 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp)
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
mDestructStack.Push(exp->mLeft->mRight); mDestructStack.Push(exp->mLeft->mRight);
if (exp->mRight)
return Execute(exp->mRight); return Execute(exp->mRight);
return FLOW_NEXT;
case EX_VOID: case EX_VOID:
return FLOW_NEXT; return FLOW_NEXT;

View File

@ -84,6 +84,7 @@ enum ErrorID
EERR_TEMPLATE_PARAMS, EERR_TEMPLATE_PARAMS,
EERR_FUNCTION_TEMPLATE, EERR_FUNCTION_TEMPLATE,
EERR_INVALID_BITFIELD, EERR_INVALID_BITFIELD,
EERR_INVALID_CAPTURE,
EERR_INVALID_CONSTEXPR, EERR_INVALID_CONSTEXPR,
EERR_DOUBLE_FREE, EERR_DOUBLE_FREE,

View File

@ -919,7 +919,9 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo
Analyze(exp->mLeft->mLeft, procDec, false); Analyze(exp->mLeft->mLeft, procDec, false);
if (exp->mLeft->mRight) if (exp->mLeft->mRight)
Analyze(exp->mLeft->mRight, procDec, false); Analyze(exp->mLeft->mRight, procDec, false);
if (exp->mRight)
return Analyze(exp->mRight, procDec, false); return Analyze(exp->mRight, procDec, false);
break;
case EX_CLEANUP: case EX_CLEANUP:
Analyze(exp->mRight, procDec, false); Analyze(exp->mRight, procDec, false);

View File

@ -53,6 +53,13 @@ const Ident* Ident::PreMangle(const char* str) const
return Unique(buffer); return Unique(buffer);
} }
const Ident* Ident::Unique(const char* str, int id)
{
char buffer[200];
sprintf_s(buffer, "%s#%d", str, id);
return Unique(buffer);
}
const Ident* Ident::Mangle(const char* str) const const Ident* Ident::Mangle(const char* str) const
{ {
char buffer[200]; char buffer[200];

View File

@ -9,6 +9,7 @@ public:
unsigned int mHash; unsigned int mHash;
static const Ident* Unique(const char* str); static const Ident* Unique(const char* str);
static const Ident* Unique(const char* str, int id);
const Ident* Mangle(const char* str) const; const Ident* Mangle(const char* str) const;
const Ident* PreMangle(const char* str) const; const Ident* PreMangle(const char* str) const;
protected: protected:

View File

@ -17081,7 +17081,7 @@ void InterCodeProcedure::Close(void)
{ {
GrowingTypeArray tstack(IT_NONE); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "test"); CheckFunc = !strcmp(mIdent->mString, "main");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -1635,6 +1635,8 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
} }
exp = exp->mRight; exp = exp->mRight;
if (!exp)
return ExValue(TheVoidTypeDeclaration);
} }
break; break;
@ -2054,6 +2056,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ins->mSrc[1].mMemory = IM_INDIRECT; ins->mSrc[1].mMemory = IM_INDIRECT;
ins->mSrc[1].mOperandSize = 2; ins->mSrc[1].mOperandSize = 2;
ins->mSrc[1].mStride = vl.mType->mStripe; ins->mSrc[1].mStride = vl.mType->mStripe;
ins->mNumOperands = 2;
block->Append(ins); block->Append(ins);
} }
@ -2345,6 +2348,9 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType);
block->Append(ains); block->Append(ains);
if (exp->mDecType->IsReference())
return ExValue(exp->mDecValue->mBase->mBase, ains->mDst.mTemp, 2);
else
return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift); return ExValue(exp->mDecValue->mBase, ains->mDst.mTemp, 1, exp->mDecValue->mBits, exp->mDecValue->mShift);
} }

View File

@ -21,6 +21,8 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
mThisPointer = nullptr; mThisPointer = nullptr;
mFunction = nullptr; mFunction = nullptr;
mFunctionType = nullptr; mFunctionType = nullptr;
mLambda = nullptr;
mCaptureScope = nullptr;
for (int i = 0; i < 256; i++) for (int i = 0; i < 256; i++)
mCharMap[i] = i; mCharMap[i] = i;
@ -4514,6 +4516,280 @@ Declaration* Parser::ParseQualIdent(void)
return dec; return dec;
} }
Expression* Parser::ParseLambdaExpression(void)
{
Declaration* cdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT);
cdec->mIdent = Ident::Unique("lambda", mCompilationUnits->UniqueID());
cdec->mQualIdent = mScope->Mangle(cdec->mIdent);
cdec->mFlags |= DTF_DEFINED;
cdec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, cdec->mIdent);
Declaration* olambda = mLambda;
mLambda = cdec;
Token octoken = mCaptureToken;
mCaptureToken = TK_NONE;
Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE);
Declaration* cpdec = cdec->BuildConstPointer(mScanner->mLocation);
Declaration* fdec = new Declaration(mScanner->mLocation, DT_CONST_FUNCTION);
fdec->mIdent = Ident::Unique("operator()");
fdec->mQualIdent = cdec->mScope->Mangle(fdec->mIdent);
cdec->mScope->Insert(fdec->mIdent, fdec);
Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
pdec->mBase = cpdec;
pdec->mSize = 2;
Expression* einit = nullptr;
ConsumeToken(TK_OPEN_BRACKET);
if (!ConsumeTokenIf(TK_CLOSE_BRACKET))
{
// Parse capture list list
do {
bool reference = false;
if (ConsumeTokenIf(TK_BINARY_AND))
{
if (mScanner->mToken == TK_IDENT)
reference = true;
else
mCaptureToken = TK_BINARY_AND;
}
if (ConsumeTokenIf(TK_ASSIGN))
mCaptureToken = TK_ASSIGN;
else if (ConsumeTokenIf(TK_THIS))
{
Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT);
mdec->mIdent = Ident::Unique("this");
mdec->mQualIdent = cdec->mScope->Mangle(mdec->mIdent);
if (cdec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent);
if (mThisPointer)
{
Expression* iexp = new Expression(mScanner->mLocation, EX_VARIABLE);
iexp->mDecType = mThisPointer->mBase;
iexp->mDecValue = mThisPointer;
mdec->mBase = iexp->mDecType;
mdec->mValue = iexp;
mdec->mNext = cdec->mParams;
cdec->mParams = mdec;
}
else
mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method");
mdec->mOffset = cdec->mSize;
mdec->mSize = mdec->mBase->mSize;
cdec->mSize += mdec->mSize;
}
else if (mScanner->mToken == TK_IDENT)
{
Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT);
mdec->mIdent = mScanner->mTokenIdent;
mdec->mQualIdent = cdec->mScope->Mangle(mdec->mIdent);
if (cdec->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent);
Expression* iexp = nullptr;
mScanner->NextToken();
if (ConsumeTokenIf(TK_ASSIGN))
iexp = ParseExpression(false);
else
{
Declaration* mvdec = mScope->Lookup(mdec->mIdent);
if (mvdec && mvdec->mType == DT_VARIABLE)
{
iexp = new Expression(mdec->mLocation, EX_VARIABLE);
iexp->mDecType = mvdec->mBase;
iexp->mDecValue = mvdec;
}
else
mErrors->Error(mdec->mLocation, EERR_INVALID_CAPTURE, "Invalid variable capture", mdec->mIdent);
}
if (iexp)
{
if (reference)
mdec->mBase = iexp->mDecType->BuildReference(mdec->mLocation);
else
mdec->mBase = iexp->mDecType;
mdec->mValue = iexp;
mdec->mNext = cdec->mParams;
cdec->mParams = mdec;
}
mdec->mOffset = cdec->mSize;
mdec->mSize = mdec->mBase->mSize;
cdec->mSize += mdec->mSize;
}
} while (ConsumeTokenIf(TK_COMMA));
ConsumeToken(TK_CLOSE_BRACKET);
}
Declaration* rtype = new Declaration(mScanner->mLocation, DT_TYPE_AUTO);
if (mScanner->mToken == TK_OPEN_PARENTHESIS)
{
fdec->mBase = ParseFunctionDeclaration(rtype);
}
else
{
ConsumeToken(TK_OPEN_PARENTHESIS);
fdec->mBase = TheConstVoidTypeDeclaration;
}
PrependThisArgument(fdec->mBase, cpdec);
fdec->mFlags |= fdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
fdec->mSection = mCodeSection;
if (mCompilerOptions & COPT_NATIVE)
fdec->mFlags |= DTF_NATIVE;
fdec->mCompilerOptions = mCompilerOptions;
fdec->mBase->mCompilerOptions = mCompilerOptions;
fdec->mVarIndex = -1;
int li = mLocalIndex;
DeclarationScope * oscope = mCaptureScope;
mCaptureScope = mScope;
while (mScope->mLevel >= SLEVEL_NAMESPACE)
mScope = mScope->mParent;
fdec->mValue = ParseFunction(fdec->mBase);
mScope = mCaptureScope;
mLambda = olambda;
mCaptureScope = oscope;
mCaptureToken = octoken;
Declaration* pmdec = cdec->mParams;
while (pmdec)
{
Declaration* fcons = pmdec->mBase->mType == DT_TYPE_STRUCT && pmdec->mBase->mScope ? pmdec->mBase->mScope->Lookup(pmdec->mBase->mIdent->PreMangle("+"), SLEVEL_CLASS) : nullptr;
Expression* ciexp;
if (fcons)
{
Expression* vexp = new Expression(pmdec->mLocation, EX_QUALIFY);
vexp->mLeft = new Expression(pmdec->mLocation, EX_VARIABLE);
vexp->mLeft->mDecType = cdec;
vexp->mLeft->mDecValue = vdec;
vexp->mDecValue = pmdec;
vexp->mDecType = pmdec->mBase;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = fcons;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp;
fexp->mRight = pmdec->mValue;
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = vexp;
texp->mDecType = pmdec->mBase->BuildPointer(mScanner->mLocation);
Expression* lexp = new Expression(mScanner->mLocation, EX_LIST);
lexp->mLeft = texp;
lexp->mRight = fexp->mRight;
fexp->mRight = lexp;
fexp = ResolveOverloadCall(fexp);
Expression* dexp = nullptr;
if (pmdec->mBase->mDestructor)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = pmdec->mBase->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = texp;
}
ciexp = new Expression(mScanner->mLocation, EX_CONSTRUCT);
ciexp->mLeft = new Expression(mScanner->mLocation, EX_LIST);
ciexp->mLeft->mLeft = fexp;
ciexp->mLeft->mRight = dexp;
}
else
{
ciexp = new Expression(pmdec->mLocation, EX_INITIALIZATION);
ciexp->mToken = TK_ASSIGN;
ciexp->mDecType = pmdec->mValue->mDecType;
ciexp->mRight = pmdec->mValue;
ciexp->mLeft = new Expression(pmdec->mLocation, EX_QUALIFY);
ciexp->mLeft->mLeft = new Expression(pmdec->mLocation, EX_VARIABLE);
ciexp->mLeft->mLeft->mDecType = cdec;
ciexp->mLeft->mLeft->mDecValue = vdec;
ciexp->mLeft->mDecValue = pmdec;
ciexp->mLeft->mDecType = pmdec->mBase;
}
if (einit)
{
Expression* lexp = new Expression(mScanner->mLocation, EX_LIST);
lexp->mLeft = einit;
lexp->mRight = ciexp;
einit = lexp;
}
else
einit = ciexp;
pmdec = pmdec->mNext;
}
fdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE;
fdec->mNumVars = mLocalIndex;
mLocalIndex = li;
vdec->mBase = cdec;
vdec->mVarIndex = mLocalIndex++;
vdec->mSize = cdec->mSize;
vdec->mFlags |= DTF_DEFINED;
vdec->mIdent = cdec->mIdent;
Expression* vexp = new Expression(mScanner->mLocation, EX_VARIABLE);
vexp->mDecType = vdec->mBase;
vexp->mDecValue = vdec;
if (einit)
{
Expression* conex = new Expression(mScanner->mLocation, EX_CONSTRUCT);
conex->mRight = vexp;
conex->mDecType = vexp->mDecType;
conex->mLeft = new Expression(mScanner->mLocation, EX_LIST);
conex->mLeft->mLeft = einit;
conex->mLeft->mRight = nullptr;
return conex;
}
else
return vexp;
}
Expression* Parser::ParseSimpleExpression(bool lhs) Expression* Parser::ParseSimpleExpression(bool lhs)
{ {
Declaration* dec = nullptr; Declaration* dec = nullptr;
@ -4701,7 +4977,31 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
mScanner->NextToken(); mScanner->NextToken();
break; break;
case TK_THIS: case TK_THIS:
if (mThisPointer) if (mLambda)
{
dec = mLambda->mScope->Lookup(Ident::Unique("this"), SLEVEL_CLASS);
if (dec)
{
Expression* texp = new Expression(mScanner->mLocation, EX_VARIABLE);
texp->mDecType = mThisPointer->mBase;
texp->mDecValue = mThisPointer;
Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX);
dexp->mToken = TK_MUL;
dexp->mDecType = texp->mDecType->mBase;
dexp->mLeft = texp;
dexp = dexp->ConstantFold(mErrors, mDataSection);
exp = new Expression(mScanner->mLocation, EX_QUALIFY);
exp->mLeft = dexp;
exp->mDecType = dec->mBase;
exp->mDecValue = dec;
}
else
mErrors->Error(mScanner->mLocation, ERRO_THIS_OUTSIDE_OF_METHOD, "Use of this outside of method");
}
else if (mThisPointer)
{ {
exp = new Expression(mScanner->mLocation, EX_VARIABLE); exp = new Expression(mScanner->mLocation, EX_VARIABLE);
exp->mDecType = mThisPointer->mBase; exp->mDecType = mThisPointer->mBase;
@ -4713,6 +5013,35 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
mScanner->NextToken(); mScanner->NextToken();
break; break;
case TK_IDENT: case TK_IDENT:
if (mLambda && mCaptureToken != TK_NONE && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS) && !mLambda->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS))
{
Declaration * mvdec = mCaptureScope->Lookup(mScanner->mTokenIdent, SLEVEL_CLASS);
if (mvdec && mvdec->mType == DT_VARIABLE)
{
Declaration* mdec = new Declaration(mScanner->mLocation, DT_ELEMENT);
mdec->mIdent = mScanner->mTokenIdent;
mdec->mQualIdent = mLambda->mScope->Mangle(mdec->mIdent);
if (mLambda->mScope->Insert(mdec->mIdent, mdec))
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate lambda capture", mdec->mIdent);
Expression* iexp = new Expression(mdec->mLocation, EX_VARIABLE);
iexp->mDecType = mvdec->mBase;
iexp->mDecValue = mvdec;
if (mCaptureToken == TK_BINARY_AND)
mdec->mBase = iexp->mDecType->BuildReference(mdec->mLocation);
else
mdec->mBase = iexp->mDecType;
mdec->mValue = iexp;
mdec->mNext = mLambda->mParams;
mLambda->mParams = mdec;
mdec->mOffset = mLambda->mSize;
mdec->mSize = mdec->mBase->mSize;
mLambda->mSize += mdec->mSize;
}
}
if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION)) if (mThisPointer && mThisPointer->mType == DT_ARGUMENT && !mScope->Lookup(mScanner->mTokenIdent, SLEVEL_FUNCTION))
{ {
int offset; int offset;
@ -4883,6 +5212,9 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
} }
} }
break; break;
case TK_OPEN_BRACKET:
exp = ParseLambdaExpression();
break;
case TK_ASM: case TK_ASM:
mScanner->NextToken(); mScanner->NextToken();
if (mScanner->mToken == TK_OPEN_BRACE) if (mScanner->mToken == TK_OPEN_BRACE)
@ -7108,6 +7440,8 @@ Expression* Parser::ParseListExpression(bool lhs)
Expression* Parser::ParseFunction(Declaration * dec) Expression* Parser::ParseFunction(Declaration * dec)
{ {
Declaration* othis = mThisPointer; Declaration* othis = mThisPointer;
Declaration* ofunc = mFunctionType;
if (dec->mFlags & DTF_FUNC_THIS) if (dec->mFlags & DTF_FUNC_THIS)
mThisPointer = dec->mParams; mThisPointer = dec->mParams;
@ -7182,6 +7516,7 @@ Expression* Parser::ParseFunction(Declaration * dec)
mScope = oscope; mScope = oscope;
mThisPointer = othis; mThisPointer = othis;
mFunctionType = ofunc;
return exp; return exp;
} }

View File

@ -12,10 +12,11 @@ public:
Parser* Clone(void); Parser* Clone(void);
DeclarationScope * mGlobals, * mScope, * mTemplateScope; DeclarationScope * mGlobals, * mScope, * mTemplateScope, * mCaptureScope;
int mLocalIndex; int mLocalIndex;
CompilationUnits * mCompilationUnits; CompilationUnits * mCompilationUnits;
Declaration * mThisPointer, * mFunctionType, * mFunction; Declaration * mThisPointer, * mFunctionType, * mFunction, * mLambda;
Token mCaptureToken;
LinkerSection * mCodeSection, * mDataSection, * mBSSection; LinkerSection * mCodeSection, * mDataSection, * mBSSection;
@ -105,6 +106,7 @@ protected:
void CompleteTemplateExpansion(Declaration* tmpld); void CompleteTemplateExpansion(Declaration* tmpld);
Expression* ParseNewOperator(void); Expression* ParseNewOperator(void);
Expression* ParseLambdaExpression(void);
Expression* ParseSimpleExpression(bool lhs); Expression* ParseSimpleExpression(bool lhs);
Expression* ParsePrefixExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs);