From a0409002b6696dd4b556befb902532165c569037 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:19:56 +0200 Subject: [PATCH] Fix pointers in constexpr --- autotest/autotest.bat | 3 + autotest/opp_pairtest.cpp | 28 + include/opp/move.h | 14 - include/opp/utility.h | 34 ++ include/opp/vector.h | 2 +- oscar64/Constexpr.cpp | 142 ++++- oscar64/Constexpr.h | 3 +- oscar64/Declaration.cpp | 76 ++- oscar64/Declaration.h | 4 +- oscar64/GlobalAnalyzer.cpp | 11 +- oscar64/InterCode.cpp | 53 +- oscar64/InterCodeGenerator.cpp | 63 ++- oscar64/Parser.cpp | 985 +++++++++++++++++++++++++-------- oscar64/Parser.h | 2 + oscar64/Scanner.cpp | 94 ++++ oscar64/Scanner.h | 8 + 16 files changed, 1216 insertions(+), 306 deletions(-) create mode 100644 autotest/opp_pairtest.cpp delete mode 100644 include/opp/move.h create mode 100644 include/opp/utility.h diff --git a/autotest/autotest.bat b/autotest/autotest.bat index b5ed668..a5eaf07 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -18,6 +18,9 @@ rem @echo off @call :test opp_streamtest.cpp @if %errorlevel% neq 0 goto :error +@call :test opp_pairtest.cpp +@if %errorlevel% neq 0 goto :error + @call :test operatoroverload.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_pairtest.cpp b/autotest/opp_pairtest.cpp new file mode 100644 index 0000000..7a1113c --- /dev/null +++ b/autotest/opp_pairtest.cpp @@ -0,0 +1,28 @@ +#include +#include +#include +#include + +using namespace opp; + +int main(void) +{ + vector > vii; + + for(int i=0; i<100; i++) + vii.push_back(make_pair(i, i * i)); + + int sum1 = 0; + long sum2 = 0; + for(const auto & v : vii) + { + sum1 += v.first; + sum2 += v.second; + } + + + assert(sum1 == 4950); + assert(sum2 == 328350l); + + return 0; +} diff --git a/include/opp/move.h b/include/opp/move.h deleted file mode 100644 index 977fb64..0000000 --- a/include/opp/move.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef OPP_MOVE_H -#define OPP_MOVE_H - -namespace opp { - -template -T && move(T & m) -{ - return (T &&)m; -} - -} - -#endif diff --git a/include/opp/utility.h b/include/opp/utility.h new file mode 100644 index 0000000..b09c0aa --- /dev/null +++ b/include/opp/utility.h @@ -0,0 +1,34 @@ +#ifndef OPP_UTILITY_H +#define OPP_UTILITY_H + +namespace opp { + +template +T && move(T & m) +{ + return (T &&)m; +} + + +template +struct pair +{ + T1 first; + T2 second; + + pair(T1 && t1, T2 && t2) + : first(t1), second(t2) + {} +}; + +template +constexpr pair make_pair(T1 && t1, T2 && t2) +{ + return pair(t1, t2); +} + +} + + + +#endif diff --git a/include/opp/vector.h b/include/opp/vector.h index d28d51e..f1fa8dd 100644 --- a/include/opp/vector.h +++ b/include/opp/vector.h @@ -2,7 +2,7 @@ #define OPP_VECTOR_H #include -#include +#include namespace opp { diff --git a/oscar64/Constexpr.cpp b/oscar64/Constexpr.cpp index 3d36080..97efbfa 100644 --- a/oscar64/Constexpr.cpp +++ b/oscar64/Constexpr.cpp @@ -37,6 +37,7 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec) switch (dec->mType) { case DT_CONST_INTEGER: + case DT_CONST_ADDRESS: PutIntAt(dec->mInteger, offset, dec->mBase); break; case DT_CONST_FLOAT: @@ -46,6 +47,10 @@ void ConstexprInterpreter::Value::PutConst(int offset, Declaration* dec) for (Declaration* pdec = dec->mParams; pdec; pdec = pdec->mNext) PutConst(pdec->mOffset, pdec); break; + case DT_CONST_DATA: + for (int i = 0; i < dec->mBase->mSize; i++) + PutIntAt(dec->mData[i], offset + i, TheConstCharTypeDeclaration); + break; } } @@ -116,8 +121,8 @@ ConstexprInterpreter::Value::Value(Value* value) { } -ConstexprInterpreter::Value::Value(Value* value, Declaration* type, int offset) - : mLocation(value->mLocation), +ConstexprInterpreter::Value::Value(const Location& location, Value* value, Declaration* type, int offset) + : mLocation(location), mDecType(type), mBaseValue(value), mOffset(offset), mDataSize(0), mData(mShortData) @@ -331,7 +336,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Value::GetPtrAt(int at, Declar { const ValueItem* dp = GetAddr() + at; - return Value(dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8))); + return Value(mLocation, dp->mBaseValue, type, uint16(dp[0].mByte | ((uint32)(dp[1].mByte) << 8))); } void ConstexprInterpreter::Value::PutIntAt(int64 v, int at, Declaration* type) @@ -448,19 +453,27 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type dec->mSize = type->mSize; dec->mSection = dataSection; dec->mOffset = offset; + Declaration* ldec = nullptr; - for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) + while (type) { - Declaration * cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); - cdec->mOffset = mdec->mOffset; + for (Declaration* mdec = type->mParams; mdec; mdec = mdec->mNext) + { + Declaration* cdec = GetConst(offset + mdec->mOffset, mdec->mBase, dataSection); + cdec->mOffset = mdec->mOffset; - if (ldec) - ldec->mNext = cdec; + if (ldec) + ldec->mNext = cdec; + else + dec->mParams = cdec; + + ldec = cdec; + } + + if (type->mBase) + type = type->mBase->mBase; else - dec->mParams = cdec; - - ldec = cdec; - + type = nullptr; } break; } @@ -486,6 +499,46 @@ Declaration* ConstexprInterpreter::Value::GetConst(int offset, Declaration* type } break; } + case DT_TYPE_POINTER: + { + Value vp = GetPtrAt(offset, type); + if (vp.mBaseValue) + { + dec = new Declaration(mLocation, DT_CONST_POINTER); + dec->mBase = type; + dec->mSize = type->mSize; + + Declaration* target; + + if (vp.mBaseValue->mDecType->mType == DT_TYPE_ARRAY) + { + target = new Declaration(mLocation, DT_CONST_DATA); + target->mSize = vp.mBaseValue->mDataSize; + target->mBase = vp.mBaseValue->mDecType; + target->mSection = dataSection; + + uint8* buffer = new uint8[target->mSize]; + for (int i = 0; i < target->mSize; i++) + buffer[i] = uint8(vp.mBaseValue->GetIntAt(i, TheUnsignedCharTypeDeclaration)); + target->mData = buffer; + } + else + target = vp.mBaseValue->GetConst(0, vp.mBaseValue->mDecType, dataSection); + + dec->mValue = new Expression(mLocation, EX_CONSTANT); + dec->mValue->mDecType = target->mBase; + dec->mValue->mDecValue = target; + } + else + { + dec = new Declaration(mLocation, DT_CONST_ADDRESS); + dec->mBase = type; + dec->mFlags = 0; + dec->mSize = type->mSize; + dec->mInteger = vp.mOffset; + } + break; + } } @@ -511,7 +564,8 @@ ConstexprInterpreter::ConstexprInterpreter(const Location & location, Errors* er ConstexprInterpreter::~ConstexprInterpreter(void) { - + for (int i = 0; i < mTemps.Size(); i++) + delete mTemps[i]; } ConstexprInterpreter::Value* ConstexprInterpreter::NewValue(Expression* exp, Declaration* type, int size) @@ -541,13 +595,30 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) Declaration* dec = exp->mLeft->mDecType->mParams; int pos = 0; + if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT) + { + mResult = Value(exp->mLocation, mProcType->mBase); + mParams[0] = Value(&mResult); + pos = 2; + } + while (pex && pex->mType == EX_LIST) { if (dec) pos = dec->mVarIndex; if (pex->mLeft->mType == EX_CONSTANT) - mParams[pos] = Value(pex->mLeft); + { + if (pex->mLeft->mDecType->mType == DT_TYPE_ARRAY) + { + Value * tmp = new Value(pex->mLeft); + mTemps.Push(tmp); + mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecType->BuildArrayPointer()); + mParams[pos].PutPtr(Value(tmp)); + } + else + mParams[pos] = Value(pex->mLeft); + } else if (pex->mLeft->mType == EX_VARIABLE && (pex->mLeft->mDecValue->mFlags & DTF_CONST)) { mParams[pos] = Value(pex->mLeft->mLocation, pex->mLeft->mDecValue->mBase); @@ -566,7 +637,17 @@ Expression* ConstexprInterpreter::EvalCall(Expression* exp) pos = dec->mVarIndex; if (pex->mType == EX_CONSTANT) - mParams[pos] = Value(pex); + { + if (pex->mDecType->mType == DT_TYPE_ARRAY) + { + Value* tmp = new Value(pex); + mTemps.Push(tmp); + mParams[pos] = Value(pex->mLocation, pex->mDecType->BuildArrayPointer()); + mParams[pos].PutPtr(Value(tmp)); + } + else + mParams[pos] = Value(pex); + } else if (pex->mType == EX_VARIABLE && (pex->mDecValue->mFlags & DTF_CONST)) { mParams[pos] = Value(pex->mLocation, pex->mDecValue->mBase); @@ -619,6 +700,12 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalBinary(Expression * exp, c mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Incompatible operator", TokenNames[exp->mToken]); } } + else if (exp->mDecType->mType == DT_TYPE_POINTER) + { + Value vlp = vl.GetPtr(); + vlp.mOffset += int(vr.GetInt() * vl.mDecType->mBase->mSize); + v.PutPtr(vlp); + } else { switch (exp->mToken) @@ -880,6 +967,13 @@ ConstexprInterpreter::Value ConstexprInterpreter::EvalCall(Expression* exp, Cons Declaration* dec = exp->mLeft->mDecType->mParams; int pos = 0; + if (mProcType->mBase && mProcType->mBase->mType == DT_TYPE_STRUCT) + { + mResult = Value(exp->mLocation, mProcType->mBase); + mParams[0] = Value(&mResult); + pos = 2; + } + while (pex && pex->mType == EX_LIST) { if (dec) @@ -1096,7 +1190,7 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) { Value v = Eval(exp->mLeft); if (v.mBaseValue) - return Value(v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset); + return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + exp->mDecValue->mOffset); } case EX_INDEX: @@ -1107,15 +1201,26 @@ ConstexprInterpreter::Value ConstexprInterpreter::Eval(Expression* exp) if (v.mDecType->mType == DT_TYPE_ARRAY) { if (v.mBaseValue) - return Value(v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); + return Value(exp->mLocation, v.mBaseValue, exp->mDecType, v.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); } else if (v.mDecType->mType == DT_TYPE_POINTER) { Value p = v.GetPtr(); - return Value(p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); + return Value(exp->mLocation, p.mBaseValue, exp->mDecType, p.mOffset + v.mDecType->mBase->mSize * int(vi.GetInt())); } } + case EX_RESULT: + if (mParams[0].mBaseValue) + return mParams[0]; + else + return Value(&mParams[0]); + + case EX_CONSTRUCT: + if (exp->mLeft->mLeft) + Eval(exp->mLeft->mLeft); + return Eval(exp->mRight); + case EX_VOID: return Value(exp->mLocation); @@ -1162,6 +1267,7 @@ ConstexprInterpreter::Flow ConstexprInterpreter::Execute(Expression* exp) case EX_PREINCDEC: case EX_QUALIFY: case EX_INDEX: + case EX_RESULT: Eval(exp); return FLOW_NEXT; diff --git a/oscar64/Constexpr.h b/oscar64/Constexpr.h index 88f24e8..8a0df57 100644 --- a/oscar64/Constexpr.h +++ b/oscar64/Constexpr.h @@ -29,7 +29,7 @@ protected: Value(const Location& location, Declaration* dec, int count); Value(const Value& value); Value(Value&& value); - Value(Value * value, Declaration * type, int offset); + Value(const Location& location, Value * value, Declaration * type, int offset); Value(Value* value); Value(const Location& location, const uint8 * data, Declaration* type); Value(const Location& location, const ValueItem* data, Declaration* type); @@ -101,6 +101,7 @@ protected: GrowingArray mParams, mLocals; ExpandingArray mDestructStack; ExpandingArray * mHeap; + ExpandingArray mTemps; Errors * mErrors; Value mResult; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 3358fc1..3d5facf 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -303,6 +303,9 @@ void Expression::Dump(int ident) const case EX_PACK: printf("PACK"); break; + case EX_PACK_TYPE: + printf("PACK_TYPE"); + break; } printf("\n"); @@ -355,6 +358,16 @@ bool Expression::IsRValue(void) const return true; } +bool Expression::IsConstRef(void) const +{ + if (mDecType->mType == DT_TYPE_RVALUEREF || mDecType->mType == DT_TYPE_REFERENCE) + return true; + else if (mType == EX_VARIABLE || mType == EX_QUALIFY || mType == EX_INDEX || mType == EX_PREFIX && mToken == TK_MUL) + return true; + else + return false; +} + bool Expression::IsLValue(void) const { if (mDecType->mFlags & DTF_CONST) @@ -996,7 +1009,7 @@ Declaration* Declaration::DeduceAuto(Declaration * dec) if (dec->mType == DT_TYPE_ARRAY) dec = dec->mBase->BuildPointer(mLocation); - if (mFlags & DTF_CONST) + if ((IsReference() ? mBase->mFlags : mFlags) & DTF_CONST) dec = dec->ToConstType(); else dec = dec->ToMutableType(); @@ -1133,7 +1146,7 @@ const Ident* Declaration::MangleIdent(void) } else if (mType == DT_PACK_TYPE) { - Declaration* dec = mBase; + Declaration* dec = mParams; while (dec) { const Ident* id = dec->MangleIdent(); @@ -1288,7 +1301,7 @@ bool Declaration::ResolveTemplate(Expression* pexp, Declaration* tdec) tpdec->mIdent = pdec->mBase->mBase->mIdent; else tpdec->mIdent = pdec->mBase->mIdent; - tpdec->mBase = phead; + tpdec->mParams = phead; mScope->Insert(tpdec->mIdent, tpdec); } else @@ -1434,25 +1447,66 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) Declaration *ftdec = tdec->mTemplate; while (ftdec) { - if (ftdec->mBase->IsConstSame(fdec)) + if (ftdec->mBase->mQualIdent == fdec->mQualIdent) { Declaration* fpdec = ftdec->mParams; Declaration* tpdec = tdec->mTemplate->mParams; - while (fpdec) + while (fpdec && tpdec) { if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE) { - Declaration * pdec = mScope->Insert(tpdec->mIdent, fpdec->mBase); + Declaration * pdec = mScope->Insert(tpdec->mBase->mIdent, fpdec->mBase); if (pdec && !pdec->IsSame(fpdec->mBase)) return false; } + else if (tpdec->mBase->mType == DT_PACK_TEMPLATE) + { + Declaration* tppack; + if (fpdec->mType == DT_PACK_TEMPLATE) + tppack = fpdec->mBase; + else + { + tppack = new Declaration(fpdec->mLocation, DT_PACK_TYPE); + + Declaration* ppdec = nullptr; + + while (fpdec) + { + if (fpdec->mType == DT_PACK_TEMPLATE) + { + if (ppdec) + ppdec->mNext = fpdec->mBase->mParams; + else + tppack->mParams = fpdec->mBase->mParams; + break; + } + + Declaration* ndec = fpdec->mBase->Clone(); + + if (ppdec) + ppdec->mNext = ndec; + else + tppack->mParams = ndec; + ppdec = ndec; + + fpdec = fpdec->mNext; + } + + } + + Declaration* pdec = mScope->Insert(tpdec->mBase->mIdent, tppack); + if (pdec && !pdec->IsSame(fpdec->mBase)) + return false; + + return true; + } fpdec = fpdec->mNext; tpdec = tpdec->mNext; } - return true; + return !fpdec && !tpdec; } ftdec = ftdec->mNext; @@ -1604,6 +1658,7 @@ Declaration* Declaration::ToConstType(void) ndec->mQualIdent = mQualIdent; ndec->mTemplate = mTemplate; + ndec->mDestructor = mDestructor; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; ndec->mMoveConstructor = mMoveConstructor; @@ -1636,6 +1691,7 @@ Declaration* Declaration::ToMutableType(void) ndec->mQualIdent = mQualIdent; ndec->mTemplate = mTemplate; + ndec->mDestructor = mDestructor; ndec->mDefaultConstructor = mDefaultConstructor; ndec->mCopyConstructor = mCopyConstructor; ndec->mMoveConstructor = mMoveConstructor; @@ -1659,6 +1715,8 @@ bool Declaration::IsSameTemplate(const Declaration* dec) const if (mType == DT_CONST_FUNCTION) return mBase->IsSame(dec->mBase); + else if (mType == DT_TYPE_STRUCT) + return true; return false; } @@ -1673,7 +1731,7 @@ bool Declaration::IsSubType(const Declaration* dec) const if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY) { - if (dec->mType == DT_TYPE_POINTER) + if (dec->mType == DT_TYPE_POINTER || dec->mType == DT_TYPE_ARRAY) return /*this->Stride() == dec->Stride() &&*/ mBase->IsSubType(dec->mBase); } @@ -1906,7 +1964,7 @@ bool Declaration::IsSameParams(const Declaration* dec) const } else if (mType == DT_PACK_TYPE && dec->mType == DT_PACK_TYPE) { - Declaration* ld = mBase, * rd = dec->mBase; + Declaration* ld = mParams, * rd = dec->mParams; while (ld && rd) { if (!ld->IsSame(rd)) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 05be0ae..17bb110 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -222,7 +222,8 @@ enum ExpressionType EX_CONSTRUCT, EX_CLEANUP, EX_RESULT, - EX_PACK + EX_PACK, + EX_PACK_TYPE, }; class Expression @@ -247,6 +248,7 @@ public: bool IsSame(const Expression* exp) const; bool IsRValue(void) const; bool IsLValue(void) const; + bool IsConstRef(void) const; void Dump(int ident) const; }; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index ab171d0..1d50024 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -557,7 +557,7 @@ void GlobalAnalyzer::AnalyzeProcedure(Expression* exp, Declaration* dec) while (pdec) { pdec->mVarIndex += vi; - if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mBase->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST)) + if (pdec->mBase->mType == DT_TYPE_REFERENCE && pdec->mBase->mBase->IsSimpleType() && !(pdec->mFlags & DTF_VAR_ADDRESS) && (pdec->mBase->mBase->mFlags & DTF_CONST)) { pdec->mBase = pdec->mBase->mBase; pdec->mSize = pdec->mBase->mSize; @@ -884,6 +884,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo if (pex->mType == EX_CALL && IsStackParam(pex->mDecType) && !(pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF))) ldec->mBase->mFlags |= DTF_STACKCALL; + RegisterProc(Analyze(pex, procDec, pdec && pdec->mBase->IsReference())); + if (pdec) pdec = pdec->mNext; @@ -892,7 +894,6 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo else rex = nullptr; } - RegisterProc(Analyze(exp->mRight, procDec, false)); } break; case EX_LIST: @@ -901,7 +902,7 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo case EX_RETURN: if (exp->mLeft) { - RegisterProc(Analyze(exp->mLeft, procDec, false)); + RegisterProc(Analyze(exp->mLeft, procDec, procDec->mBase->mBase->IsReference())); if (procDec->mBase->mBase && procDec->mBase->mBase->mType == DT_TYPE_STRUCT && procDec->mBase->mBase->mCopyConstructor) { if (procDec->mBase->mBase->mMoveConstructor) @@ -1031,8 +1032,8 @@ Declaration * GlobalAnalyzer::Analyze(Expression* exp, Declaration* procDec, boo procDec->mComplexity += exp->mDecType->mSize * 10; ldec = Analyze(exp->mLeft, procDec, false); - RegisterProc(Analyze(exp->mRight->mLeft, procDec, false)); - RegisterProc(Analyze(exp->mRight->mRight, procDec, false)); + RegisterProc(Analyze(exp->mRight->mLeft, procDec, lhs)); + RegisterProc(Analyze(exp->mRight->mRight, procDec, lhs)); break; } diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 9ee5698..1599ca1 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -3679,6 +3679,34 @@ bool InterInstruction::RemoveUnusedStoreInstructions(const GrowingVariableArray& } } } + else if (mCode == IC_SELECT) + { + if (mDst.mType == IT_POINTER) + { + if (mSrc[1].mTemp < 0) + { + if (mSrc[1].mMemory == IM_LOCAL) + { + requiredVars += mSrc[1].mVarIndex; + } + else if (mSrc[1].mMemory == paramMemory) + { + requiredParams += mSrc[1].mVarIndex; + } + } + if (mSrc[2].mTemp < 0) + { + if (mSrc[2].mMemory == IM_LOCAL) + { + requiredVars += mSrc[2].mVarIndex; + } + else if (mSrc[2].mMemory == paramMemory) + { + requiredParams += mSrc[2].mVarIndex; + } + } + } + } else if (mCode == IC_CONSTANT) { if (mConst.mType == IT_POINTER) @@ -3809,6 +3837,22 @@ bool InterInstruction::RemoveUnusedStaticStoreInstructions(InterCodeBasicBlock* } } } + else if (mCode == IC_SELECT) + { + if (mDst.mType == IT_POINTER) + { + if (mSrc[1].mTemp < 0) + { + if (mSrc[1].mMemory == IM_GLOBAL && mSrc[1].mVarIndex >= 0) + requiredVars += mSrc[1].mVarIndex; + } + if (mSrc[2].mTemp < 0) + { + if (mSrc[2].mMemory == IM_GLOBAL && mSrc[2].mVarIndex >= 0) + requiredVars += mSrc[2].mVarIndex; + } + } + } else if (mCode == IC_COPY || mCode == IC_STRCPY) { requiredVars.Fill(); @@ -5241,12 +5285,11 @@ void InterCodeBasicBlock::CheckValueUsage(InterInstruction * ins, const GrowingI break; case IC_SELECT: - for(int i=0; i<3; i++) + for (int i = 0; i < 3; i++) { - if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT) + if (ins->mSrc[i].mTemp >= 0 && tvalue[ins->mSrc[i].mTemp] && tvalue[ins->mSrc[i].mTemp]->mCode == IC_CONSTANT && ins->mSrc[i].mType != IT_POINTER) { ins->mSrc[i] = tvalue[ins->mSrc[i].mTemp]->mConst; - ins->mSrc[i].mType = ins->mDst.mType; ins->mSrc[i].mTemp = -1; } } @@ -16376,6 +16419,8 @@ void InterCodeProcedure::ResetVisited(void) int InterCodeProcedure::AddTemporary(InterType type) { + assert(type != IT_NONE); + int temp = mTemporaries.Size(); mTemporaries.Push(type); return temp; @@ -17179,7 +17224,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "bv"); + CheckFunc = !strcmp(mIdent->mString, "main"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index d34f7c3..39ca8ee 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -63,6 +63,12 @@ InterCodeGenerator::ExValue InterCodeGenerator::Dereference(InterCodeProcedure* ins->mSrc[0].mOperandSize = v.mReference == 1 ? v.mType->mSize : 2; ins->mSrc[0].mStride = v.mReference == 1 ? v.mType->mStripe : 1; + if (ins->mDst.mType == IT_NONE) + { + mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Not a simple type"); + return v; + } + if (v.mReference == 1 && v.mType->mType == DT_TYPE_ENUM) { ins->mDst.mRange.LimitMin(v.mType->mMinValue); @@ -1641,6 +1647,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* break; case EX_PACK: + case EX_PACK_TYPE: mErrors->Error(exp->mLocation, EERR_INVALID_PACK_USAGE, "Invalid pack usage"); return ExValue(TheVoidTypeDeclaration); @@ -2032,7 +2039,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* if (exp->mToken == TK_ASSIGN || !(vl.mType->mType == DT_TYPE_POINTER && vr.mType->IsIntegerType() && (exp->mToken == TK_ASSIGN_ADD || exp->mToken == TK_ASSIGN_SUB))) { if (!vl.mType->CanAssign(vr.mType)) + { + vl.mType->CanAssign(vr.mType); mErrors->Error(exp->mLocation, EERR_INCOMPATIBLE_TYPES, "Cannot assign incompatible types"); + } } if (exp->mType != EX_INITIALIZATION && (vl.mType->mFlags & DTF_CONST)) @@ -3754,10 +3764,19 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { vr = TranslateExpression(procType, proc, block, exp->mLeft, destack, breakBlock, continueBlock, inlineMapper); + if (vr.mType->IsReference()) + { + vr.mReference++; + vr.mType = vr.mType->mBase; + } + vr = Dereference(proc, exp, block, vr, 1); vr = CoerceType(proc, exp, block, vr, procType->mBase); + if (vr.mReference == 0) + mErrors->Error(exp->mLocation, EERR_INVALID_VALUE, "Returning value as reference"); + ins->mSrc[0].mType = IT_POINTER; ins->mSrc[0].mTemp = vr.mTemp; ins->mSrc[0].mMemory = IM_INDIRECT; @@ -3766,18 +3785,28 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { if (inlineMapper->mResultExp) { - ins->mSrc[1].mType = IT_POINTER; - ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; - ins->mSrc[1].mMemory = IM_INDIRECT; - ins->mCode = IC_STORE; - ins->mSrc[1].mOperandSize = 2; - ins->mNumOperands = 2; + if (inlineMapper->mResultExp->mType->IsReference()) + { + ins->mSrc[1].mType = IT_POINTER; + ins->mSrc[1].mTemp = inlineMapper->mResultExp->mTemp; + ins->mSrc[1].mMemory = IM_INDIRECT; + ins->mCode = IC_STORE; + ins->mSrc[1].mOperandSize = 2; + ins->mNumOperands = 2; + } + else + { + //bool moving = exp->mLeft->IsRValue() || exp->mLeft->mType == EX_VARIABLE && !(exp->mLeft->mDecValue->mFlags & (DTF_STATIC | DTF_GLOBAL)) && exp->mLeft->mDecType->mType != DT_TYPE_REFERENCE; + + CopyStruct(proc, exp, block, *(inlineMapper->mResultExp), vr, inlineMapper, false); + ins->mCode = IC_NONE; + } } else { InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; @@ -4007,7 +4036,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* { InterInstruction* ains = new InterInstruction(exp->mLocation, IC_CONSTANT); ains->mDst.mType = IT_POINTER; - ains->mDst.mTemp = proc->AddTemporary(ins->mDst.mType); + ains->mDst.mTemp = proc->AddTemporary(ains->mDst.mType); ains->mConst.mType = IT_POINTER; ains->mConst.mOperandSize = procType->mBase->mSize; ains->mConst.mIntConst = 0; @@ -4148,14 +4177,24 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vc = Dereference(proc, exp, block, vc); - int ttemp; + int ttemp, tref = 0; InterType ttype, stypel, styper; stypel = InterTypeOf(vl.mType); styper = InterTypeOf(vr.mType); - Declaration* dtype; - if (stypel == IT_POINTER || styper == IT_POINTER) + Declaration* dtype = exp->mDecType; + + if (dtype->IsReference()) + { + vl = Dereference(proc, exp, block, vl, 1); + vr = Dereference(proc, exp, block, vr, 1); + tref = 1; + + dtype = dtype->mBase; + ttype = IT_POINTER; + } + else if (stypel == IT_POINTER || styper == IT_POINTER) { if (vl.mType->mType == DT_TYPE_ARRAY) vl = Dereference(proc, exp, block, vl, 1); @@ -4224,7 +4263,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* sins->mDst.mTemp = ttemp; block->Append(sins); - return ExValue(dtype, ttemp); + return ExValue(dtype, ttemp, tref); } else #endif diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 8f66d00..313b047 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -595,6 +595,16 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaratio AddDefaultConstructors(pthis); + if (pthis->mBase->mConst) + { + pthis->mBase->mConst->mDestructor = pthis->mBase->mDestructor; + pthis->mBase->mConst->mDefaultConstructor = pthis->mBase->mDefaultConstructor; + pthis->mBase->mConst->mCopyConstructor = pthis->mBase->mCopyConstructor; + pthis->mBase->mConst->mMoveConstructor = pthis->mBase->mMoveConstructor; + pthis->mBase->mConst->mVectorConstructor = pthis->mBase->mVectorConstructor; + pthis->mBase->mConst->mVectorCopyConstructor = pthis->mBase->mVectorCopyConstructor; + } + // Lookup constructors, have same name as class Declaration* cdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+"), SLEVEL_SCOPE); while (cdec) @@ -753,24 +763,26 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Decl case TK_IDENT: pident = mScanner->mTokenIdent; + mScanner->NextToken(); + if (mTemplateScope) - dec = mTemplateScope->Lookup(mScanner->mTokenIdent); + { + dec = mTemplateScope->Lookup(pident); + if (dec && mScanner->mToken == TK_LESS_THAN && !dec->mTemplate) + dec = nullptr; + } if (!dec) { - dec = mScope->Lookup(mScanner->mTokenIdent); + dec = mScope->Lookup(pident); if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) - dec = mScope->mParent->Lookup(mScanner->mTokenIdent); - - mScanner->NextToken(); + dec = mScope->mParent->Lookup(pident); dec = ParseBaseTypeQualify(qualified, dec, pident); if (dec && dec->mTemplate) dec = ParseTemplateExpansion(dec->mTemplate, nullptr); } - else - mScanner->NextToken(); dec = ParseBaseTypeQualify(qualified, dec, pident); @@ -1191,7 +1203,7 @@ Declaration * Parser::ParseFunctionDeclaration(Declaration* bdec) atdec = atdec->mBase; if (atdec->mType == DT_PACK_TYPE) { - atdec = atdec->mBase; + atdec = atdec->mParams; Declaration* apdec = adec; while (atdec) @@ -1827,8 +1839,11 @@ Expression* Parser::BuildMemberInitializer(Expression* vexp) nexp->mDecType = vexp->mDecType; nexp->mLeft = vexp; ConsumeToken(TK_OPEN_PARENTHESIS); - nexp->mRight = ParseRExpression(); - ConsumeToken(TK_CLOSE_PARENTHESIS); + if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) + { + nexp->mRight = ParseRExpression(); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } return nexp; } @@ -2043,6 +2058,9 @@ void Parser::BuildMemberConstructor(Declaration* pthis, Declaration* cfunc) scope->Insert(pdec->mIdent, pdec); pdec = pdec->mNext; } + if (cfunc->mBase->mParamPack) + mScope->Insert(cfunc->mBase->mParamPack->mIdent, cfunc->mBase->mParamPack); + Declaration* othis = mThisPointer; mThisPointer = pthis; @@ -2165,6 +2183,12 @@ void Parser::AddDefaultConstructors(Declaration* pthis) if (!(bcdec->mBase->mCopyConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) inlineCopy = false; } + if (bcdec->mBase->mMoveConstructor) + { + simpleMove = false; + if (!(bcdec->mBase->mMoveConstructor->mBase->mFlags & DTF_REQUEST_INLINE)) + inlineCopy = false; + } if (bcdec->mBase->mCopyAssignment) simpleAssignment = false; bcdec = bcdec->mNext; @@ -2202,6 +2226,8 @@ void Parser::AddDefaultConstructors(Declaration* pthis) simpleCopy = false; if (bdec->mCopyAssignment) simpleAssignment = false; + if (bdec->mMoveConstructor) + simpleMove = false; } if (dec->mValue) simpleConstructor = false; @@ -3242,16 +3268,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass by address // add a temporary variable - int nindex = mLocalIndex++; + //int nindex = mLocalIndex++; Declaration* rtdec = exp->mLeft->mDecType; + Declaration* vdec = AllocTempVar(rtdec); +#if 0 Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; vdec->mBase = rtdec; vdec->mSize = rtdec->mSize; - +#endif Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); vexp->mDecType = rtdec; vexp->mDecValue = vdec; @@ -3293,16 +3321,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass by address // add a temporary variable - int nindex = mLocalIndex++; +// int nindex = mLocalIndex++; Declaration* rtdec = exp->mLeft->mDecType; + Declaration* vdec = AllocTempVar(rtdec); +#if 0 Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; vdec->mBase = rtdec; vdec->mSize = rtdec->mSize; - +#endif Expression* vexp = new Expression(exp->mLocation, EX_VARIABLE); vexp->mDecType = rtdec; vexp->mDecValue = vdec; @@ -3361,16 +3391,18 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) // Returning a value object for pass as reference // add a temporary variable + Declaration* vdec = AllocTempVar(pex->mDecType); +#if 0 int nindex = mLocalIndex++; Declaration* vdec = new Declaration(exp->mLocation, DT_VARIABLE); vdec->mVarIndex = nindex; - vdec->mBase = pdec->mBase->mBase; - vdec->mSize = pdec->mBase->mBase->mSize; - + vdec->mBase = pex->mDecType; + vdec->mSize = pex->mDecType->mSize; +#endif Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); - vexp->mDecType = pdec->mBase->mBase; + vexp->mDecType = pex->mDecType; vexp->mDecValue = vdec; Expression* cexp = new Expression(pex->mLocation, pex->mType); @@ -3450,6 +3482,28 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) pex->mDecType = vdec->mBase; } } + else if ((pdec->mBase->mType == DT_TYPE_REFERENCE && !pex->IsConstRef()) || (pdec->mBase->mType == DT_TYPE_RVALUEREF && !pex->IsLValue())) + { + Declaration* vdec = AllocTempVar(pex->mDecType); + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pex->mDecType; + vexp->mDecValue = vdec; + + Expression* cexp = new Expression(pex->mLocation, pex->mType); + cexp->mDecType = pex->mDecType; + cexp->mDecValue = pex->mDecValue; + cexp->mLeft = pex->mLeft; + cexp->mRight = pex->mRight; + cexp->mToken = pex->mToken; + + pex->mType = EX_INITIALIZATION; + pex->mToken = TK_ASSIGN; + pex->mLeft = vexp; + pex->mRight = cexp; + pex->mDecValue = nullptr; + pex->mDecType = vdec->mBase; + } pdec = pdec->mNext; } @@ -3753,7 +3807,15 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex if (ctdec->mParams) mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter"); - PrependThisArgument(ctdec, pthis); + Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); + bthis->mFlags |= DTF_CONST | DTF_DEFINED; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = pthis->mBase->ToConstType(); + else + bthis->mBase = pthis->mBase; + bthis->mSize = 2; + + PrependThisArgument(ctdec, bthis); Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION); cdec->mBase = ctdec; @@ -4995,6 +5057,21 @@ Expression* Parser::ParseSimpleExpression(bool lhs) } 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); + } + break; + case TK_VOLATILE: case TK_STRUCT: case TK_CLASS: @@ -5314,6 +5391,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecValue = dec; exp->mDecType = dec->mBase; } + else if (dec->mType == DT_PACK_TYPE) + { + exp = new Expression(mScanner->mLocation, EX_PACK_TYPE); + exp->mDecValue = nullptr; + exp->mDecType = dec; + } else if (dec->mType <= DT_TYPE_FUNCTION) { if (lhs) @@ -5335,6 +5418,11 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecValue = dec; exp->mDecType = TheSignedIntTypeDeclaration; } + else if (dec->mType == DT_PACK_TEMPLATE) + { + exp = new Expression(mScanner->mLocation, EX_PACK_TYPE); + exp->mDecType = dec; + } else if (dec->mType == DT_ELEMENT) { mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent); @@ -5411,6 +5499,7 @@ Expression* Parser::ParseSimpleExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = ParsePrefixExpression(false); + nexp = CheckOperatorOverload(nexp); exp = nexp->ConstantFold(mErrors, mDataSection); } } @@ -5514,6 +5603,7 @@ Expression* Parser::ParseQualify(Expression* exp) uint64 mflags = 0; Declaration* mdec = nullptr; const Ident* ident = nullptr; + bool destructor = false; if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_BINARY_NOT) { @@ -5529,6 +5619,7 @@ Expression* Parser::ParseQualify(Expression* exp) } ident = ident->PreMangle("~"); + destructor = true; } else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); @@ -5628,6 +5719,12 @@ Expression* Parser::ParseQualify(Expression* exp) exp = nexp; } } + else if (destructor) + { + mScanner->NextToken(); + ConsumeToken(TK_OPEN_PARENTHESIS); + ConsumeToken(TK_CLOSE_PARENTHESIS); + } else { mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Struct member identifier not found", mScanner->mTokenIdent); @@ -5808,23 +5905,30 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else return NOOVERLOAD; - int ncast = 0; - Declaration* ext = ex->mDecType; - while (ext && !ext->IsConstSame(ptype->mBase)) + if (ptype->mBase->mTemplate) { - ncast++; - ext = ext->mBase; - } - - if (ext) - { - if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) - return NOOVERLOAD; - - dist += 32 * ncast; + dist += 16; } else - return NOOVERLOAD; + { + int ncast = 0; + Declaration* ext = ex->mDecType; + while (ext && !ext->IsConstSame(ptype->mBase)) + { + ncast++; + ext = ext->mBase; + } + + if (ext) + { + if ((etype->mFlags & DTF_CONST) && !(ptype->mBase->mFlags & DTF_CONST)) + return NOOVERLOAD; + + dist += 32 * ncast; + } + else + return NOOVERLOAD; + } } else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase)) dist += 2; @@ -5912,7 +6016,7 @@ bool Parser::CanCoerceExpression(Expression* exp, Declaration* type) { if (!type->IsConstSame(tdec)) { - Declaration* fcons = type->mScope->Lookup(type->mIdent->PreMangle("+")); + 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))) @@ -6148,7 +6252,12 @@ Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) if (ibest == NOOVERLOAD) { #if _DEBUG - int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); + fdec = exp->mLeft->mDecValue; + while (fdec) + { + int d = OverloadDistance(exp->mLeft->mDecValue, exp->mRight); + fdec = fdec->mNext; + } #endif mErrors->Error(exp->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching function call", exp->mLeft->mDecValue->mQualIdent); } @@ -6301,6 +6410,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) Expression* nexp = new Expression(mScanner->mLocation, EX_TYPECAST); nexp->mDecType = exp->mDecType; nexp->mLeft = pexp; + nexp = CheckOperatorOverload(nexp); exp = nexp->ConstantFold(mErrors, mDataSection); } else @@ -6639,20 +6749,33 @@ Expression* Parser::ParseNewOperator(void) if (mScanner->mToken == TK_OPEN_PARENTHESIS || dec->mDefaultConstructor) { Declaration* mdec = dec->mDefaultConstructor; + Expression* pexp = nullptr; - bool plist = false; if (ConsumeTokenIf(TK_OPEN_PARENTHESIS)) { if (!ConsumeTokenIf(TK_CLOSE_PARENTHESIS)) { - plist = true; - if (dec->mType == DT_TYPE_STRUCT) - mdec = dec->mScope->Lookup(dec->mIdent->PreMangle("+")); - else - mdec = nullptr; + pexp = ParseListExpression(false); + ConsumeToken(TK_CLOSE_PARENTHESIS); } } + if (dec->mType == DT_TYPE_STRUCT) + { + mdec = dec->mScope ? dec->mScope->Lookup(dec->mIdent->PreMangle("+")) : nullptr; + if (pexp && pexp->mType != EX_LIST) + { + if (pexp->mDecType->IsSame(dec)) + mdec = dec->mCopyConstructor; + else if (pexp->mDecType->mType == DT_TYPE_REFERENCE && pexp->mDecType->mBase->IsSame(dec)) + mdec = dec->mCopyConstructor; + else if (pexp->mDecType->mType == DT_TYPE_RVALUEREF && pexp->mDecType->mBase->IsSame(dec)) + mdec = dec->mMoveConstructor; + } + } + else + mdec = nullptr; + if (mdec) { Declaration* vdec = new Declaration(mScanner->mLocation, DT_VARIABLE); @@ -6670,19 +6793,10 @@ Expression* Parser::ParseNewOperator(void) iexp->mRight = nexp; iexp->mDecType = nexp->mDecType; - Expression* pexp = vexp; - - if (plist) - { - pexp = ParseListExpression(false); - - ConsumeToken(TK_CLOSE_PARENTHESIS); - - Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); - lexp->mLeft = vexp; - lexp->mRight = pexp; - pexp = lexp; - } + Expression* lexp = new Expression(mScanner->mLocation, EX_LIST); + lexp->mLeft = vexp; + lexp->mRight = pexp; + pexp = lexp; Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); cexp->mDecValue = mdec; @@ -6718,32 +6832,25 @@ Expression* Parser::ParseNewOperator(void) nexp->mRight = coexp; nexp->mDecType = coexp->mDecType; } - else if (plist && !mdec) + else if (pexp && pexp->mType != EX_LIST) { - Expression * pexp = ParseListExpression(false); - ConsumeToken(TK_CLOSE_PARENTHESIS); - - if (pexp && pexp->mType != EX_LIST) - { - Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); - dexp->mToken = TK_MUL; - dexp->mLeft = nexp; - dexp->mDecType = nexp->mDecType->mBase; - - Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); - iexp->mToken = TK_ASSIGN; - iexp->mLeft = dexp; - iexp->mRight = pexp; - iexp->mDecType = nexp->mDecType; - - nexp = iexp; - } - else - mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_MUL; + dexp->mLeft = nexp; + dexp->mDecType = nexp->mDecType->mBase; + Expression* iexp = new Expression(mScanner->mLocation, EX_INITIALIZATION); + iexp->mToken = TK_ASSIGN; + iexp->mLeft = dexp; + iexp->mRight = pexp; + iexp->mDecType = nexp->mDecType; + nexp = new Expression(mScanner->mLocation, EX_PREFIX); + nexp->mToken = TK_BINARY_AND; + nexp->mDecType = nexp->mDecType; + nexp->mLeft = iexp; } - else if (plist) + else if (pexp) { mErrors->Error(mScanner->mLocation, ERRO_NO_MATCHING_FUNCTION_CALL, "No matching constructor", dec->mIdent); } @@ -7880,6 +7987,56 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } + else if (exp->mType == EX_TYPECAST) + { + Declaration* tdec = exp->mLeft->mDecType; + if (exp->mLeft->mDecType) + { + while (tdec->mType == DT_TYPE_REFERENCE || tdec->mType == DT_TYPE_RVALUEREF) + tdec = tdec->mBase; + + if (tdec->mType == DT_TYPE_STRUCT) + { + Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("(cast)")); + while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType)) + mdec = mdec->mNext; + while (!mdec && tdec->mBase && tdec->mBase->mBase) + { + tdec = tdec->mBase->mBase; + mdec = tdec->mScope->Lookup(Ident::Unique("(cast)")); + while (mdec && !mdec->mBase->mBase->IsSame(exp->mDecType)) + mdec = mdec->mNext; + } + + if (mdec) + { + Expression* nexp = new Expression(mScanner->mLocation, EX_CALL); + + nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT); + nexp->mLeft->mDecType = mdec->mBase; + nexp->mLeft->mDecValue = mdec; + + nexp->mDecType = mdec->mBase; + nexp->mRight = exp->mRight; + + Expression* texp = new Expression(nexp->mLocation, EX_PREFIX); + texp->mToken = TK_BINARY_AND; + texp->mLeft = exp->mLeft; + texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); + texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; + texp->mDecType->mBase = tdec; + texp->mDecType->mSize = 2; + + nexp->mRight = texp->ConstantFold(mErrors, mDataSection); + + nexp = ResolveOverloadCall(nexp); + nexp->mDecType = nexp->mLeft->mDecType->mBase; + + exp = nexp; + } + } + } + } else if (exp->mType == EX_LOGICAL_NOT) { const Ident* opident = Ident::Unique("operator!"); @@ -8133,6 +8290,30 @@ Expression* Parser::ParseFunction(Declaration * dec) return exp; } +void Parser::SkipStatement(void) +{ + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int cnt = 1; + while (cnt > 0) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + cnt++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + cnt--; + else + mScanner->NextToken(); + } + } + else + { + while (!ConsumeTokenIf(TK_SEMICOLON)) + { + mScanner->NextToken(); + } + } +} + Expression* Parser::ParseStatement(void) { Expression* exp = nullptr; @@ -8202,34 +8383,45 @@ Expression* Parser::ParseStatement(void) case TK_IF: { mScanner->NextToken(); - bool constExp = ConsumeTokenIf(TK_CONSTEXPR); - exp = new Expression(mScanner->mLocation, EX_IF); - exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); - exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); - exp->mRight->mLeft = ParseStatement(); - if (mScanner->mToken == TK_ELSE) + + if (ConsumeTokenIf(TK_CONSTEXPR)) { - mScanner->NextToken(); - exp->mRight->mRight = ParseStatement(); - } - else - exp->mRight->mRight = nullptr; - - if (constExp) - { - Expression * cexp = exp->mLeft->ConstantFold(mErrors, mDataSection); - if (cexp->mType == EX_CONSTANT && cexp->mDecValue->mType == DT_CONST_INTEGER) + exp = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration)->ConstantFold(mErrors, mDataSection); + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) { - if (cexp->mDecValue->mInteger) - exp = exp->mRight->mLeft; - else if (exp->mRight->mRight) - exp = exp->mRight->mRight; + if (exp->mDecValue->mInteger) + { + exp = ParseStatement(); + if (ConsumeTokenIf(TK_ELSE)) + SkipStatement(); + } else - exp = new Expression(mScanner->mLocation, EX_VOID); + { + SkipStatement(); + if (ConsumeTokenIf(TK_ELSE)) + exp = ParseStatement(); + else + exp = new Expression(mScanner->mLocation, EX_VOID); + } } else mErrors->Error(exp->mLocation, EERR_INVALID_CONSTEXPR, "Condition is not constant"); } + else + { + exp = new Expression(mScanner->mLocation, EX_IF); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); + exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); + exp->mRight->mLeft = ParseStatement(); + if (mScanner->mToken == TK_ELSE) + { + mScanner->NextToken(); + exp->mRight->mRight = ParseStatement(); + } + else + exp->mRight->mRight = nullptr; + } + } break; case TK_WHILE: { @@ -8663,9 +8855,10 @@ Expression* Parser::ParseStatement(void) exp->mLeft = ParseRExpression(); if (mFunctionType && mFunctionType->mBase) { - if (mFunctionType->mBase->mType == DT_TYPE_AUTO) + if (mFunctionType->mBase->mType == DT_TYPE_AUTO || mFunctionType->mBase->IsReference() && mFunctionType->mBase->mBase->mType == DT_TYPE_AUTO) { - mFunctionType->mBase = exp->mLeft->mDecType; + mFunctionType->mBase = mFunctionType->mBase->DeduceAuto(exp->mLeft->mDecType); + ; if (mFunctionType->mBase->mType == DT_TYPE_STRUCT) { // Make room for value struct return @@ -8835,11 +9028,323 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } +int Parser::ExpansionDistance(Declaration* tdec, Declaration* spec) +{ + Declaration* ptdec = tdec->mParams; + Declaration* psdec = spec->mParams; + + int cost = 0; + if (tdec->mParser) + cost = 100000; + + while (ptdec && psdec) + { + if (ptdec->mType == DT_CONST_TEMPLATE && psdec->mType == DT_CONST_TEMPLATE) + { + if (ptdec->mBase) + { + if (ptdec->mBase->mInteger != psdec->mBase->mInteger) + return NOOVERLOAD; + } + else + cost += 100; + } + else if (ptdec->mType == DT_TYPE_TEMPLATE && psdec->mType == DT_TYPE_TEMPLATE) + { + if (ptdec->mBase) + { + if (!ptdec->mBase->IsSame(psdec->mBase)) + return NOOVERLOAD; + } + else + cost += 100; + } + else if (ptdec->mType == DT_PACK_TEMPLATE && psdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + + Declaration* tvp = ptdec->mBase->mParams; + Declaration* svp = psdec->mBase->mParams; + + while (tvp && svp && tvp->IsSame(svp)) + { + tvp = tvp->mNext; + svp = svp->mNext; + } + + if (tvp || svp) + return NOOVERLOAD; + } + else if (psdec->mBase) + { + Declaration* dec = psdec->mBase->mParams; + while (dec) + { + cost += 200; + dec = dec->mNext; + } + } + } + else if (ptdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + ptdec = ptdec->mBase->mParams; + continue; + } + else + { + while (psdec) + { + cost += 200; + psdec = psdec->mNext; + } + + return cost; + } + } + else + return NOOVERLOAD; + + ptdec = ptdec->mNext; + psdec = psdec->mNext; + } + + if (ptdec && ptdec->mType == DT_PACK_TEMPLATE) + { + if (ptdec->mBase) + { + if (ptdec->mBase->mParams) + return NOOVERLOAD; + } + else + cost += 50; + } + else if (ptdec || psdec) + return NOOVERLOAD; + + return cost; +} + 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 + { + 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) + { + 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); + } + } + + while (!tmpld->mTokens) + tmpld = tmpld->mNext; + + Declaration* epdec = tdec->mParams; + while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE && epdec->mBase->mType != DT_PACK_TEMPLATE) + epdec = epdec->mNext; + + if (epdec) + { + // Partial template specification + Declaration* bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType); + tdec->mBase = bdec; + bdec->mTemplate = tdec; + bdec->mBase = tmpld->mBase->mBase; + tdec->mNext = tmpld; + bdec->mIdent = tdec->MangleIdent(); + + return bdec; + } + + Declaration* pthis = tmpld->mClass; + + int mindist = NOOVERLOAD; + Declaration* etdec = nullptr; + + Declaration* dec = tmpld; + while (dec) + { + int dist = ExpansionDistance(dec, tdec); + if (dist < mindist) + { + mindist = dist; + etdec = dec; + } + dec = dec->mNext; + } + + if (mindist == 0) + return etdec->mBase; + else if (mindist == NOOVERLOAD) + mErrors->Error(tdec->mLocation, EERR_TEMPLATE_PARAMS, "No matching template parameters"); + else + tmpld = etdec; + + dec = tdec->mParams; + Declaration * pdec = tmpld->mParams; + + Declaration * ppdec = nullptr; + while (pdec) + { + if (pdec->mType == DT_PACK_TEMPLATE) + { + if (!dec) + { + 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; + } + else if (dec->mType != DT_PACK_TEMPLATE) + { + Declaration* packd = new Declaration(dec->mLocation, DT_PACK_TEMPLATE); + packd->mBase = new Declaration(dec->mLocation, DT_PACK_TYPE); + if (ppdec) + ppdec->mNext = packd; + else + tdec->mParams = packd; + + ppdec = nullptr; + while (dec) + { + Declaration* ndec = dec->mBase->Clone(); + + if (ppdec) + ppdec->mNext = ndec; + else + packd->mBase->mParams = ndec; + ppdec = ndec; + dec = dec->mNext; + } + + dec = packd; + } + } + + if (dec) + { + dec->mIdent = pdec->mIdent; + tdec->mScope->Insert(dec->mIdent, dec->mBase); + + ppdec = dec; + dec = dec->mNext; + } + + pdec = pdec->mNext; + } + + +#else if (expd) { if (tmpld->mBase->mType == DT_TEMPLATE) @@ -8971,112 +9476,90 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp Declaration* etdec = tmpld->mNext; while (etdec && !etdec->IsSameParams(tdec)) etdec = etdec->mNext; - if (etdec) +#endif + + Parser* p = tmpld->mParser->Clone(); + + p->mScanner->Replay(tmpld->mTokens); + + tdec->mScope->mName = tdec->MangleIdent(); + tdec->mNext = tmpld->mNext; + tmpld->mNext = tdec; + + tdec->mScope->mParent = tmpld->mScope->mParent; + + p->mTemplateScope = tdec->mScope; + if (tmpld->mFlags & DTF_AUTO_TEMPLATE) { - return etdec->mBase; + Declaration * ndec = tmpld->mBase->ExpandTemplate(tdec->mScope); + + Declaration* pdec = tmpld->mBase; + + if (pdec) + { + Declaration* pcdec = nullptr; + + while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) + { + pcdec = pdec; + pdec = pdec->mNext; + } + + if (!pdec) + pcdec->mNext = ndec; + } + + tdec->mBase = ndec; + ndec->mValue = p->ParseFunction(ndec->mBase); + ndec->mFlags |= DTF_DEFINED; + + ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); + ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); } else { - Declaration* epdec = tdec->mParams; - while (epdec && epdec->mBase && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) - epdec = epdec->mNext; - - if (epdec) - { - // Partial template specification - Declaration * bdec = new Declaration(mScanner->mLocation, tmpld->mBase->mType); - tdec->mBase = bdec; - bdec->mTemplate = tdec; - bdec->mBase = tmpld->mBase->mBase; - tdec->mNext = tmpld; - bdec->mIdent = tdec->MangleIdent(); - - return bdec; - } - - Parser* p = tmpld->mParser->Clone(); - - p->mScanner->Replay(tmpld->mTokens); - - tdec->mScope->mName = tdec->MangleIdent(); - tdec->mNext = tmpld->mNext; - tmpld->mNext = tdec; - - tdec->mScope->mParent = tmpld->mScope->mParent; - - p->mTemplateScope = tdec->mScope; - if (tmpld->mFlags & DTF_AUTO_TEMPLATE) - { - Declaration * ndec = tmpld->mBase->ExpandTemplate(tdec->mScope); - - Declaration* pdec = tmpld->mBase; - - if (pdec) - { - Declaration* pcdec = nullptr; - - while (pdec && !ndec->mBase->IsSameParams(pdec->mBase)) - { - pcdec = pdec; - pdec = pdec->mNext; - } - - if (!pdec) - pcdec->mNext = ndec; - } - - tdec->mBase = ndec; - ndec->mValue = p->ParseFunction(ndec->mBase); - ndec->mFlags |= DTF_DEFINED; - - ndec->mIdent = ndec->mIdent->Mangle(tdec->mScope->mName->mString); - ndec->mQualIdent = ndec->mQualIdent->Mangle(tdec->mScope->mName->mString); - } - else - { - tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); - } - - p->mTemplateScope = nullptr; - - if (tdec->mBase->mType == DT_ANON) - { - tdec->mBase = tdec->mBase->mBase; - mCompilationUnits->mTemplateScope->Insert(tmpld->mQualIdent, tmpld); - - tdec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) - { - if (mdec->mType == DT_CONST_FUNCTION) - { - while (mdec) - { - if (!(mdec->mFlags & DTF_DEFINED)) - { - Declaration* mpdec = mCompilationUnits->mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); - while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) - mpdec = mpdec->mNext; - if (mpdec && mpdec->mTemplate) - { - if (mdec->mTemplate) - { - Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); - mtdec->mClass = mdec->mTemplate->mClass; - mdec->mTemplate = mtdec; - mdec->mTemplate->mBase = mdec; - } - else - p->ParseTemplateExpansion(mpdec->mTemplate, tdec); - } - } - - mdec = mdec->mNext; - } - } - }); - } - - return tdec->mBase; + tdec->mBase = p->ParseDeclaration(nullptr, true, false, tmpld->mClass, tdec); } + + p->mTemplateScope = nullptr; + + if (tdec->mBase->mType == DT_ANON) + { + tdec->mBase = tdec->mBase->mBase; + mCompilationUnits->mTemplateScope->Insert(tmpld->mQualIdent, tmpld); + + tdec->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + if (!(mdec->mFlags & DTF_DEFINED)) + { + Declaration* mpdec = mCompilationUnits->mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + while (mpdec && !mdec->mBase->IsTemplateSameParams(mpdec->mBase, tdec)) + mpdec = mpdec->mNext; + if (mpdec && mpdec->mTemplate) + { + if (mdec->mTemplate) + { + Declaration * mtdec = p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + mtdec->mClass = mdec->mTemplate->mClass; + mdec->mTemplate = mtdec; + mdec->mTemplate->mBase = mdec; + } + else + p->ParseTemplateExpansion(mpdec->mTemplate, tdec); + } + } + + mdec = mdec->mNext; + } + } + }); + } + + return tdec->mBase; } void Parser::CompleteTemplateExpansion(Declaration* tmpld) @@ -9121,7 +9604,7 @@ Declaration* Parser::FunctionAutoParamsToTemplate(Declaration* fdec) { Declaration* tdec = new Declaration(fdec->mLocation, DT_TEMPLATE); tdec->mParser = this->Clone(); - tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + tdec->mScope = new DeclarationScope(mTemplateScope, SLEVEL_TEMPLATE); Declaration* ppdec = nullptr; int ntp = 0; @@ -9221,60 +9704,63 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) Declaration* ppdec = nullptr; ConsumeToken(TK_LESS_THAN); - for (;;) + if (mScanner->mToken != TK_GREATER_THAN) { - Declaration* pdec = nullptr; - - if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) + for (;;) { - if (ConsumeTokenIf(TK_ELLIPSIS)) + Declaration* pdec = nullptr; + + if (ConsumeTokenIf(TK_CLASS) || ConsumeTokenIf(TK_TYPENAME)) { - if (mScanner->mToken == TK_IDENT) + if (ConsumeTokenIf(TK_ELLIPSIS)) { - pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_PACK_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + } + else if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; mScanner->NextToken(); } else mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); } - else if (mScanner->mToken == TK_IDENT) + else if (ConsumeTokenIf(TK_INT)) { - pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); - pdec->mIdent = mScanner->mTokenIdent; - mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); + pdec->mIdent = mScanner->mTokenIdent; + mScanner->NextToken(); + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); } else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); - } - else if (ConsumeTokenIf(TK_INT)) - { - if (mScanner->mToken == TK_IDENT) + mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter"); + + if (pdec) { - pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); - pdec->mIdent = mScanner->mTokenIdent; - mScanner->NextToken(); + tdec->mScope->Insert(pdec->mIdent, pdec); + pdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = pdec; + else + tdec->mParams = pdec; + ppdec = pdec; } - else - mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + if (!ConsumeTokenIf(TK_COMMA)) + break; } - else - mErrors->Error(mScanner->mLocation, EERR_TEMPLATE_PARAMS, "'class' or 'int' expected as template parameter"); - - if (pdec) - { - tdec->mScope->Insert(pdec->mIdent, pdec); - pdec->mFlags |= DTF_DEFINED; - - if (ppdec) - ppdec->mNext = pdec; - else - tdec->mParams = pdec; - ppdec = pdec; - } - - if (!ConsumeTokenIf(TK_COMMA)) - break; } ConsumeToken(TK_GREATER_THAN); @@ -9295,7 +9781,7 @@ Declaration * Parser::ParseTemplateDeclaration(Declaration* pthis) void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthis) { mScanner->BeginRecord(); - if (mScanner->mToken == TK_CLASS) + if (mScanner->mToken == TK_CLASS || mScanner->mToken == TK_STRUCT) { // Class template Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); @@ -9404,7 +9890,24 @@ void Parser::ParseTemplateDeclarationBody(Declaration * tdec, Declaration * pthi tdec->mScope->mName = tdec->mQualIdent; if (tdec->mQualIdent == mScope->Mangle(tdec->mIdent)) - mScope->Insert(tdec->mIdent, tdec->mBase); + { + Declaration* pdec = mScope->Insert(tdec->mIdent, tdec->mBase); + if (pdec) + { + Declaration* ppdec = pdec; + while (pdec && !pdec->IsSameTemplate(tdec->mBase)) + { + ppdec = pdec; + pdec = pdec->mNext; + } + + if (pdec && pdec->mTemplate) + { + tdec->mNext = pdec->mTemplate->mNext; + pdec->mTemplate->mNext = tdec; + } + } + } Declaration* pdec = mCompilationUnits->mScope->Insert(tdec->mQualIdent, tdec->mBase); if (pdec) diff --git a/oscar64/Parser.h b/oscar64/Parser.h index b0f5e9e..ade1d6c 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -91,6 +91,7 @@ protected: Declaration* ParseQualIdent(void); + void SkipStatement(void); Expression* ParseStatement(void); Expression* ParseSwitchStatement(void); @@ -109,6 +110,7 @@ protected: void ParseTemplateDeclarationBody(Declaration* tdec, Declaration* pthis); Declaration* FunctionAutoParamsToTemplate(Declaration* fdec); + int ExpansionDistance(Declaration* tdec, Declaration* spec); Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); void CompleteTemplateExpansion(Declaration* tmpld); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 849a06e..472c04e 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -148,6 +148,7 @@ const char* TokenNames[] = "'#repeat'", "'#until'", "'#embed'", + "'#for'", "'##'", "'namespace'", @@ -596,6 +597,84 @@ void Scanner::NextPreToken(void) mPreprocessor->CloseSource(); } } + else if (mToken == TK_PREP_FOR) + { + NextRawToken(); + if (mToken == TK_OPEN_PARENTHESIS) + { + NextRawToken(); + Macro* macro = new Macro(Ident::Unique("@for"), nullptr); + if (mToken == TK_IDENT) + { + const Ident* loopindex = mTokenIdent; + NextRawToken(); + + if (mToken == TK_COMMA) + { + mPreprocessorMode = true; + NextToken(); + int64 loopCount = PrepParseConditional(); + mPreprocessorMode = false; + + if (mToken == TK_CLOSE_PARENTHESIS) + { + int slen = mOffset; + bool quote = false; + while (mLine[slen] && (quote || mLine[slen] != '/' || mLine[slen + 1] != '/')) + { + if (mLine[slen] == '"') + quote = !quote; + slen++; + } + + macro->SetString(mLine + mOffset, slen - mOffset); + + mOffset = slen; + while (mLine[mOffset]) + mOffset++; + + if (loopCount > 0) + { + MacroExpansion* ex = new MacroExpansion(); + MacroDict* scope = mDefineArguments; + mDefineArguments = new MacroDict(); + + Macro* arg = new Macro(loopindex, scope); + mDefineArguments->Insert(arg); + + arg->SetString("0"); + + ex->mLine = mLine; + ex->mOffset = mOffset; + ex->mLink = mMacroExpansion; + ex->mChar = mTokenChar; + ex->mLoopCount = 0; + ex->mLoopIndex = arg; + ex->mLoopLimit = loopCount; + + mMacroExpansion = ex; + mMacroExpansionDepth++; + if (mMacroExpansionDepth > 1024) + mErrors->Error(mLocation, EFATAL_MACRO_EXPANSION_DEPTH, "Maximum macro expansion depth exceeded", mTokenIdent); + mLine = macro->mString; + mOffset = 0; + NextChar(); + } + } + else + mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "')' expected in defined parameter list"); + } + else + mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "',' expected"); + + } + else + mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'loop index variable expected"); + } + else + mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "'('(' expected"); + + } else if (mToken == TK_PREP_DEFINE) { NextRawToken(); @@ -1313,6 +1392,8 @@ void Scanner::NextRawToken(void) mToken = TK_PREP_UNTIL; else if (!strcmp(tkprep, "embed")) mToken = TK_PREP_EMBED; + else if (!strcmp(tkprep, "for")) + mToken = TK_PREP_FOR; else mErrors->Error(mLocation, EERR_INVALID_PREPROCESSOR, "Invalid preprocessor command", tkprep); } @@ -1912,6 +1993,19 @@ bool Scanner::NextChar(void) { if (mMacroExpansion) { + if (mMacroExpansion->mLoopIndex) + { + mMacroExpansion->mLoopCount++; + if (mMacroExpansion->mLoopCount < mMacroExpansion->mLoopLimit) + { + char buffer[20]; + sprintf_s(buffer, "%d", int(mMacroExpansion->mLoopCount)); + mMacroExpansion->mLoopIndex->SetString(buffer); + mOffset = 0; + continue; + } + } + MacroExpansion* mac = mMacroExpansion->mLink; // delete mDefineArguments; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 9d6ade7..8db05ac 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -146,6 +146,7 @@ enum Token TK_PREP_REPEAT, TK_PREP_UNTIL, TK_PREP_EMBED, + TK_PREP_FOR, TK_PREP_CONCAT, @@ -284,7 +285,14 @@ protected: const char * mLine; int mOffset; char mChar; + Macro * mLoopIndex; + int64 mLoopCount, mLoopLimit; MacroDict* mDefinedArguments; + + MacroExpansion(void) + : mLink(nullptr), mLine(nullptr), mOffset(0), mChar(0), mLoopIndex(nullptr), mLoopCount(0), mLoopLimit(0), mDefinedArguments(nullptr) + {} + } * mMacroExpansion; int mMacroExpansionDepth;