Add templates
This commit is contained in:
parent
07969d1fa6
commit
fef6bc29bc
|
@ -3,6 +3,15 @@ rem @echo off
|
||||||
@call :test opp_string.cpp
|
@call :test opp_string.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@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
|
@call :test opp_streamtest.cpp
|
||||||
@if %errorlevel% neq 0 goto :error
|
@if %errorlevel% neq 0 goto :error
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
|
@ -129,23 +129,20 @@ string & string::operator+=(const string & s)
|
||||||
{
|
{
|
||||||
if (s.cstr)
|
if (s.cstr)
|
||||||
{
|
{
|
||||||
|
char d = 0;
|
||||||
if (cstr)
|
if (cstr)
|
||||||
{
|
d = cstr[0];
|
||||||
char l = cstr[0] + s.cstr[0];
|
|
||||||
|
char l = s.cstr[0] + d;
|
||||||
char * c = malloc(char(l + 2));
|
char * c = malloc(char(l + 2));
|
||||||
c[0] = l;
|
c[0] = l;
|
||||||
smemcpy(c + 1, cstr + 1, cstr[0]);
|
|
||||||
smemcpy(c + 1 + cstr[0], s.cstr + 1, s.cstr[0] + 1);
|
if (d)
|
||||||
|
smemcpy(c + 1, cstr + 1, d);
|
||||||
|
smemcpy(c + 1 + d, s.cstr + 1, s.cstr[0] + 1);
|
||||||
free(cstr);
|
free(cstr);
|
||||||
cstr = c;
|
cstr = c;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
char l = s.cstr[0];
|
|
||||||
cstr = malloc(char(l + 2));
|
|
||||||
smemcpy(cstr, s.cstr, l + 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -15,6 +15,7 @@ CompilationUnits::CompilationUnits(Errors * errors)
|
||||||
mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
mScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
mRuntimeScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
mVTableScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
|
mTemplateScope = new DeclarationScope(nullptr, SLEVEL_GLOBAL);
|
||||||
mStartup = nullptr;
|
mStartup = nullptr;
|
||||||
|
|
||||||
for (int i = 0; i < 256; i++)
|
for (int i = 0; i < 256; i++)
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
CompilationUnits(Errors * errors);
|
CompilationUnits(Errors * errors);
|
||||||
~CompilationUnits(void);
|
~CompilationUnits(void);
|
||||||
|
|
||||||
DeclarationScope* mScope, * mVTableScope;
|
DeclarationScope* mScope, * mVTableScope, * mTemplateScope;
|
||||||
CompilationUnit* mCompilationUnits, * mPendingUnits;
|
CompilationUnit* mCompilationUnits, * mPendingUnits;
|
||||||
|
|
||||||
Declaration* mStartup;
|
Declaration* mStartup;
|
||||||
|
|
|
@ -240,6 +240,10 @@ static void FillVTableTree(Declaration* vdec)
|
||||||
cvdec = cvdec->mNext;
|
cvdec = cvdec->mNext;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void Compiler::CompleteTemplateExpansion(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
void Compiler::BuildVTables(void)
|
void Compiler::BuildVTables(void)
|
||||||
{
|
{
|
||||||
// Connect vdecs with parents
|
// Connect vdecs with parents
|
||||||
|
|
|
@ -52,6 +52,7 @@ public:
|
||||||
|
|
||||||
void CompileProcedure(InterCodeProcedure* proc);
|
void CompileProcedure(InterCodeProcedure* proc);
|
||||||
void BuildVTables(void);
|
void BuildVTables(void);
|
||||||
|
void CompleteTemplateExpansion(void);
|
||||||
|
|
||||||
bool WriteDbjFile(const char* filename);
|
bool WriteDbjFile(const char* filename);
|
||||||
};
|
};
|
||||||
|
|
|
@ -800,7 +800,7 @@ Declaration::Declaration(const Location& loc, DecType type)
|
||||||
mVTable(nullptr),
|
mVTable(nullptr),
|
||||||
mVarIndex(-1), mLinkerObject(nullptr), mCallers(nullptr), mCalled(nullptr), mAlignment(1),
|
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),
|
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)
|
Declaration::~Declaration(void)
|
||||||
|
@ -811,7 +811,12 @@ Declaration::~Declaration(void)
|
||||||
|
|
||||||
int Declaration::Stride(void) const
|
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)
|
Declaration* Declaration::BuildConstPointer(const Location& loc)
|
||||||
|
@ -862,6 +867,104 @@ Declaration* Declaration::Last(void)
|
||||||
return p;
|
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* Declaration::Clone(void)
|
||||||
{
|
{
|
||||||
Declaration* ndec = new Declaration(mLocation, mType);
|
Declaration* ndec = new Declaration(mLocation, mType);
|
||||||
|
@ -1221,7 +1324,7 @@ bool Declaration::IsConstSame(const Declaration* dec) const
|
||||||
|
|
||||||
bool Declaration::IsSameParams(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;
|
Declaration* ld = mParams, * rd = dec->mParams;
|
||||||
while (ld && rd)
|
while (ld && rd)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
class LinkerObject;
|
class LinkerObject;
|
||||||
class LinkerSection;
|
class LinkerSection;
|
||||||
|
class Parser;
|
||||||
|
|
||||||
enum DecType
|
enum DecType
|
||||||
{
|
{
|
||||||
|
@ -25,6 +26,7 @@ enum DecType
|
||||||
DT_TYPE_FUNCTION,
|
DT_TYPE_FUNCTION,
|
||||||
DT_TYPE_ASSEMBLER,
|
DT_TYPE_ASSEMBLER,
|
||||||
DT_TYPE_AUTO,
|
DT_TYPE_AUTO,
|
||||||
|
DT_TYPE_TEMPLATE,
|
||||||
|
|
||||||
DT_TYPE_CONST,
|
DT_TYPE_CONST,
|
||||||
DT_TYPE_VOLATILE,
|
DT_TYPE_VOLATILE,
|
||||||
|
@ -39,6 +41,7 @@ enum DecType
|
||||||
DT_CONST_REFERENCE,
|
DT_CONST_REFERENCE,
|
||||||
DT_CONST_ASSEMBLER,
|
DT_CONST_ASSEMBLER,
|
||||||
DT_CONST_CONSTRUCTOR,
|
DT_CONST_CONSTRUCTOR,
|
||||||
|
DT_CONST_TEMPLATE,
|
||||||
|
|
||||||
DT_VARIABLE,
|
DT_VARIABLE,
|
||||||
DT_ARGUMENT,
|
DT_ARGUMENT,
|
||||||
|
@ -115,6 +118,7 @@ enum ScopeLevel
|
||||||
SLEVEL_GLOBAL,
|
SLEVEL_GLOBAL,
|
||||||
SLEVEL_STATIC,
|
SLEVEL_STATIC,
|
||||||
SLEVEL_NAMESPACE,
|
SLEVEL_NAMESPACE,
|
||||||
|
SLEVEL_TEMPLATE,
|
||||||
SLEVEL_CLASS,
|
SLEVEL_CLASS,
|
||||||
SLEVEL_FUNCTION,
|
SLEVEL_FUNCTION,
|
||||||
SLEVEL_LOCAL,
|
SLEVEL_LOCAL,
|
||||||
|
@ -254,11 +258,13 @@ public:
|
||||||
int64 mInteger, mMinValue, mMaxValue;
|
int64 mInteger, mMinValue, mMaxValue;
|
||||||
double mNumber;
|
double mNumber;
|
||||||
uint64 mFlags, mCompilerOptions;
|
uint64 mFlags, mCompilerOptions;
|
||||||
const Ident * mIdent, * mQualIdent;
|
const Ident * mIdent, * mQualIdent, * mMangleIdent;
|
||||||
LinkerSection * mSection;
|
LinkerSection * mSection;
|
||||||
const uint8 * mData;
|
const uint8 * mData;
|
||||||
LinkerObject * mLinkerObject;
|
LinkerObject * mLinkerObject;
|
||||||
int mUseCount;
|
int mUseCount;
|
||||||
|
TokenSequence * mTokens;
|
||||||
|
Parser * mParser;
|
||||||
|
|
||||||
GrowingArray<Declaration*> mCallers, mCalled;
|
GrowingArray<Declaration*> mCallers, mCalled;
|
||||||
|
|
||||||
|
@ -290,6 +296,10 @@ public:
|
||||||
Declaration* BuildConstPointer(const Location& loc);
|
Declaration* BuildConstPointer(const Location& loc);
|
||||||
Declaration* BuildConstReference(const Location& loc);
|
Declaration* BuildConstReference(const Location& loc);
|
||||||
|
|
||||||
|
Declaration* TemplateExpand(Declaration* tdec);
|
||||||
|
|
||||||
|
const Ident* MangleIdent(void);
|
||||||
|
|
||||||
int Stride(void) const;
|
int Stride(void) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ enum ErrorID
|
||||||
EERR_MISSING_TEMP,
|
EERR_MISSING_TEMP,
|
||||||
EERR_NON_STATIC_MEMBER,
|
EERR_NON_STATIC_MEMBER,
|
||||||
EERR_TEMPLATE_PARAMS,
|
EERR_TEMPLATE_PARAMS,
|
||||||
|
EERR_FUNCTION_TEMPLATE,
|
||||||
|
|
||||||
ERRR_STACK_OVERFLOW,
|
ERRR_STACK_OVERFLOW,
|
||||||
ERRR_INVALID_NUMBER,
|
ERRR_INVALID_NUMBER,
|
||||||
|
|
|
@ -14812,6 +14812,18 @@ bool InterCodeBasicBlock::PeepholeReplaceOptimization(const GrowingVariableArray
|
||||||
mInstructions[i + 0]->mSrc[1].mFinal = false;
|
mInstructions[i + 0]->mSrc[1].mFinal = false;
|
||||||
changed = true;
|
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 (
|
else if (
|
||||||
mInstructions[i + 0]->mCode == IC_STORE && mInstructions[i + 1]->mCode == IC_STORE &&
|
mInstructions[i + 0]->mCode == IC_STORE && mInstructions[i + 1]->mCode == IC_STORE &&
|
||||||
SameMemSegment(mInstructions[i + 1]->mSrc[1], mInstructions[i + 0]->mSrc[1]) &&
|
SameMemSegment(mInstructions[i + 1]->mSrc[1], mInstructions[i + 0]->mSrc[1]) &&
|
||||||
|
@ -16736,7 +16748,7 @@ void InterCodeProcedure::Close(void)
|
||||||
{
|
{
|
||||||
GrowingTypeArray tstack(IT_NONE);
|
GrowingTypeArray tstack(IT_NONE);
|
||||||
|
|
||||||
CheckFunc = !strcmp(mIdent->mString, "main");
|
CheckFunc = !strcmp(mIdent->mString, "join");
|
||||||
|
|
||||||
mEntryBlock = mBlocks[0];
|
mEntryBlock = mBlocks[0];
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ static inline InterType InterTypeOf(const Declaration* dec)
|
||||||
|
|
||||||
InterCodeGenerator::ExValue InterCodeGenerator::ToValue(InterCodeProcedure* proc, Expression* exp, InterCodeBasicBlock*& block, ExValue v)
|
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.mType = v.mType->mBase;
|
||||||
v.mReference++;
|
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)
|
if (vr.mType->mType == DT_TYPE_ARRAY || vr.mType->mType == DT_TYPE_FUNCTION)
|
||||||
vr = Dereference(proc, texp, block, vr, 1);
|
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);
|
vr = Dereference(proc, texp, block, vr, 1);
|
||||||
else
|
else
|
||||||
vr = Dereference(proc, texp, block, vr);
|
vr = Dereference(proc, texp, block, vr);
|
||||||
|
@ -2029,7 +2029,10 @@ InterCodeGenerator::ExValue InterCodeGenerator::TranslateExpression(Declaration*
|
||||||
vr = Dereference(proc, exp, block, vr);
|
vr = Dereference(proc, exp, block, vr);
|
||||||
|
|
||||||
if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER)
|
if (vl.mType->mType != DT_TYPE_ARRAY && vl.mType->mType != DT_TYPE_POINTER)
|
||||||
|
{
|
||||||
mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Invalid type for indexing");
|
mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Invalid type for indexing");
|
||||||
|
return ExValue(TheConstVoidTypeDeclaration, -1);
|
||||||
|
}
|
||||||
|
|
||||||
if (!vr.mType->IsIntegerType())
|
if (!vr.mType->IsIntegerType())
|
||||||
mErrors->Error(exp->mLocation, EERR_INVALID_INDEX, "Index operand is not integral number");
|
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");
|
mErrors->Error(texp->mLocation, EWARN_NUMERIC_0_USED_AS_NULLPTR, "Numeric 0 used for nullptr");
|
||||||
vr = CoerceType(proc, texp, block, vr, pdec->mBase);
|
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);
|
vr = Dereference(proc, texp, block, vr, 1);
|
||||||
else
|
else
|
||||||
vr = Dereference(proc, texp, block, vr);
|
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));
|
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 0
|
||||||
if (proc->mIdent && !strcmp(proc->mIdent->mString, "main"))
|
if (proc->mIdent && !strcmp(proc->mIdent->mString, "join"))
|
||||||
exp->Dump(0);
|
exp->Dump(0);
|
||||||
#endif
|
#endif
|
||||||
#if 0
|
#if 0
|
||||||
|
|
|
@ -16298,7 +16298,7 @@ bool NativeCodeBasicBlock::ExpandADCToBranch(NativeCodeProcedure* proc)
|
||||||
fblock->mFalseJump = mFalseJump;
|
fblock->mFalseJump = mFalseJump;
|
||||||
fblock->mBranch = mBranch;
|
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 + 1].mType = ASMIT_NOP;
|
||||||
mIns[i + 2].mType = ASMIT_NOP; mIns[i + 2].mMode = ASMIM_IMPLIED;
|
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;
|
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;
|
return false;
|
||||||
if (mIns[i].ReferencesZeroPage(sins.mAddress))
|
if (mIns[i].ReferencesZeroPage(sins.mAddress))
|
||||||
return false;
|
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();
|
at = mIns.Size();
|
||||||
|
@ -27108,6 +27110,58 @@ bool NativeCodeBasicBlock::ReverseLoadCommutativeOpUp(int aload, int aop)
|
||||||
return false;
|
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)
|
bool NativeCodeBasicBlock::MoveLDSTXOutOfRange(int at)
|
||||||
{
|
{
|
||||||
int j = at + 2;
|
int j = at + 2;
|
||||||
|
@ -28678,15 +28732,19 @@ bool NativeCodeBasicBlock::OptimizeSingleEntryLoop(NativeCodeProcedure* proc)
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int aimm = -1;
|
bool aimm = false;
|
||||||
|
NativeCodeInstruction ains;
|
||||||
|
|
||||||
if (!pblock->mExitRequiredRegs[CPU_REG_A] || !pblock->mExitRequiredRegs[CPU_REG_X])
|
if (!pblock->mExitRequiredRegs[CPU_REG_A] || !pblock->mExitRequiredRegs[CPU_REG_X])
|
||||||
{
|
{
|
||||||
for (int i = 0; i < mIns.Size(); i++)
|
for (int i = 0; i < mIns.Size(); i++)
|
||||||
{
|
{
|
||||||
if (mIns[i].mType == ASMIT_LDA && mIns[i].mMode == ASMIM_IMMEDIATE)
|
if (mIns[i].mType == ASMIT_LDA && (mIns[i].mMode == ASMIM_IMMEDIATE || mIns[i].mMode == ASMIM_IMMEDIATE_ADDRESS))
|
||||||
aimm = mIns[i].mAddress;
|
{
|
||||||
else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm >= 0)
|
aimm = true;
|
||||||
|
ains = mIns[i];
|
||||||
|
}
|
||||||
|
else if (mIns[i].mType == ASMIT_STA && mIns[i].mMode == ASMIM_ZERO_PAGE && aimm)
|
||||||
{
|
{
|
||||||
int reg = mIns[i].mAddress;
|
int reg = mIns[i].mAddress;
|
||||||
if (!ReferencedOnPath(this, 0, i, reg) && !ChangedOnPath(this, i + 1, mIns.Size(), reg))
|
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])
|
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));
|
pblock->mIns.Push(NativeCodeInstruction(mIns[i].mIns, ASMIT_STA, ASMIM_ZERO_PAGE, reg));
|
||||||
}
|
}
|
||||||
else if (!pblock->mExitRequiredRegs[CPU_REG_X])
|
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));
|
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())
|
else if (mIns[i].ChangesAccu())
|
||||||
aimm = -1;
|
aimm = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33760,6 +33818,20 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
|
|
||||||
#endif
|
#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
|
#if 1
|
||||||
// move load - store abs up to initial store
|
// move load - store abs up to initial store
|
||||||
//
|
//
|
||||||
|
@ -38380,6 +38452,26 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
|
||||||
progress = true;
|
progress = true;
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
#if 0
|
||||||
else if (
|
else if (
|
||||||
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
mIns[i + 0].mType == ASMIT_LDY && mIns[i + 0].mMode == ASMIM_ZERO_PAGE &&
|
||||||
|
@ -40692,7 +40784,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
|
||||||
{
|
{
|
||||||
mInterProc = proc;
|
mInterProc = proc;
|
||||||
|
|
||||||
CheckFunc = !strcmp(mInterProc->mIdent->mString, "time_draw");
|
CheckFunc = !strcmp(mInterProc->mIdent->mString, "main");
|
||||||
|
|
||||||
int nblocks = proc->mBlocks.Size();
|
int nblocks = proc->mBlocks.Size();
|
||||||
tblocks = new NativeCodeBasicBlock * [nblocks];
|
tblocks = new NativeCodeBasicBlock * [nblocks];
|
||||||
|
|
|
@ -410,6 +410,7 @@ public:
|
||||||
bool MoveLoadAddZPStoreUp(int at);
|
bool MoveLoadAddZPStoreUp(int at);
|
||||||
bool MoveLoadShiftRotateUp(int at);
|
bool MoveLoadShiftRotateUp(int at);
|
||||||
bool MoveLoadShiftStoreUp(int at);
|
bool MoveLoadShiftStoreUp(int at);
|
||||||
|
bool MoveTYADCStoreDown(int at);
|
||||||
|
|
||||||
bool MoveLDSTXOutOfRange(int at);
|
bool MoveLDSTXOutOfRange(int at);
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ Parser::Parser(Errors* errors, Scanner* scanner, CompilationUnits* compilationUn
|
||||||
{
|
{
|
||||||
mGlobals = new DeclarationScope(compilationUnits->mScope, SLEVEL_STATIC);
|
mGlobals = new DeclarationScope(compilationUnits->mScope, SLEVEL_STATIC);
|
||||||
mScope = mGlobals;
|
mScope = mGlobals;
|
||||||
|
mTemplateScope = nullptr;
|
||||||
|
|
||||||
mCodeSection = compilationUnits->mSectionCode;
|
mCodeSection = compilationUnits->mSectionCode;
|
||||||
mDataSection = compilationUnits->mSectionData;
|
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)
|
Declaration* Parser::FindBaseMemberFunction(Declaration* dec, Declaration* mdec)
|
||||||
{
|
{
|
||||||
const Ident* ident = mdec->mIdent;
|
const Ident* ident = mdec->mIdent;
|
||||||
|
@ -117,7 +132,15 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
|
||||||
structName = mScanner->mTokenIdent;
|
structName = mScanner->mTokenIdent;
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
Declaration* edec = mScope->Lookup(structName);
|
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;
|
dec = edec;
|
||||||
}
|
}
|
||||||
|
@ -562,11 +585,20 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
|
||||||
|
|
||||||
case TK_IDENT:
|
case TK_IDENT:
|
||||||
pident = mScanner->mTokenIdent;
|
pident = mScanner->mTokenIdent;
|
||||||
|
if (mTemplateScope)
|
||||||
|
dec = mTemplateScope->Lookup(mScanner->mTokenIdent);
|
||||||
|
|
||||||
|
if (!dec)
|
||||||
|
{
|
||||||
dec = mScope->Lookup(mScanner->mTokenIdent);
|
dec = mScope->Lookup(mScanner->mTokenIdent);
|
||||||
if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS)
|
if (dec && dec->mType == DT_CONST_FUNCTION && mScope->mLevel == SLEVEL_CLASS)
|
||||||
dec = mScope->mParent->Lookup(mScanner->mTokenIdent);
|
dec = mScope->mParent->Lookup(mScanner->mTokenIdent);
|
||||||
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
|
|
||||||
|
if (dec && dec->mType == DT_TEMPLATE)
|
||||||
|
dec = ParseTemplateExpansion(dec, nullptr);
|
||||||
|
|
||||||
while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON))
|
while (qualified && dec && dec->mType == DT_TYPE_STRUCT && ConsumeTokenIf(TK_COLCOLON))
|
||||||
{
|
{
|
||||||
if (ExpectToken(TK_IDENT))
|
if (ExpectToken(TK_IDENT))
|
||||||
|
@ -609,6 +641,9 @@ Declaration* Parser::ParseBaseTypeDeclaration(uint64 flags, bool qualified)
|
||||||
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident);
|
mErrors->Error(mScanner->mLocation, EERR_OBJECT_NOT_FOUND, "Identifier not defined", pident);
|
||||||
else
|
else
|
||||||
mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent);
|
mErrors->Error(mScanner->mLocation, EERR_NOT_A_TYPE, "Identifier is no type", dec->mQualIdent);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mScanner->NextToken();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TK_ENUM:
|
case TK_ENUM:
|
||||||
|
@ -804,10 +839,26 @@ Declaration* Parser::ParsePostfixDeclaration(void)
|
||||||
{
|
{
|
||||||
dec = new Declaration(mScanner->mLocation, DT_VARIABLE);
|
dec = new Declaration(mScanner->mLocation, DT_VARIABLE);
|
||||||
dec->mIdent = mScanner->mTokenIdent;
|
dec->mIdent = mScanner->mTokenIdent;
|
||||||
dec->mQualIdent = mScope->Mangle(dec->mIdent);
|
|
||||||
dec->mSection = mBSSection;
|
dec->mSection = mBSSection;
|
||||||
dec->mBase = nullptr;
|
dec->mBase = nullptr;
|
||||||
mScanner->NextToken();
|
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)
|
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
|
// 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;
|
cexp->mToken = pex->mToken;
|
||||||
|
|
||||||
pex->mType = EX_INITIALIZATION;
|
pex->mType = EX_INITIALIZATION;
|
||||||
|
pex->mToken = TK_ASSIGN;
|
||||||
pex->mLeft = vexp;
|
pex->mLeft = vexp;
|
||||||
pex->mRight = cexp;
|
pex->mRight = cexp;
|
||||||
pex->mDecValue = nullptr;
|
pex->mDecValue = nullptr;
|
||||||
|
@ -2990,6 +3042,38 @@ Expression* Parser::AddFunctionCallRefReturned(Expression* exp)
|
||||||
rexp = ConcatExpression(rexp, dexp);
|
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;
|
pdec = pdec->mNext;
|
||||||
}
|
}
|
||||||
|
@ -4108,7 +4192,15 @@ Expression* Parser::ParseDeclarationExpression(Declaration * pdec)
|
||||||
|
|
||||||
Declaration* Parser::ParseQualIdent(void)
|
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)
|
if (dec)
|
||||||
{
|
{
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
|
@ -4371,6 +4463,9 @@ Expression* Parser::ParseSimpleExpression(bool lhs)
|
||||||
dec = ParseQualIdent();
|
dec = ParseQualIdent();
|
||||||
if (dec)
|
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)
|
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);
|
exp = new Expression(mScanner->mLocation, EX_CONSTANT);
|
||||||
|
@ -6980,10 +7075,153 @@ Expression* Parser::ParseSwitchStatement(void)
|
||||||
return sexp;
|
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);
|
ConsumeToken(TK_LESS_THAN);
|
||||||
Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
|
Declaration* tdec = new Declaration(mScanner->mLocation, DT_TEMPLATE);
|
||||||
|
tdec->mParser = this->Clone();
|
||||||
|
tdec->mScope = new DeclarationScope(nullptr, SLEVEL_TEMPLATE);
|
||||||
Declaration* ppdec = nullptr;
|
Declaration* ppdec = nullptr;
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
|
@ -6994,9 +7232,8 @@ void Parser::ParseTemplate(void)
|
||||||
{
|
{
|
||||||
if (mScanner->mToken == TK_IDENT)
|
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->mIdent = mScanner->mTokenIdent;
|
||||||
pdec->mBase = TheVoidTypeDeclaration;
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -7006,9 +7243,8 @@ void Parser::ParseTemplate(void)
|
||||||
{
|
{
|
||||||
if (mScanner->mToken == TK_IDENT)
|
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->mIdent = mScanner->mTokenIdent;
|
||||||
pdec->mBase = TheSignedIntTypeDeclaration;
|
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -7019,6 +7255,9 @@ void Parser::ParseTemplate(void)
|
||||||
|
|
||||||
if (pdec)
|
if (pdec)
|
||||||
{
|
{
|
||||||
|
tdec->mScope->Insert(pdec->mIdent, pdec);
|
||||||
|
pdec->mFlags |= DTF_DEFINED;
|
||||||
|
|
||||||
if (ppdec)
|
if (ppdec)
|
||||||
ppdec->mNext = pdec;
|
ppdec->mNext = pdec;
|
||||||
else
|
else
|
||||||
|
@ -7032,16 +7271,86 @@ void Parser::ParseTemplate(void)
|
||||||
|
|
||||||
ConsumeToken(TK_GREATER_THAN);
|
ConsumeToken(TK_GREATER_THAN);
|
||||||
|
|
||||||
|
mScanner->BeginRecord();
|
||||||
if (mScanner->mToken == TK_CLASS)
|
if (mScanner->mToken == TK_CLASS)
|
||||||
{
|
{
|
||||||
// Class template
|
// 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
|
else
|
||||||
{
|
{
|
||||||
// Function template
|
// 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)
|
else if (mScanner->mToken == TK_TEMPLATE)
|
||||||
{
|
{
|
||||||
mScanner->NextToken();
|
mScanner->NextToken();
|
||||||
ParseTemplate();
|
ParseTemplateDeclaration();
|
||||||
}
|
}
|
||||||
else if (mScanner->mToken == TK_NAMESPACE)
|
else if (mScanner->mToken == TK_NAMESPACE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,9 @@ public:
|
||||||
Parser(Errors * errors, Scanner* scanner, CompilationUnits * compilationUnits);
|
Parser(Errors * errors, Scanner* scanner, CompilationUnits * compilationUnits);
|
||||||
~Parser(void);
|
~Parser(void);
|
||||||
|
|
||||||
DeclarationScope * mGlobals, * mScope;
|
Parser* Clone(void);
|
||||||
|
|
||||||
|
DeclarationScope * mGlobals, * mScope, * mTemplateScope;
|
||||||
int mLocalIndex;
|
int mLocalIndex;
|
||||||
CompilationUnits * mCompilationUnits;
|
CompilationUnits * mCompilationUnits;
|
||||||
Declaration * mThisPointer, * mReturnType;
|
Declaration * mThisPointer, * mReturnType;
|
||||||
|
@ -93,7 +95,9 @@ protected:
|
||||||
bool CanCoerceExpression(Expression* exp, Declaration* type);
|
bool CanCoerceExpression(Expression* exp, Declaration* type);
|
||||||
void CompleteFunctionDefaultParams(Expression* exp);
|
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* ParseSimpleExpression(bool lhs);
|
||||||
Expression* ParsePrefixExpression(bool lhs);
|
Expression* ParsePrefixExpression(bool lhs);
|
||||||
|
|
|
@ -309,7 +309,7 @@ Macro* MacroDict::Lookup(const Ident* ident)
|
||||||
|
|
||||||
TokenSequence::TokenSequence(Scanner* scanner)
|
TokenSequence::TokenSequence(Scanner* scanner)
|
||||||
: mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken),
|
: mNext(nullptr), mLocation(scanner->mLocation), mToken(scanner->mToken),
|
||||||
mTokenIdent(scanner->mTokenIdent), mTokenChar(scanner->mTokenChar),
|
mTokenIdent(scanner->mTokenIdent),
|
||||||
mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber),
|
mTokenInteger(scanner->mTokenInteger), mTokenNumber(scanner->mTokenNumber),
|
||||||
mTokenString(nullptr)
|
mTokenString(nullptr)
|
||||||
{
|
{
|
||||||
|
@ -345,6 +345,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor)
|
||||||
mToken = TK_NONE;
|
mToken = TK_NONE;
|
||||||
mUngetToken = TK_NONE;
|
mUngetToken = TK_NONE;
|
||||||
mReplay = nullptr;
|
mReplay = nullptr;
|
||||||
|
mRecord = mRecordLast = nullptr;
|
||||||
|
|
||||||
mOnceDict = new MacroDict();
|
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* Scanner::Replay(const TokenSequence* replay)
|
||||||
{
|
{
|
||||||
const TokenSequence* seq = mReplay;
|
const TokenSequence* seq = mReplay;
|
||||||
mReplay = replay;
|
mReplay = replay;
|
||||||
|
NextToken();
|
||||||
return seq;
|
return seq;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,16 +472,27 @@ void Scanner::NextToken(void)
|
||||||
mToken = mReplay->mToken;
|
mToken = mReplay->mToken;
|
||||||
|
|
||||||
mTokenIdent = mReplay->mTokenIdent;
|
mTokenIdent = mReplay->mTokenIdent;
|
||||||
mTokenChar = mReplay->mTokenChar;
|
|
||||||
mTokenNumber = mReplay->mTokenNumber;
|
mTokenNumber = mReplay->mTokenNumber;
|
||||||
mTokenInteger = mReplay->mTokenInteger;
|
mTokenInteger = mReplay->mTokenInteger;
|
||||||
if (mReplay->mTokenString)
|
if (mReplay->mTokenString)
|
||||||
strcpy_s(mTokenString, mReplay->mTokenString);
|
strcpy_s(mTokenString, mReplay->mTokenString);
|
||||||
|
|
||||||
mReplay = mReplay->mNext;
|
mReplay = mReplay->mNext;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NextPreToken();
|
||||||
|
|
||||||
|
if (mRecord)
|
||||||
|
{
|
||||||
|
mRecordLast->mNext = new TokenSequence(this);
|
||||||
|
mRecordLast = mRecordLast->mNext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Scanner::NextPreToken(void)
|
||||||
|
{
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
NextRawToken();
|
NextRawToken();
|
||||||
|
|
|
@ -214,7 +214,6 @@ struct TokenSequence
|
||||||
Token mToken;
|
Token mToken;
|
||||||
|
|
||||||
const Ident * mTokenIdent;
|
const Ident * mTokenIdent;
|
||||||
char mTokenChar;
|
|
||||||
const char * mTokenString;
|
const char * mTokenString;
|
||||||
double mTokenNumber;
|
double mTokenNumber;
|
||||||
int64 mTokenInteger;
|
int64 mTokenInteger;
|
||||||
|
@ -233,7 +232,9 @@ public:
|
||||||
|
|
||||||
void NextToken(void);
|
void NextToken(void);
|
||||||
|
|
||||||
TokenSequence* Record(void);
|
void BeginRecord(void);
|
||||||
|
TokenSequence* CompleteRecord(void);
|
||||||
|
|
||||||
const TokenSequence* Replay(const TokenSequence * sequence);
|
const TokenSequence* Replay(const TokenSequence * sequence);
|
||||||
|
|
||||||
void Warning(const char * error);
|
void Warning(const char * error);
|
||||||
|
@ -272,6 +273,7 @@ public:
|
||||||
void MarkSourceOnce(void);
|
void MarkSourceOnce(void);
|
||||||
protected:
|
protected:
|
||||||
void NextRawToken(void);
|
void NextRawToken(void);
|
||||||
|
void NextPreToken(void);
|
||||||
|
|
||||||
struct MacroExpansion
|
struct MacroExpansion
|
||||||
{
|
{
|
||||||
|
@ -289,6 +291,7 @@ protected:
|
||||||
Token mUngetToken;
|
Token mUngetToken;
|
||||||
|
|
||||||
const TokenSequence* mReplay;
|
const TokenSequence* mReplay;
|
||||||
|
TokenSequence* mRecord, * mRecordLast;
|
||||||
|
|
||||||
void StringToken(char terminator, char mode);
|
void StringToken(char terminator, char mode);
|
||||||
void CharToken(char mode);
|
void CharToken(char mode);
|
||||||
|
|
Loading…
Reference in New Issue