Add templates

This commit is contained in:
drmortalwombat 2023-08-11 07:41:27 +02:00
parent 07969d1fa6
commit fef6bc29bc
22 changed files with 1041 additions and 84 deletions

View File

@ -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

23
autotest/opp_array.cpp Normal file
View File

@ -0,0 +1,23 @@
#include <opp/array.h>
#include <assert.h>
int main(void)
{
array<int, 10> a10;
array<int, 20> 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;
}

27
autotest/opp_vector.cpp Normal file
View File

@ -0,0 +1,27 @@
#include <opp/vector.h>
#include <assert.h>
int main(void)
{
vector<int> a;
for(int i=0; i<10; i++)
a.push_back(i);
int s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 45);
for(int i=0; i<5; i++)
a.erase(i);
s = 0;
for(int i=0; i<a.size(); i++)
s += a[i];
assert(s == 1 + 3 + 5 + 7 + 9);
return 0;
}

View File

@ -0,0 +1,35 @@
#include <opp/vector.h>
#include <opp/string.h>
#include <assert.h>
#include <stdlib.h>
#include <opp/iostream.h>
string join(const vector<string> & vs)
{
string sj;
for(int i=0; i<vs.size(); i++)
sj += vs[i];
return sj;
}
int main(void)
{
vector<string> 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;
}

127
include/opp/array.h Normal file
View File

@ -0,0 +1,127 @@
#ifndef OPP_ARRAY_H
#define OPP_ARRAY_H
template <class T, int n>
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<n; i++)
_data[i] = t;
}
};
#if 0
void swap(array<T, n> & a)
{
for(int i=0; i<n; i++)
{
T t(_data[i]);
_data[i] = a._data[i];
a._data[i] = t;
}
}
#endif
#endif

View File

@ -129,22 +129,19 @@ string & string::operator+=(const string & s)
{
if (s.cstr)
{
char d = 0;
if (cstr)
{
char l = cstr[0] + s.cstr[0];
char * c = malloc(char(l + 2));
c[0] = l;
smemcpy(c + 1, cstr + 1, cstr[0]);
smemcpy(c + 1 + cstr[0], s.cstr + 1, s.cstr[0] + 1);
free(cstr);
cstr = c;
}
else
{
char l = s.cstr[0];
cstr = malloc(char(l + 2));
smemcpy(cstr, s.cstr, l + 2);
}
d = cstr[0];
char l = s.cstr[0] + d;
char * c = malloc(char(l + 2));
c[0] = l;
if (d)
smemcpy(c + 1, cstr + 1, d);
smemcpy(c + 1 + d, s.cstr + 1, s.cstr[0] + 1);
free(cstr);
cstr = c;
}
return *this;
}

175
include/opp/vector.h Normal file
View File

@ -0,0 +1,175 @@
#ifndef OPP_VECTOR_H
#define OPP_VECTOR_H
template <class T>
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 <class T>
void vector<T>::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 <class T>
void vector<T>::resize(int n)
{
if (n < _size)
_size = n;
else if (n < _capacity)
_size = n;
else
{
reserve(n);
_size = n;
}
}
template <class T>
void vector<T>::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 <class T>
void vector<T>::push_back(const T & t)
{
if (_size == _capacity)
reserve(_size + 1 + (_size >> 1));
_data[_size++] = t;
}
template <class T>
void vector<T>::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 <class T>
void vector<T>::erase(int at, int n)
{
_size -= n;
for(int i=at; i<_size; i++)
_data[i] = _data[i + n];
}
#endif

View File

@ -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++)

View File

@ -19,7 +19,7 @@ public:
CompilationUnits(Errors * errors);
~CompilationUnits(void);
DeclarationScope* mScope, * mVTableScope;
DeclarationScope* mScope, * mVTableScope, * mTemplateScope;
CompilationUnit* mCompilationUnits, * mPendingUnits;
Declaration* mStartup;

View File

@ -240,6 +240,10 @@ static void FillVTableTree(Declaration* vdec)
cvdec = cvdec->mNext;
}
}
void Compiler::CompleteTemplateExpansion(void)
{
}
void Compiler::BuildVTables(void)
{
// Connect vdecs with parents

View File

@ -52,6 +52,7 @@ public:
void CompileProcedure(InterCodeProcedure* proc);
void BuildVTables(void);
void CompleteTemplateExpansion(void);
bool WriteDbjFile(const char* filename);
};

View File

@ -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)

View File

@ -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<Declaration*> 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;
};

View File

@ -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,

View File

@ -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];

View File

@ -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

View File

@ -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];

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

View File

@ -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();

View File

@ -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);