diff --git a/autotest/autotest.bat b/autotest/autotest.bat index 38ae467..9d5a926 100644 --- a/autotest/autotest.bat +++ b/autotest/autotest.bat @@ -3,6 +3,15 @@ rem @echo off @call :test opp_string.cpp @if %errorlevel% neq 0 goto :error +@call :test opp_array.cpp +@if %errorlevel% neq 0 goto :error + +@call :test opp_vector.cpp +@if %errorlevel% neq 0 goto :error + +@call :test opp_vector_string.cpp +@if %errorlevel% neq 0 goto :error + @call :test opp_streamtest.cpp @if %errorlevel% neq 0 goto :error diff --git a/autotest/opp_array.cpp b/autotest/opp_array.cpp new file mode 100644 index 0000000..cf105c0 --- /dev/null +++ b/autotest/opp_array.cpp @@ -0,0 +1,23 @@ +#include +#include + +int main(void) +{ + array a10; + array a20; + + for(int i=0; i<10; i++) + a10[i] = i; + for(int i=0; i<20; i++) + a20[i] = i; + + int s = 0; + for(int i=0; i<10; i++) + s += a10[i]; + for(int i=10; i<20; i++) + s -= a20[i]; + + assert(s == -100); + + return 0; +} diff --git a/autotest/opp_vector.cpp b/autotest/opp_vector.cpp new file mode 100644 index 0000000..91ecca3 --- /dev/null +++ b/autotest/opp_vector.cpp @@ -0,0 +1,27 @@ +#include +#include + +int main(void) +{ + vector a; + + for(int i=0; i<10; i++) + a.push_back(i); + + int s = 0; + for(int i=0; i +#include +#include +#include +#include + +string join(const vector & vs) +{ + string sj; + for(int i=0; i vs; + string a; + + for(int i=0; i<10; i++) + { + vs.push_back(a); + a += "x"; + } + + int s = 0; + for(int i=0; i<10; i++) + s += vs[i].size(); + + assert(s == 45); + + assert(join(vs).size() == 45); + + return 0; +} diff --git a/include/opp/array.h b/include/opp/array.h new file mode 100644 index 0000000..0956811 --- /dev/null +++ b/include/opp/array.h @@ -0,0 +1,127 @@ +#ifndef OPP_ARRAY_H +#define OPP_ARRAY_H + + +template +class array +{ +protected: + T _data[n]; +public: + int size(void) const + { + return n; + } + + int max_size(void) const + { + return n; + } + + bool empty(void) const + { + return n == 0; + } + + const T & at(int at) const + { + return _data[at]; + } + + T & at(int at) + { + return _data[at]; + } + + T & operator[] (int at) + { + return _data[at]; + } + + const T & operator[] (int at) const + { + return _data[at]; + } + + T * begin(void) + { + return _data; + } + + const T * begin(void) const + { + return _data; + } + + const T * cbegin(void) const + { + return _data; + } + + T * end(void) + { + return _data + n; + } + + const T * end(void) const + { + return _data + n; + } + + const T * cend(void) const + { + return _data + n; + } + + T & back(void) + { + return _data[n - 1]; + } + + const T & back(void) const + { + return _data[n - 1]; + } + + T & front(void) + { + return _data[0]; + } + + const T & front(void) const + { + return _data[0]; + } + + T * data(void) + { + return _data; + } + + const T * data(void) const + { + return _data; + } + + void fill(const T & t) + { + for(int i=0; i & a) + { + for(int i=0; i +class vector +{ +protected: + T * _data; + int _size, _capacity; +public: + vector(void) : _data(nullptr), _size(0), _capacity(0) {} + vector(int n) : _data(new T[n]), _size(n), _capacity(n) {} + ~vector(void) + { + delete[] _data; + } + + int size(void) const + { + return _size; + } + + int max_size(void) const + { + return 32767; + } + + bool empty(void) const + { + return _size == 0; + } + + int capacity(void) const + { + return _capacity; + } + + void resize(int n); + + void reserve(int n); + + void shrink_to_fit(void); + + T & at(int at) + { + return _data[at]; + } + + const T & at(int at) const + { + return _data[at]; + } + + T & operator[](int at) + { + return _data[at]; + } + + const T & operator[](int at) const + { + return _data[at]; + } + + T & front(void) + { + return _data[0]; + } + + const T & front(void) const + { + return _data[0]; + } + + T & back(void) + { + return _data[_size - 1]; + } + + const T & back(void) const + { + return _data[_size - 1]; + } + + T * data(void) + { + return _data; + } + + const T * at(void) const + { + return _data; + } + + void push_back(const T & t); + + void pop_back(void) + { + _size--; + } + + void insert(int at, const T & t); + + void erase(int at, int n = 1); +}; + + +template +void vector::reserve(int n) +{ + if (n > _capacity) + { + _capacity = n; + T * d = new T[_capacity]; + for(int i=0; i<_size; i++) + d[i] = _data[i]; + delete[] _data; + _data = d; + } +} + +template +void vector::resize(int n) +{ + if (n < _size) + _size = n; + else if (n < _capacity) + _size = n; + else + { + reserve(n); + _size = n; + } +} + +template +void vector::shrink_to_fit(void) +{ + if (_size < _capacity) + { + _capacity = _size; + T * d = new T[_capacity]; + for(int i=0; i<_size; i++) + d[i] = _data[i]; + delete[] _data; + _data = d; + } +} + +template +void vector::push_back(const T & t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + _data[_size++] = t; +} + +template +void vector::insert(int at, const T & t) +{ + if (_size == _capacity) + reserve(_size + 1 + (_size >> 1)); + for(int i=_size; i>at; i--) + _data[i] = _data[i - 1]; + _data[at] = t; +} + +template +void vector::erase(int at, int n) +{ + _size -= n; + for(int i=at; i<_size; i++) + _data[i] = _data[i + n]; +} + +#endif diff --git a/oscar64/CompilationUnits.cpp b/oscar64/CompilationUnits.cpp index 948964b..9db05f7 100644 --- a/oscar64/CompilationUnits.cpp +++ b/oscar64/CompilationUnits.cpp @@ -15,6 +15,7 @@ CompilationUnits::CompilationUnits(Errors * errors) mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); + mTemplateScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL); mStartup = nullptr; for (int i = 0; i < 256; i++) diff --git a/oscar64/CompilationUnits.h b/oscar64/CompilationUnits.h index a68acbb..47d829d 100644 --- a/oscar64/CompilationUnits.h +++ b/oscar64/CompilationUnits.h @@ -19,7 +19,7 @@ public: CompilationUnits(Errors * errors); ~CompilationUnits(void); - DeclarationScope* mScope, * mVTableScope; + DeclarationScope* mScope, * mVTableScope, * mTemplateScope; CompilationUnit* mCompilationUnits, * mPendingUnits; Declaration* mStartup; diff --git a/oscar64/Compiler.cpp b/oscar64/Compiler.cpp index 06b66e2..08e9b58 100644 --- a/oscar64/Compiler.cpp +++ b/oscar64/Compiler.cpp @@ -240,6 +240,10 @@ static void FillVTableTree(Declaration* vdec) cvdec = cvdec->mNext; } } +void Compiler::CompleteTemplateExpansion(void) +{ +} + void Compiler::BuildVTables(void) { // Connect vdecs with parents diff --git a/oscar64/Compiler.h b/oscar64/Compiler.h index b14571f..67964b7 100644 --- a/oscar64/Compiler.h +++ b/oscar64/Compiler.h @@ -52,6 +52,7 @@ public: void CompileProcedure(InterCodeProcedure* proc); void BuildVTables(void); + void CompleteTemplateExpansion(void); bool WriteDbjFile(const char* filename); }; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 5617724..a075e27 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -800,7 +800,7 @@ Declaration::Declaration(const Location& loc, DecType type) mVTable(nullptr), mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1), mInteger(0), mNumber(0), mMinValue(-0x80000000LL), mMaxValue(0x7fffffffLL), mFastCallBase(0), mFastCallSize(0), mStride(0), mStripe(1), - mCompilerOptions(0), mUseCount(0) + mCompilerOptions(0), mUseCount(0), mTokens(nullptr), mParser(nullptr) {} Declaration::~Declaration(void) @@ -811,7 +811,12 @@ Declaration::~Declaration(void) int Declaration::Stride(void) const { - return mStride > 0 ? mStride : mBase->mSize; + if (mStride > 0) + return mStride; + else if (mBase) + return mBase->mSize; + else + return 1; } Declaration* Declaration::BuildConstPointer(const Location& loc) @@ -862,6 +867,104 @@ Declaration* Declaration::Last(void) return p; } +const Ident* Declaration::MangleIdent(void) +{ + if (!mMangleIdent) + { + if (mType == DT_CONST_INTEGER) + { + char buffer[20]; + sprintf_s(buffer, "%d", (int)mInteger); + mMangleIdent = Ident::Unique(buffer); + } + else if (mType == DT_TYPE_INTEGER) + { + char buffer[20]; + sprintf_s(buffer, "%c%d", (mFlags & DTF_SIGNED) ? 'i' : 'u', mSize * 8); + mMangleIdent = Ident::Unique(buffer); + } + else if (mType == DT_TYPE_FLOAT) + { + mMangleIdent = Ident::Unique("float"); + } + else if (mType == DT_TYPE_REFERENCE) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("&"); + } + else if (mType == DT_TYPE_POINTER) + { + mMangleIdent = mBase->MangleIdent()->PreMangle("*"); + } + else if (mType == DT_TYPE_STRUCT) + { + mMangleIdent = mQualIdent->PreMangle("struct "); + } + else if (mType == DT_TYPE_ENUM) + { + mMangleIdent = mQualIdent->PreMangle("enum "); + } + else if (mType == DT_TEMPLATE) + { + mMangleIdent = Ident::Unique("<"); + + Declaration* dec = mParams; + while (dec) + { + mMangleIdent = mMangleIdent->Mangle(dec->mBase->MangleIdent()->mString); + dec = dec->mNext; + if (dec) + mMangleIdent = mMangleIdent->Mangle(","); + } + mMangleIdent = mMangleIdent->Mangle(">"); + } + else + mMangleIdent = mQualIdent; + + if (mFlags & DTF_CONST) + mMangleIdent = mMangleIdent->PreMangle("const "); + } + + return mMangleIdent; +} + +Declaration* Declaration::TemplateExpand(Declaration* tdec) +{ + if (mType == DT_ARGUMENT) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + if (mNext) + edec->mNext = mNext->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_CONST_FUNCTION) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_TYPE_FUNCTION) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + if (edec->mParams) + edec->mParams = mParams->TemplateExpand(tdec); + return edec; + } + else if (mType == DT_TYPE_TEMPLATE || mType == DT_CONST_TEMPLATE) + { + return tdec->mScope->Lookup(mIdent); + } + else if (mType == DT_TYPE_POINTER || mType == DT_TYPE_ARRAY || mType == DT_TYPE_REFERENCE) + { + Declaration* edec = this->Clone(); + edec->mBase = mBase->TemplateExpand(tdec); + return edec; + } + else + return this; +} + Declaration* Declaration::Clone(void) { Declaration* ndec = new Declaration(mLocation, mType); @@ -1221,7 +1324,7 @@ bool Declaration::IsConstSame(const Declaration* dec) const bool Declaration::IsSameParams(const Declaration* dec) const { - if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION) + if (mType == DT_TYPE_FUNCTION && dec->mType == DT_TYPE_FUNCTION || mType == DT_TEMPLATE && dec->mType == DT_TEMPLATE) { Declaration* ld = mParams, * rd = dec->mParams; while (ld && rd) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 2788596..07d107b 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -8,6 +8,7 @@ class LinkerObject; class LinkerSection; +class Parser; enum DecType { @@ -25,6 +26,7 @@ enum DecType DT_TYPE_FUNCTION, DT_TYPE_ASSEMBLER, DT_TYPE_AUTO, + DT_TYPE_TEMPLATE, DT_TYPE_CONST, DT_TYPE_VOLATILE, @@ -39,6 +41,7 @@ enum DecType DT_CONST_REFERENCE, DT_CONST_ASSEMBLER, DT_CONST_CONSTRUCTOR, + DT_CONST_TEMPLATE, DT_VARIABLE, DT_ARGUMENT, @@ -115,6 +118,7 @@ enum ScopeLevel SLEVEL_GLOBAL, SLEVEL_STATIC, SLEVEL_NAMESPACE, + SLEVEL_TEMPLATE, SLEVEL_CLASS, SLEVEL_FUNCTION, SLEVEL_LOCAL, @@ -254,11 +258,13 @@ public: int64 mInteger, mMinValue, mMaxValue; double mNumber; uint64 mFlags, mCompilerOptions; - const Ident * mIdent, * mQualIdent; + const Ident * mIdent, * mQualIdent, * mMangleIdent; LinkerSection * mSection; const uint8 * mData; LinkerObject * mLinkerObject; int mUseCount; + TokenSequence * mTokens; + Parser * mParser; GrowingArray mCallers, mCalled; @@ -290,6 +296,10 @@ public: Declaration* BuildConstPointer(const Location& loc); Declaration* BuildConstReference(const Location& loc); + Declaration* TemplateExpand(Declaration* tdec); + + const Ident* MangleIdent(void); + int Stride(void) const; }; diff --git a/oscar64/Errors.h b/oscar64/Errors.h index 157de78..23b5678 100644 --- a/oscar64/Errors.h +++ b/oscar64/Errors.h @@ -81,6 +81,7 @@ enum ErrorID EERR_MISSING_TEMP, EERR_NON_STATIC_MEMBER, EERR_TEMPLATE_PARAMS, + EERR_FUNCTION_TEMPLATE, ERRR_STACK_OVERFLOW, ERRR_INVALID_NUMBER, diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index df97f20..6811f5f 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -14790,7 +14790,7 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 1]->mCode == IC_RELATIONAL_OPERATOR && mInstructions[i + 1]->mSrc[1].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 1]->mSrc[1].mFinal && mInstructions[i + 1]->mSrc[0].mTemp < 0 && mInstructions[i + 0]->mDst.mIntConst >= 0 && mInstructions[i + 0]->mSrc[1].mRange.mMaxState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMaxValue + mInstructions[i + 0]->mSrc[0].mIntConst < 32767 && - (IsSignedRelational(mInstructions[i + 1]->mOperator) || mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue >= 0) && + (IsSignedRelational(mInstructions[i + 1]->mOperator) || mInstructions[i + 0]->mSrc[1].mRange.mMinState == IntegerValueRange::S_BOUND && mInstructions[i + 0]->mSrc[1].mRange.mMinValue >= 0) && mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst >= (IsSignedRelational(mInstructions[i + 1]->mOperator) ? 0 : -32768) && mInstructions[i + 1]->mSrc[0].mIntConst - mInstructions[i + 0]->mSrc[0].mIntConst <= 32767) { @@ -14812,6 +14812,18 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray mInstructions[i + 0]->mSrc[1].mFinal = false; changed = true; } + else if ( + mInstructions[i + 0]->mCode == IC_LEA && + mInstructions[i + 1]->mCode == IC_BINARY_OPERATOR && + mInstructions[i + 2]->mCode == IC_LOAD && + mInstructions[i + 2]->mSrc[0].mTemp == mInstructions[i + 0]->mDst.mTemp && mInstructions[i + 2]->mSrc[0].mFinal && + CanSwapInstructions(mInstructions[i + 1], mInstructions[i + 2])) + { + InterInstruction* ins = mInstructions[i + 2]; + mInstructions[i + 2] = mInstructions[i + 1]; + mInstructions[i + 1] = ins; + changed = true; + } else if ( mInstructions[i + 0]->mCode == IC_STORE && mInstructions[i + 1]->mCode == IC_STORE && SameMemSegment(mInstructions[i + 1]->mSrc[1], mInstructions[i + 0]->mSrc[1]) && @@ -16736,7 +16748,7 @@ void InterCodeProcedure::Close(void) { GrowingTypeArray tstack(IT_NONE); - CheckFunc = !strcmp(mIdent->mString, "main"); + CheckFunc = !strcmp(mIdent->mString, "join"); mEntryBlock = mBlocks[0]; diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 0612f0e..cf1c62f 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -40,7 +40,7 @@ static inline InterType InterTypeOf(const Declaration* dec) InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v) { - if (v.mType->mType == DT_TYPE_REFERENCE) + if (v.mType && v.mType->mType == DT_TYPE_REFERENCE) { v.mType = v.mType->mBase; v.mReference++; @@ -1020,7 +1020,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateInline(Declaration* pro { 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_REFERENCE) + else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -2029,7 +2029,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* vr = Dereference(proc, exp, block, vr); if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER) + { mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Invalid type for indexing"); + return ExValue(TheConstVoidTypeDeclaration, -1); + } if (!vr.mType->IsIntegerType()) mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Index operand is not integral number"); @@ -3235,7 +3238,7 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration* mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr"); vr = CoerceType(proc, texp, block, vr, pdec->mBase); } - else if (pdec && pdec->mBase->mType == DT_TYPE_REFERENCE) + else if (pdec && (pdec->mBase->mType == DT_TYPE_REFERENCE && vr.mType->mType != DT_TYPE_REFERENCE)) vr = Dereference(proc, texp, block, vr, 1); else vr = Dereference(proc, texp, block, vr); @@ -4659,7 +4662,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod InterCodeProcedure* proc = new InterCodeProcedure(mod, dec->mLocation, dec->mQualIdent, mLinker->AddObject(dec->mLocation, dec->mQualIdent, dec->mSection, LOT_BYTE_CODE, dec->mAlignment)); #if 0 - if (proc->mIdent && !strcmp(proc->mIdent->mString, "main")) + if (proc->mIdent && !strcmp(proc->mIdent->mString, "join")) exp->Dump(0); #endif #if 0 diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 9ad5473..9fdf5f6 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -16298,7 +16298,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc) fblock->mFalseJump = mFalseJump; fblock->mBranch = mBranch; - mIns[i + 0].mType = ASMIT_NOP; mIns[i + 1].mMode = ASMIM_IMPLIED; + mIns[i + 0].mType = ASMIT_NOP; mIns[i + 0].mMode = ASMIM_IMPLIED; mIns[i + 1].mType = ASMIT_NOP; mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED; mIns[i + 3].mType = ASMIT_INC; mIns[i + 3].mLive |= LIVE_CPU_REG_Z; @@ -25274,6 +25274,8 @@ bool NativeCodeBasicBlock::MoveZeroPageCrossBlockUp(int at, const NativeCodeInst return false; if (mIns[i].ReferencesZeroPage(sins.mAddress)) return false; + if (mIns[i].mMode == ASMIM_INDIRECT_Y && (mIns[i].mAddress + 1 == lins.mAddress || mIns[i].mAddress == lins.mAddress)) + return false; } at = mIns.Size(); @@ -27108,6 +27110,58 @@ bool NativeCodeBasicBlock::ReverseLoadCommutativeOpUp(int aload, int aop) return false; } +bool NativeCodeBasicBlock::MoveTYADCStoreDown(int at) +{ + // [at + 0] TYA + // [at + 1] CLC + // [at + 2] ADC # + // [at + 3] STA + + int offset = mIns[at + 2].mAddress; + int addr = mIns[at + 3].mAddress; + + for (int i = at + 4; i < mIns.Size(); i++) + { + NativeCodeInstruction& ins(mIns[i]); + + if (mIns[i].mType == ASMIT_INY) + offset--; + else if (mIns[i].mType == ASMIT_DEY) + offset++; + else if (mIns[i].ChangesYReg()) + return false; + else if (mIns[i].ReferencesZeroPage(addr)) + return false; + else if (!(mIns[i].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_Y | LIVE_CPU_REG_Z))) + { + if (offset < -2 || offset > 2) + return false; + while (offset < 0) + { + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_DEY)); + offset++; + i++; + } + while (offset > 0) + { + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_INY)); + offset--; + i++; + } + mIns.Insert(i, NativeCodeInstruction(mIns[at].mIns, ASMIT_STY, ASMIM_ZERO_PAGE, addr)); + while (i > at) + { + mIns[i].mLive |= LIVE_CPU_REG_Y; + i--; + } + mIns.Remove(at, 4); + return true; + } + } + + return false; +} + bool NativeCodeBasicBlock::MoveLDSTXOutOfRange(int at) { int j = at + 2; @@ -28678,15 +28732,19 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) i++; } - int aimm = -1; + bool aimm = false; + NativeCodeInstruction ains; if (!pblock->mExitRequiredRegs[CPU_REG_A] || !pblock->mExitRequiredRegs[CPU_REG_X]) { for (int i = 0; i < mIns.Size(); i++) { - if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_IMMEDIATE) - aimm = mIns[i].mAddress; - else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm >= 0) + if (mIns[i].mType == ASMIT_LDA && (mIns[i].mMode == ASMIM_IMMEDIATE || mIns[i].mMode == ASMIM_IMMEDIATE_ADDRESS)) + { + aimm = true; + ains = mIns[i]; + } + else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm) { int reg = mIns[i].mAddress; if (!ReferencedOnPath(this, 0, i, reg) && !ChangedOnPath(this, i + 1, mIns.Size(), reg)) @@ -28698,12 +28756,12 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) { if (!pblock->mExitRequiredRegs[CPU_REG_A]) { - pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDA, ASMIM_IMMEDIATE, aimm)); + pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDA, ains)); pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, reg)); } else if (!pblock->mExitRequiredRegs[CPU_REG_X]) { - pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDX, ASMIM_IMMEDIATE, aimm)); + pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_LDX, ains)); pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STX, ASMIM_ZERO_PAGE, reg)); } @@ -28724,7 +28782,7 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc) } } else if (mIns[i].ChangesAccu()) - aimm = -1; + aimm = false; } } } @@ -33760,6 +33818,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass #endif +#if 1 + for (int i = 0; i + 4 < mIns.Size(); i++) + { + if (mIns[i + 0].mType == ASMIT_TYA && mIns[i + 1].mType == ASMIT_CLC && + mIns[i + 2].mType == ASMIT_ADC && mIns[i + 2].mMode == ASMIM_IMMEDIATE && + mIns[i + 3].mType == ASMIT_STA && mIns[i + 3].mMode == ASMIM_ZERO_PAGE && !(mIns[i + 3].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C | LIVE_CPU_REG_Z))) + { + if (MoveTYADCStoreDown(i)) + changed = true; + } + } + CheckLive(); +#endif + #if 1 // move load - store abs up to initial store // @@ -38380,6 +38452,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass progress = true; } #endif +#if 1 + else if ( + mIns[i + 0].mType == ASMIT_TYA && + mIns[i + 1].mType == ASMIT_TAX && + mIns[i + 2].mType == ASMIT_CLC && + mIns[i + 3].mType == ASMIT_ADC && mIns[i + 3].mMode == ASMIM_IMMEDIATE && mIns[i + 3].mAddress <= 2 && + mIns[i + 4].mType == ASMIT_TAY && !(mIns[i + 4].mLive & (LIVE_CPU_REG_A | LIVE_CPU_REG_C))) + { + mIns[i + 0].mLive |= LIVE_CPU_REG_Y; + mIns[i + 1].mLive |= LIVE_CPU_REG_Y; + mIns[i + 2].mType = ASMIT_INY; mIns[i + 2].mLive |= LIVE_CPU_REG_Y; + mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED; + if (mIns[i + 3].mAddress > 1) + mIns[i + 4].mType = ASMIT_INY; + else + mIns[i + 4].mType = ASMIT_NOP; + + progress = true; + } +#endif #if 0 else if ( mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE && @@ -40692,7 +40784,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "time_draw"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "main"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; diff --git a/oscar64/NativeCodeGenerator.h b/oscar64/NativeCodeGenerator.h index d417e8e..044061b 100644 --- a/oscar64/NativeCodeGenerator.h +++ b/oscar64/NativeCodeGenerator.h @@ -410,6 +410,7 @@ public: bool MoveLoadAddZPStoreUp(int at); bool MoveLoadShiftRotateUp(int at); bool MoveLoadShiftStoreUp(int at); + bool MoveTYADCStoreDown(int at); bool MoveLDSTXOutOfRange(int at); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index e424e98..f7df66e 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -8,6 +8,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn { mGlobals = new DeclarationScope(compilationUnits->mScope, SLEVEL_STATIC); mScope = mGlobals; + mTemplateScope = nullptr; mCodeSection = compilationUnits->mSectionCode; mDataSection = compilationUnits->mSectionData; @@ -28,6 +29,20 @@ Parser::~Parser(void) } +Parser* Parser::Clone(void) +{ + Parser* p = new Parser(mErrors, new Scanner(mErrors, mScanner->mPreprocessor), mCompilationUnits); + + p->mGlobals = mGlobals; + p->mScope = mScope; + p->mCompilerOptions = mCompilerOptions; + p->mCodeSection = mCodeSection; + p->mDataSection = mDataSection; + p->mBSSection = mBSSection; + + return p; +} + Declaration* Parser::FindBaseMemberFunction(Declaration* dec, Declaration* mdec) { const Ident* ident = mdec->mIdent; @@ -117,7 +132,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt) structName = mScanner->mTokenIdent; mScanner->NextToken(); Declaration* edec = mScope->Lookup(structName); - if (edec && mScanner->mToken != TK_OPEN_BRACE && mScanner->mToken != TK_COLON) + if (edec && edec->mType == DT_TEMPLATE) + { + mTemplateScope->Insert(structName, dec); + + dec->mIdent = structName; + dec->mQualIdent = mScope->Mangle(structName->Mangle(mTemplateScope->mName->mString)); + dec->mScope = new DeclarationScope(nullptr, SLEVEL_CLASS, dec->mQualIdent); + } + else if (edec && mScanner->mToken != TK_OPEN_BRACE && mScanner->mToken != TK_COLON) { dec = edec; } @@ -562,53 +585,65 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified) case TK_IDENT: pident = mScanner->mTokenIdent; - dec = mScope->Lookup(mScanner->mTokenIdent); - if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) - dec = mScope->mParent->Lookup(mScanner->mTokenIdent); + if (mTemplateScope) + dec = mTemplateScope->Lookup(mScanner->mTokenIdent); - mScanner->NextToken(); - while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) + if (!dec) { - if (ExpectToken(TK_IDENT)) - { - pident = mScanner->mTokenIdent; - dec = dec->mScope->Lookup(mScanner->mTokenIdent); - mScanner->NextToken(); - } - } + dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS) + dec = mScope->mParent->Lookup(mScanner->mTokenIdent); - if (dec && dec->mType <= DT_TYPE_FUNCTION) - { - if (dec->IsSimpleType() && (flags & ~dec->mFlags)) + mScanner->NextToken(); + + if (dec && dec->mType == DT_TEMPLATE) + dec = ParseTemplateExpansion(dec, nullptr); + + while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON)) { - Declaration* ndec = new Declaration(dec->mLocation, dec->mType); - ndec->mFlags = dec->mFlags | flags; - ndec->mSize = dec->mSize; - ndec->mBase = dec->mBase; - dec = ndec; + if (ExpectToken(TK_IDENT)) + { + pident = mScanner->mTokenIdent; + dec = dec->mScope->Lookup(mScanner->mTokenIdent); + mScanner->NextToken(); + } } - else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + + if (dec && dec->mType <= DT_TYPE_FUNCTION) { - if ((flags & ~dec->mFlags) == DTF_CONST) - dec = dec->ToConstType(); - else + if (dec->IsSimpleType() && (flags & ~dec->mFlags)) { Declaration* ndec = new Declaration(dec->mLocation, dec->mType); ndec->mFlags = dec->mFlags | flags; ndec->mSize = dec->mSize; ndec->mBase = dec->mBase; - ndec->mScope = dec->mScope; - ndec->mParams = dec->mParams; - ndec->mIdent = dec->mIdent; - ndec->mQualIdent = dec->mQualIdent; dec = ndec; } + else if (dec->mType == DT_TYPE_STRUCT && (flags & ~dec->mFlags)) + { + if ((flags & ~dec->mFlags) == DTF_CONST) + dec = dec->ToConstType(); + else + { + Declaration* ndec = new Declaration(dec->mLocation, dec->mType); + ndec->mFlags = dec->mFlags | flags; + ndec->mSize = dec->mSize; + ndec->mBase = dec->mBase; + ndec->mScope = dec->mScope; + ndec->mParams = dec->mParams; + ndec->mIdent = dec->mIdent; + ndec->mQualIdent = dec->mQualIdent; + dec = ndec; + } + } } + else if (!dec) + mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); + else + mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); } - else if (!dec) - mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident); else - mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent); + mScanner->NextToken(); break; case TK_ENUM: @@ -804,10 +839,26 @@ Declaration* Parser::ParsePostfixDeclaration(void) { dec = new Declaration(mScanner->mLocation, DT_VARIABLE); dec->mIdent = mScanner->mTokenIdent; - dec->mQualIdent = mScope->Mangle(dec->mIdent); dec->mSection = mBSSection; dec->mBase = nullptr; mScanner->NextToken(); + + if (mScanner->mToken == TK_LESS_THAN && mTemplateScope) + { + Declaration* tdec = mScope->Lookup(dec->mIdent); + if (tdec && tdec->mType == DT_TEMPLATE) + { + // for now just skip over template stuff + while (!ConsumeTokenIf(TK_GREATER_THAN)) + mScanner->NextToken(); + + if (mTemplateScope->mName) + dec->mIdent = dec->mIdent->Mangle(mTemplateScope->mName->mString); + } + } + + dec->mQualIdent = mScope->Mangle(dec->mIdent); + if (mScanner->mToken == TK_OPEN_PARENTHESIS && mScope->mLevel >= SLEVEL_FUNCTION) { // Can't be a function declaration in local context, so it must be an object @@ -2964,6 +3015,7 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) cexp->mToken = pex->mToken; pex->mType = EX_INITIALIZATION; + pex->mToken = TK_ASSIGN; pex->mLeft = vexp; pex->mRight = cexp; pex->mDecValue = nullptr; @@ -2990,6 +3042,38 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp) rexp = ConcatExpression(rexp, dexp); } } + else if (pdec->mBase->mType == DT_TYPE_REFERENCE && pex->mType == EX_CONSTANT) + { + // A simple constant is passed by const ref + if (pex->mDecValue->mType == DT_CONST_INTEGER || pex->mDecValue->mType == DT_CONST_FLOAT || pex->mDecValue->mType == DT_CONST_POINTER) + { + 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; + + Expression* vexp = new Expression(pex->mLocation, EX_VARIABLE); + vexp->mDecType = pdec->mBase->mBase; + 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; } @@ -4108,7 +4192,15 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec) Declaration* Parser::ParseQualIdent(void) { - Declaration* dec = mScope->Lookup(mScanner->mTokenIdent); + Declaration* dec = nullptr; + if (mTemplateScope) + { + dec = mTemplateScope->Lookup(mScanner->mTokenIdent); + } + + if (!dec) + dec = mScope->Lookup(mScanner->mTokenIdent); + if (dec) { mScanner->NextToken(); @@ -4371,6 +4463,9 @@ Expression* Parser::ParseSimpleExpression(bool lhs) dec = ParseQualIdent(); if (dec) { + if (dec->mType == DT_TEMPLATE) + dec = ParseTemplateExpansion(dec, nullptr); + 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) { exp = new Expression(mScanner->mLocation, EX_CONSTANT); @@ -6980,10 +7075,153 @@ Expression* Parser::ParseSwitchStatement(void) return sexp; } -void Parser::ParseTemplate(void) +Declaration* Parser::ParseTemplateExpansion(Declaration* tmpld, Declaration* expd) +{ + + Declaration * tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); + + if (expd) + { + tdec->mParams = expd->mParams; + Declaration* dec = tdec->mParams; + while (dec) + { + tdec->mScope->Insert(dec->mIdent, dec->mBase); + dec = dec->mNext; + } + } + else + { + ConsumeToken(TK_LESS_THAN); + + Declaration* ppdec = nullptr; + Declaration* pdec = tmpld->mParams; + while (pdec) + { + Declaration* epdec = pdec->Clone(); + Expression* exp = ParseShiftExpression(false); + + if (epdec->mType == DT_TYPE_TEMPLATE) + { + if (exp->mType == EX_TYPE) + epdec->mBase = exp->mDecType; + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Type parameter expected", pdec->mIdent); + } + else + { + if (exp->mType == EX_CONSTANT && exp->mDecValue->mType == DT_CONST_INTEGER) + epdec->mBase = exp->mDecValue; + else + mErrors->Error(exp->mLocation, EERR_TEMPLATE_PARAMS, "Const integer parameter expected", pdec->mIdent); + } + + tdec->mScope->Insert(epdec->mIdent, epdec->mBase); + epdec->mFlags |= DTF_DEFINED; + + if (ppdec) + ppdec->mNext = epdec; + else + tdec->mParams = epdec; + ppdec = epdec; + + pdec = pdec->mNext; + if (pdec) + ConsumeToken(TK_COMMA); + } + + ConsumeToken(TK_GREATER_THAN); + } + + Declaration* etdec = tmpld->mNext; + while (etdec && !etdec->IsSameParams(tdec)) + etdec = etdec->mNext; + if (etdec) + { + return etdec->mBase; + } + else + { + Parser* p = tmpld->mParser; + + p->mScanner->Replay(tmpld->mTokens); + + tdec->mScope->mName = tdec->MangleIdent(); + + p->mTemplateScope = tdec->mScope; + tdec->mBase = p->ParseDeclaration(nullptr, true, false); + p->mTemplateScope = nullptr; + + tdec->mNext = tmpld->mNext; + tmpld->mNext = tdec; + + 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 = mScope->Lookup(tmpld->mScope->Mangle(mdec->mIdent)); + if (mpdec && mpdec->mType == DT_TEMPLATE) + { + p->ParseTemplateExpansion(mpdec, tdec); + } + } + + mdec = mdec->mNext; + } + } + }); + } + + return tdec->mBase; + } +} + +void Parser::CompleteTemplateExpansion(Declaration* tmpld) +{ + tmpld = tmpld->mNext; + while (tmpld) + { + if (tmpld->mBase->mType == DT_TYPE_STRUCT) + { + // now expand the templated members + + tmpld->mBase->mScope->Iterate([=](const Ident* ident, Declaration* mdec) + { + if (mdec->mType == DT_CONST_FUNCTION) + { + while (mdec) + { + Declaration* mpdec = mScope->Lookup(mdec->mQualIdent); + if (mpdec && mpdec->mType == DT_TEMPLATE) + { + ParseTemplateExpansion(mpdec, tmpld); + } + + mdec = mdec->mNext; + } + } + }); + } + } +} + + +void Parser::ParseTemplateDeclaration(void) { ConsumeToken(TK_LESS_THAN); Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE); + tdec->mParser = this->Clone(); + tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE); Declaration* ppdec = nullptr; for (;;) @@ -6994,9 +7232,8 @@ void Parser::ParseTemplate(void) { if (mScanner->mToken == TK_IDENT) { - Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec = new Declaration(mScanner->mLocation, DT_TYPE_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; - pdec->mBase = TheVoidTypeDeclaration; mScanner->NextToken(); } else @@ -7006,9 +7243,8 @@ void Parser::ParseTemplate(void) { if (mScanner->mToken == TK_IDENT) { - Declaration* pdec = new Declaration(mScanner->mLocation, DT_ARGUMENT); + pdec = new Declaration(mScanner->mLocation, DT_CONST_TEMPLATE); pdec->mIdent = mScanner->mTokenIdent; - pdec->mBase = TheSignedIntTypeDeclaration; mScanner->NextToken(); } else @@ -7019,6 +7255,9 @@ void Parser::ParseTemplate(void) if (pdec) { + tdec->mScope->Insert(pdec->mIdent, pdec); + pdec->mFlags |= DTF_DEFINED; + if (ppdec) ppdec->mNext = pdec; else @@ -7032,16 +7271,86 @@ void Parser::ParseTemplate(void) ConsumeToken(TK_GREATER_THAN); + mScanner->BeginRecord(); if (mScanner->mToken == TK_CLASS) { // Class template + Declaration* bdec = new Declaration(mScanner->mLocation, DT_TYPE_STRUCT); + tdec->mBase = bdec; + mScanner->NextToken(); + if (mScanner->mToken == TK_IDENT) + { + bdec->mIdent = mScanner->mTokenIdent; + bdec->mQualIdent = mScope->Mangle(bdec->mIdent); + + while (mScanner->mToken != TK_SEMICOLON && mScanner->mToken != TK_OPEN_BRACE) + mScanner->NextToken(); + + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int qdepth = 1; + while (qdepth) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + qdepth++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + qdepth--; + else + mScanner->NextToken(); + } + } + } + else + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Class template expected"); } else { // Function template + mTemplateScope = tdec->mScope; + Declaration* bdec = ParseBaseTypeDeclaration(0, false); + Declaration* adec = ParsePostfixDeclaration(); + + adec = ReverseDeclaration(adec, bdec); + + mTemplateScope = nullptr; + + if (adec->mBase->mType == DT_TYPE_FUNCTION) + { + adec->mType = DT_CONST_FUNCTION; + adec->mSection = mCodeSection; + + if (mCompilerOptions & COPT_NATIVE) + adec->mFlags |= DTF_NATIVE; + + tdec->mBase = adec; + + if (ConsumeTokenIf(TK_OPEN_BRACE)) + { + int qdepth = 1; + while (qdepth) + { + if (ConsumeTokenIf(TK_OPEN_BRACE)) + qdepth++; + else if (ConsumeTokenIf(TK_CLOSE_BRACE)) + qdepth--; + else + mScanner->NextToken(); + } + } + } + else + mErrors->Error(bdec->mLocation, EERR_FUNCTION_TEMPLATE, "Function template expected"); } + + tdec->mTokens = mScanner->CompleteRecord(); + + tdec->mIdent = tdec->mBase->mIdent; + tdec->mQualIdent = tdec->mBase->mQualIdent; + tdec->mScope->mName = tdec->mQualIdent; + + mScope->Insert(tdec->mQualIdent, tdec); } @@ -8673,7 +8982,7 @@ void Parser::Parse(void) else if (mScanner->mToken == TK_TEMPLATE) { mScanner->NextToken(); - ParseTemplate(); + ParseTemplateDeclaration(); } else if (mScanner->mToken == TK_NAMESPACE) { diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 81fa74b..710f1b0 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -10,7 +10,9 @@ public: Parser(Errors * errors, Scanner* scanner, CompilationUnits * compilationUnits); ~Parser(void); - DeclarationScope * mGlobals, * mScope; + Parser* Clone(void); + + DeclarationScope * mGlobals, * mScope, * mTemplateScope; int mLocalIndex; CompilationUnits * mCompilationUnits; Declaration * mThisPointer, * mReturnType; @@ -93,7 +95,9 @@ protected: bool CanCoerceExpression(Expression* exp, Declaration* type); void CompleteFunctionDefaultParams(Expression* exp); - void ParseTemplate(void); + void ParseTemplateDeclaration(void); + Declaration* ParseTemplateExpansion(Declaration* tmpld, Declaration* expd); + void CompleteTemplateExpansion(Declaration* tmpld); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 07f60f4..88e63f8 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -309,7 +309,7 @@ Macro* MacroDict::Lookup(const Ident* ident) TokenSequence::TokenSequence(Scanner* scanner) : mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken), - mTokenIdent(scanner->mTokenIdent), mTokenChar(scanner->mTokenChar), + mTokenIdent(scanner->mTokenIdent), mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber), mTokenString(nullptr) { @@ -345,6 +345,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mToken = TK_NONE; mUngetToken = TK_NONE; mReplay = nullptr; + mRecord = mRecordLast = nullptr; mOnceDict = new MacroDict(); @@ -359,15 +360,23 @@ Scanner::~Scanner(void) } -TokenSequence* Scanner::Record(void) +void Scanner::BeginRecord(void) { - return new TokenSequence(this); + mRecord = mRecordLast = new TokenSequence(this); +} + +TokenSequence* Scanner::CompleteRecord(void) +{ + TokenSequence* seq = mRecord; + mRecord = mRecordLast = nullptr; + return seq; } const TokenSequence* Scanner::Replay(const TokenSequence* replay) { const TokenSequence* seq = mReplay; mReplay = replay; + NextToken(); return seq; } @@ -463,16 +472,27 @@ void Scanner::NextToken(void) mToken = mReplay->mToken; mTokenIdent = mReplay->mTokenIdent; - mTokenChar = mReplay->mTokenChar; mTokenNumber = mReplay->mTokenNumber; mTokenInteger = mReplay->mTokenInteger; if (mReplay->mTokenString) strcpy_s(mTokenString, mReplay->mTokenString); mReplay = mReplay->mNext; - return; } + else + { + NextPreToken(); + if (mRecord) + { + mRecordLast->mNext = new TokenSequence(this); + mRecordLast = mRecordLast->mNext; + } + } +} + +void Scanner::NextPreToken(void) +{ for (;;) { NextRawToken(); diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 3d1691f..984fcf3 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -214,7 +214,6 @@ struct TokenSequence Token mToken; const Ident * mTokenIdent; - char mTokenChar; const char * mTokenString; double mTokenNumber; int64 mTokenInteger; @@ -233,7 +232,9 @@ public: void NextToken(void); - TokenSequence* Record(void); + void BeginRecord(void); + TokenSequence* CompleteRecord(void); + const TokenSequence* Replay(const TokenSequence * sequence); void Warning(const char * error); @@ -272,6 +273,7 @@ public: void MarkSourceOnce(void); protected: void NextRawToken(void); + void NextPreToken(void); struct MacroExpansion { @@ -289,6 +291,7 @@ protected: Token mUngetToken; const TokenSequence* mReplay; + TokenSequence* mRecord, * mRecordLast; void StringToken(char terminator, char mode); void CharToken(char mode);