diff --git a/include/opp/algorithm.h b/include/opp/algorithm.h index d3d692e..b1d8807 100644 --- a/include/opp/algorithm.h +++ b/include/opp/algorithm.h @@ -35,6 +35,32 @@ void sort(T s, T e) } } +template +void sort(T s, T e, LF lt) +{ + while (s != e) + { + auto p = s; + auto q = s; + + q++; + while (q != e) + { + if (lt(*q, *p)) + { + swap(*q, *p); + p++; + swap(*q, *p); + } + q++; + } + + sort(s, p, lt); + p++; + s = p; + } +} + template OI copy(II first, II last, OI result) { diff --git a/include/opp/bidxlist.h b/include/opp/bidxlist.h new file mode 100644 index 0000000..064f9a4 --- /dev/null +++ b/include/opp/bidxlist.h @@ -0,0 +1,207 @@ +#ifndef OPP_BIDXLIST_H +#ifndef OPP_BIDXLIST_H + +template +class bindexlist +{ +public: + char _free; + char _pred[n], _succ[n]; + T _data[n]; + + class iterator + { + public: + bindexlist * _l; + char _i; + + iterator(void) : _l(nullptr) {} + iterator(bindexlist * l, char i) + : _l(l), _i(i) {} + + iterator(const iterator & li) : _l(li._l), _i(li._i) {} + iterator & operator=(const iterator & li) + { + _l = li._l; + _i = li._i; + return *this; + } + + T & operator*() + { + return _l->_data[_i]; + } + + T * operator->() + { + return _l->_data + _i; + } + + iterator & operator++(void) + { + _i = _l->_succ[_i]; + return *this; + } + + iterator operator++(int) + { + char i = _i; + _i = _l->_succ[_i]; + return bindexlist::iterator(_l, i); + } + + iterator & operator+=(char n) + { + while (n--) + _i = _l->_succ[_i]; + return *this; + } + + iterator & operator--(void) + { + _i = _l->_pred[_i]; + return *this; + } + + iterator operator++(int) + { + char i = _i; + _i = _l->_pred[_i]; + return bindexlist::iterator(_l, i); + } + + iterator & operator-=(char n) + { + while (n--) + _i = _l->_pred[_i]; + return *this; + } + + bool operator==(const iterator & li) + { + return _i == li._i; + } + + bool operator!=(const iterator & li) + { + return _i != li._i; + } + }; + +public: + typedef T element_type; + typedef iterator iterator_type; + + bindexlist(void) + { + _succ[0] = 0; + _pred[0] = 0; + for(char i=1; i -class listnode +class listhead { public: - listnode * succ, * pred; - T data; + listnode * succ, * pred; - listnode() + listhead() { - succ = this; - pred = this; + succ = (listnode *)this; + pred = (listnode *)this; } +}; + +template +class listnode : public listhead +{ +public: + T data; listnode(const T & t) : data(t) {} listnode(T && t) : data(t) {} @@ -41,6 +47,11 @@ public: return node->data; } + T * operator->() + { + return &(node->data); + } + list_iterator & operator++(void) { node = node->succ; @@ -98,7 +109,8 @@ template class list { private: - listnode node; + typedef listnode ln; + listhead head; public: typedef T element_type; typedef list_iterator iterator_type; @@ -108,8 +120,8 @@ public: ~list(void) { - listnode * n = node.succ; - while (n != &node) + listnode * n = head.succ; + while (n != &head) { listnode * m = n->succ; delete n; @@ -119,32 +131,32 @@ public: list_iterator begin(void) { - return list_iterator(node.succ); + return list_iterator(head.succ); } list_iterator end(void) { - return list_iterator(&node); + return list_iterator((listnode *)&head); } T & front(void) { - return node.succ->data; + return head.succ->data; } const T & front(void) const { - return node.succ->data; + return head.succ->data; } T & back(void) { - return node.pred->data; + return head.pred->data; } const T & back(void) const { - return node.pred->data; + return head.pred->data; } list_iterator erase(list_iterator it); @@ -171,18 +183,18 @@ public: template void list::pop_front(void) { - listnode * n = node.succ; - node.succ = n->succ; - n->succ->pred = &node; + listnode * n = head.succ; + head.succ = n->succ; + n->succ->pred = (listnode *)&head; delete n; } template void list::pop_back(void) { - listnode * n = node.pred; - node.pred = n->pred; - n->pred->succ = &node; + listnode * n = head.pred; + head.pred = n->pred; + n->pred->succ = (listnode *)&head; delete n; } @@ -190,40 +202,40 @@ template void list::push_front(const T & t) { listnode * n = new listnode(t); - n->pred = &node; - n->succ = node.succ; - node.succ->pred = n; - node.succ = n; + n->pred = (listnode *)&head; + n->succ = head.succ; + head.succ->pred = n; + head.succ = n; } template void list::push_front(T && t) { listnode * n = new listnode(t); - n->pred = &node; - n->succ = node.succ; - node.succ->pred = n; - node.succ = n; + n->pred = (listnode *)&head; + n->succ = head.succ; + head.succ->pred = n; + head.succ = n; } template void list::push_back(const T & t) { listnode * n = new listnode(t); - n->succ = &node; - n->pred = node.pred; - node.pred->succ = n; - node.pred = n; + n->succ = (listnode *)&head; + n->pred = head.pred; + head.pred->succ = n; + head.pred = n; } template void list::push_back(T && t) { listnode * n = new listnode(t); - n->succ = &node; - n->pred = node.pred; - node.pred->succ = n; - node.pred = n; + n->succ = (listnode *)&head; + n->pred = head.pred; + head.pred->succ = n; + head.pred = n; } diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 4b00406..6a8995b 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -954,6 +954,20 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = mQualIdent; } + else if (mType == DT_TYPE_FUNCTION) + { + mMangleIdent = mBase->MangleIdent(); + mMangleIdent = mMangleIdent->Mangle("(*)("); + Declaration* dec = mParams; + while (dec) + { + mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString); + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + mMangleIdent = mMangleIdent->Mangle(")"); + } else if (mType == DT_TYPE_INTEGER) { char buffer[20]; @@ -964,6 +978,10 @@ const Ident* Declaration::MangleIdent(void) { mMangleIdent = Ident::Unique("float"); } + else if (mType == DT_TYPE_BOOL) + { + mMangleIdent = Ident::Unique("bool"); + } else if (mType == DT_TYPE_REFERENCE) { mMangleIdent = mBase->MangleIdent()->PreMangle("&"); @@ -1172,6 +1190,36 @@ bool Declaration::ResolveTemplate(Declaration* fdec, Declaration* tdec) return true; } + else if (tdec->mType == DT_TYPE_STRUCT && fdec->mType == DT_TYPE_STRUCT && tdec->mTemplate) + { + Declaration *ftdec = tdec->mTemplate; + while (ftdec) + { + if (ftdec->mBase == fdec) + { + Declaration* fpdec = ftdec->mParams; + Declaration* tpdec = tdec->mTemplate->mParams; + + while (fpdec) + { + if (tpdec->mBase->mType == DT_TYPE_TEMPLATE || tpdec->mBase->mType == DT_CONST_TEMPLATE) + { + Declaration * pdec = mScope->Insert(tpdec->mIdent, fpdec->mBase); + if (pdec && !pdec->IsSame(fpdec->mBase)) + return false; + } + + fpdec = fpdec->mNext; + tpdec = tpdec->mNext; + } + + return true; + } + + ftdec = ftdec->mNext; + } + return false; + } else return tdec->CanAssign(fdec); } @@ -1632,7 +1680,9 @@ bool Declaration::IsSame(const Declaration* dec) const if ((mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE)) != (dec->mFlags & (DTF_SIGNED | DTF_CONST | DTF_VOLATILE))) return false; - if (mType == DT_TYPE_INTEGER) + if (mType == DT_CONST_INTEGER) + return mInteger == dec->mInteger; + else if (mType == DT_TYPE_INTEGER) return true; else if (mType == DT_TYPE_BOOL || mType == DT_TYPE_FLOAT || mType == DT_TYPE_VOID) return true; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 5d6d5bb..e38ea70 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -4548,6 +4548,10 @@ void InterCodeBasicBlock::Append(InterInstruction * code) assert(code->mConst.mVarIndex < mProc->mModule->mGlobalVars.Size()); assert(mProc->mModule->mGlobalVars[code->mConst.mVarIndex]); } + if (code->mCode == IC_STORE) + { + assert(code->mSrc[1].mOperandSize > 0); + } if (code->mDst.mTemp >= 0) assert(code->mDst.mType != IT_NONE); for (int i = 0; i < code->mNumOperands; i++) @@ -7484,7 +7488,28 @@ void InterCodeBasicBlock::UpdateLocalIntegerRangeSets(const GrowingVariableArray if (s0 < 0) { mTrueValueRange[s1].LimitMax(mInstructions[sz - 2]->mSrc[0].mIntConst); + mTrueValueRange[s1].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[1].mType)); mFalseValueRange[s1].LimitMin(mInstructions[sz - 2]->mSrc[0].mIntConst + 1); + mFalseValueRange[s1].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[1].mType)); + } + else if (s1 < 0) + { + mTrueValueRange[s0].LimitMin(mInstructions[sz - 2]->mSrc[1].mIntConst); + mTrueValueRange[s0].LimitMaxWeak(SignedTypeMax(mInstructions[sz - 2]->mSrc[0].mType)); + mFalseValueRange[s0].LimitMax(mInstructions[sz - 2]->mSrc[1].mIntConst - 1); + mFalseValueRange[s0].LimitMinWeak(SignedTypeMin(mInstructions[sz - 2]->mSrc[0].mType)); + } + else + { + if (mLocalValueRange[s0].mMaxState == IntegerValueRange::S_BOUND) + mFalseValueRange[s1].LimitMin(mLocalValueRange[s0].mMinValue + 1); + if (mLocalValueRange[s0].mMinState == IntegerValueRange::S_BOUND) + mTrueValueRange[s1].LimitMax(mLocalValueRange[s0].mMaxValue); + + if (mLocalValueRange[s1].mMaxState == IntegerValueRange::S_BOUND) + mFalseValueRange[s0].LimitMax(mLocalValueRange[s1].mMaxValue - 1); + if (mLocalValueRange[s1].mMinState == IntegerValueRange::S_BOUND) + mTrueValueRange[s0].LimitMin(mLocalValueRange[s1].mMinValue); } break; case IA_CMPGS: @@ -8247,6 +8272,44 @@ bool InterCodeBasicBlock::RemoveUnusedResultInstructions(void) return changed; } +bool InterCodeBasicBlock::RemoveUnusedLocalStoreInstructions(void) +{ + bool changed = false; + + if (!mVisited) + { + mVisited = true; + if (mInstructions.Size() > 0 && mInstructions.Last()->mCode == IC_RETURN) + { + int i = mInstructions.Size(); + while (i > 0) + { + i--; + InterInstruction* ins = mInstructions[i]; + if (ins->mCode == IC_STORE && ins->mSrc[1].mTemp < 0 && ins->mSrc[1].mMemory == IM_LOCAL) + { + ins->mCode = IC_NONE; + ins->mNumOperands = 0; + changed = true; + } + else if (ins->mCode == IC_LOAD) + break; + else if (ins->mCode == IC_CALL || ins->mCode == IC_CALL_NATIVE) + break; + else if (ins->mCode == IC_COPY || ins->mCode == IC_STRCPY) + break; + } + } + + if (mTrueJump && mTrueJump->RemoveUnusedLocalStoreInstructions()) + changed = true; + if (mFalseJump && mFalseJump->RemoveUnusedLocalStoreInstructions()) + changed = true; + } + + return false; +} + void InterCodeBasicBlock::BuildCallerSaveTempSet(NumberSet& callerSaveTemps) { if (!mVisited) @@ -16371,6 +16434,15 @@ void InterCodeProcedure::RemoveUnusedInstructions(void) } while (mEntryBlock->RemoveUnusedResultInstructions()); } +void InterCodeProcedure::RemoveUnusedLocalStoreInstructions(void) +{ + if (mCompilerOptions & COPT_OPTIMIZE_BASIC) + { + ResetVisited(); + mEntryBlock->RemoveUnusedLocalStoreInstructions(); + } +} + void InterCodeProcedure::RemoveUnusedStoreInstructions(InterMemory paramMemory) { if (mCompilerOptions & COPT_OPTIMIZE_BASIC) @@ -16849,7 +16921,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "opp::sort::iterator,>"); mEntryBlock = mBlocks[0]; @@ -17471,6 +17543,8 @@ void InterCodeProcedure::Close(void) RemoveUnusedInstructions(); #endif + RemoveUnusedLocalStoreInstructions(); + #if 1 ResetVisited(); @@ -18370,7 +18444,7 @@ void InterCodeProcedure::Disassemble(FILE* file) void InterCodeProcedure::Disassemble(const char* name, bool dumpSets) { -#if 0 +#if 1 #ifdef _WIN32 FILE* file; static bool initial = true; diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index 0f4b4f8..f2d8026 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -422,6 +422,7 @@ public: void BuildCallerSaveTempSet(NumberSet& callerSaveTemps); void BuildConstTempSets(void); bool PropagateConstOperationsUp(void); + bool RemoveUnusedLocalStoreInstructions(void); void BuildLocalVariableSets(const GrowingVariableArray& localVars, const GrowingVariableArray& params, InterMemory paramMemory); void BuildGlobalProvidedVariableSet(const GrowingVariableArray& localVars, NumberSet fromProvidedVars, const GrowingVariableArray& params, NumberSet fromProvidedParams, InterMemory paramMemory); @@ -659,6 +660,7 @@ protected: void BuildLoopPrefix(void); void SingleAssignmentForwarding(void); void RemoveUnusedStoreInstructions(InterMemory paramMemory); + void RemoveUnusedLocalStoreInstructions(void); void MergeCommonPathInstructions(void); void PushSinglePathResultInstructions(void); void CollectVariables(InterMemory paramMemory); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 4ada98e..3d40258 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -3276,7 +3276,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* } else { - if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION) + if (vr.mType->mType == DT_TYPE_ARRAY)// || vr.mType->mType == DT_TYPE_FUNCTION) vr = Dereference(proc, texp, block, vr, 1); else if (pdec && pdec->mBase->mType == DT_TYPE_POINTER && vr.mType->mType == DT_TYPE_INTEGER && texp->mType == EX_CONSTANT && texp->mDecValue->mType == DT_CONST_INTEGER && texp->mDecValue->mInteger == 0) { @@ -3316,7 +3316,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* wins->mSrc[1].mTemp = ains->mDst.mTemp; if (pdec) { - if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF) + if (pdec->mBase->mType == DT_TYPE_ARRAY || pdec->mBase->mType == DT_TYPE_REFERENCE || pdec->mBase->mType == DT_TYPE_RVALUEREF || pdec->mBase->mType == DT_TYPE_FUNCTION) { wins->mSrc[1].mOperandSize = 2; wins->mSrc[0].mType = IT_POINTER; diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 498bf74..7c25e9b 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -13623,6 +13623,7 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) bool xisa = false, yisa = false; int xoffset = -1, yoffset = -1; + int zpx = -1, zpy = -1, zpa = -1; for (int i = 0; i < mIns.Size(); i++) { @@ -13630,32 +13631,102 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) { xisa = true; xoffset = i; + zpx = zpa; } else if (mIns[i].mType == ASMIT_TXA) { xisa = true; yisa = false; xoffset = i; + zpa = zpx; } else if (mIns[i].mType == ASMIT_TAY) { yisa = true; yoffset = i; + zpy = zpa; } else if (mIns[i].mType == ASMIT_TYA) { yisa = true; xisa = false; yoffset = i; + zpa = zpy; } - else if (mIns[i].ChangesXReg()) - xisa = false; - else if (mIns[i].ChangesYReg()) - xisa = false; - else if (mIns[i].ChangesAccu()) + else if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + if (zpx == mIns[i].mAddress) + { + mIns[i].mType = ASMIT_TXA; mIns[i].mMode = ASMIM_IMPLIED; + xisa = true; + yisa = false; + int j = i; + while (j > 0 && !(mIns[j - 1].mLive & LIVE_CPU_REG_X)) + { + mIns[j - 1].mLive |= LIVE_CPU_REG_X; + j--; + } + } + else if (zpy == mIns[i].mAddress) + { + mIns[i].mType = ASMIT_TYA; mIns[i].mMode = ASMIM_IMPLIED; + yisa = true; + xisa = false; + int j = i; + while (j > 0 && !(mIns[j - 1].mLive & LIVE_CPU_REG_Y)) + { + mIns[j - 1].mLive |= LIVE_CPU_REG_Y; + j--; + } + } + else + { + xisa = false; + yisa = false; + } + zpa = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_LDX && mIns[i].mMode == ASMIM_ZERO_PAGE) { xisa = false; + zpx = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_LDY && mIns[i].mMode == ASMIM_ZERO_PAGE) + { yisa = false; + zpy = mIns[i].mAddress; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpa = mIns[i].mAddress; + if (yisa) + zpy = mIns[i].mAddress; + else if (zpy == mIns[i].mAddress) + zpy = -1; + if (xisa) + zpx = mIns[i].mAddress; + else if (zpx == mIns[i].mAddress) + zpx = -1; + } + else if (mIns[i].mType == ASMIT_STX && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpx = mIns[i].mAddress; + if (xisa) + zpa = mIns[i].mAddress; + else if (zpa == mIns[i].mAddress) + zpa = -1; + if (zpy == mIns[i].mAddress) + zpy = -1; + } + else if (mIns[i].mType == ASMIT_STY && mIns[i].mMode == ASMIM_ZERO_PAGE) + { + zpy = mIns[i].mAddress; + if (yisa) + zpa = mIns[i].mAddress; + else if (zpa == mIns[i].mAddress) + zpa = -1; + if (zpx == mIns[i].mAddress) + zpx = -1; } else if (i + 1 < mIns.Size() && mIns[i].mType == ASMIT_CLC && mIns[i + 1].mType == ASMIT_ADC && mIns[i + 1].mMode == ASMIM_IMMEDIATE && !(mIns[i + 1].mLive & LIVE_CPU_REG_C)) @@ -13685,6 +13756,33 @@ bool NativeCodeBasicBlock::ForwardAXYReg(void) } } } + else + { + if (mIns[i].ChangesXReg()) + { + xisa = false; + zpx = -1; + } + if (mIns[i].ChangesYReg()) + { + yisa = false; + zpy = -1; + } + if (mIns[i].ChangesAccu()) + { + xisa = false; + yisa = false; + zpa = -1; + } + + if (zpa >= 0 && mIns[i].ChangesZeroPage(zpa)) + zpa = -1; + if (zpx >= 0 && mIns[i].ChangesZeroPage(zpx)) + zpx = -1; + if (zpy >= 0 && mIns[i].ChangesZeroPage(zpy)) + zpy = -1; + } + } if (mTrueJump && mTrueJump->ForwardAXYReg()) @@ -40817,7 +40915,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_pab50"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e6e9f60..d53ff72 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -119,7 +119,7 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) dec->mScope->Insert(mdec->mIdent, mdec); } -Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) +Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl) { const Ident* structName = nullptr; @@ -169,6 +169,9 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, dec->mQualIdent); } + if (ptempl) + ptempl->mBase = dec; + if ((mCompilerOptions & COPT_CPLUSPLUS) && mScanner->mToken == TK_COLON) { mScanner->NextToken(); @@ -181,7 +184,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) else if (ConsumeTokenIf(TK_PRIVATE)) pflags |= DTF_PRIVATE | DTF_PROTECTED; - Declaration* pdec = ParseQualIdent(); + Declaration* pdec = ParseBaseTypeDeclaration(0, false); if (pdec) { if (pdec->mType == DT_TYPE_STRUCT) @@ -481,7 +484,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) return dec; } -Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) +Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified, Declaration* ptempl) { Declaration* dec = nullptr; const Ident* pident = nullptr; @@ -758,13 +761,13 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) break; } case TK_STRUCT: - dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT); + dec = ParseStructDeclaration(flags, DT_TYPE_STRUCT, ptempl); break; case TK_CLASS: - dec = ParseStructDeclaration(flags | DTF_PRIVATE | DTF_PROTECTED, DT_TYPE_STRUCT); + dec = ParseStructDeclaration(flags | DTF_PRIVATE | DTF_PROTECTED, DT_TYPE_STRUCT, ptempl); break; case TK_UNION: - dec = ParseStructDeclaration(flags, DT_TYPE_UNION); + dec = ParseStructDeclaration(flags, DT_TYPE_UNION, ptempl); break; default: mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Declaration starts with invalid token", TokenNames[mScanner->mToken]); @@ -3475,7 +3478,7 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex return cdec; } - bdec = ParseBaseTypeDeclaration(typeFlags, false); + bdec = ParseBaseTypeDeclaration(typeFlags, false, ptempl); } Declaration* rdec = nullptr, * ldec = nullptr; @@ -4583,7 +4586,31 @@ Expression* Parser::ParseSimpleExpression(bool lhs) if (dec) { if (dec->mTemplate && mScanner->mToken == TK_LESS_THAN) + { dec = ParseTemplateExpansion(dec->mTemplate, nullptr); + while (ConsumeTokenIf(TK_COLCOLON)) + { + if (mScanner->mToken == TK_IDENT) + { + if (dec->mType == DT_NAMESPACE || dec->mType == DT_TYPE_STRUCT) + { + Declaration* ndec = dec->mScope->Lookup(mScanner->mTokenIdent, SLEVEL_USING); + + if (ndec) + dec = ndec; + else + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Unknown identifier", mScanner->mTokenIdent); + } + else + mErrors->Error(mScanner->mLocation, EERR_INCOMPATIBLE_OPERATOR, "Not a class or namespace"); + + } + else + mErrors->Error(mScanner->mLocation, EERR_SYNTAX, "Identifier expected"); + + mScanner->NextToken(); + } + } if (dec->mType == DT_CONST_INTEGER || dec->mType == DT_CONST_FLOAT || dec->mType == DT_CONST_FUNCTION || dec->mType == DT_CONST_ASSEMBLER || dec->mType == DT_LABEL || dec->mType == DT_LABEL_REF) { @@ -4630,6 +4657,12 @@ Expression* Parser::ParseSimpleExpression(bool lhs) exp->mDecType = exp->mDecType->BuildReference(mScanner->mLocation); } } + else if (dec->mType == DT_CONST_TEMPLATE) + { + exp = new Expression(mScanner->mLocation, EX_CONSTANT); + exp->mDecValue = dec; + exp->mDecType = TheSignedIntTypeDeclaration; + } else if (dec->mType == DT_ELEMENT) { mErrors->Error(mScanner->mLocation, EERR_NON_STATIC_MEMBER, "Non static member access", mScanner->mTokenIdent); @@ -5617,6 +5650,19 @@ Expression* Parser::ParsePostfixExpression(bool lhs) else if (mScanner->mToken == TK_ARROW) { mScanner->NextToken(); + while (exp->mDecType->mType != DT_TYPE_POINTER) + { + Expression* dexp = new Expression(mScanner->mLocation, EX_PREFIX); + dexp->mToken = TK_ARROW; + dexp->mDecType = TheVoidPointerTypeDeclaration; + dexp->mLeft = exp; + + Expression* oexp = CheckOperatorOverload(dexp); + if (oexp == dexp) + break; + exp = oexp; + } + if (exp->mDecType->mType == DT_TYPE_POINTER) { Expression * dexp = new Expression(mScanner->mLocation, EX_PREFIX); @@ -6713,6 +6759,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) case TK_BINARY_NOT: opident = Ident::Unique("operator~"); break; + case TK_ARROW: + opident = Ident::Unique("operator->"); + break; } if (opident) @@ -7447,7 +7496,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp } else { - if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + if (exp->mType == EX_CONSTANT && (exp->mDecValue->mType == DT_CONST_INTEGER || exp->mDecValue->mType == DT_CONST_TEMPLATE)) epdec->mBase = exp->mDecValue; else mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Const integer parameter expected", pdec->mIdent); @@ -7480,7 +7529,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp else { Declaration* epdec = tdec->mParams; - while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE) + while (epdec && epdec->mBase->mType != DT_TYPE_TEMPLATE && epdec->mBase->mType != DT_CONST_TEMPLATE) epdec = epdec->mNext; if (epdec) @@ -7490,6 +7539,7 @@ Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* exp tdec->mBase = bdec; bdec->mTemplate = tdec; bdec->mBase = tmpld->mBase; + tdec->mNext = tmpld; return bdec; } diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 2eb21bc..7915cc6 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -57,9 +57,9 @@ protected: Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); - Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified); + Declaration* ParseBaseTypeDeclaration(uint64 flags, bool qualified, Declaration* ptempl = nullptr); Declaration* ParseDeclaration(Declaration* pdec, bool variable, bool expression, Declaration * pthis = nullptr, Declaration * ptempl = nullptr); - Declaration* ParseStructDeclaration(uint64 flags, DecType dt); + Declaration* ParseStructDeclaration(uint64 flags, DecType dt, Declaration* ptempl = nullptr); Declaration* CopyConstantInitializer(int offset, Declaration* dtype, Expression* exp); Expression* ParseInitExpression(Declaration* dtype); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 4514311..895438c 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1623,6 +1623,10 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator[]"); break; + case TK_ARROW: + mTokenIdent = Ident::Unique("operator->"); + break; + default: // dirty little hack to implement token preview, got to fix // this with an infinit preview sequence at one point