Array constructors

This commit is contained in:
drmortalwombat 2023-06-25 22:24:13 +02:00
parent 0f67f7150f
commit 0b1b4a7d9b
9 changed files with 901 additions and 145 deletions

View File

@ -20,7 +20,7 @@ The goal was also to implement the C99 standard and not some subset for performa
After extensive optimizations it turns out, that the interpreted code is not significantly smaller than the native code in most scenarios (although there are cases where the difference is significant).
## Limits and Errors
There are still several open areas, but most targets have been reached. The current Dhrystone performance is 94 iterations per second with byte code (11696) and 395 iterations with native code (10425 Bytes). This clearly shows that Dhrystone is not a valid benchmark for optimizing compilers, because it puts the 6502 on par with a 4MHz 8088 or 68k, which it clearly is not.
@ -48,6 +48,18 @@ There are still several open areas, but most targets have been reached. The cur
### Native code generation
### C++ support level
The compiler will most likely not support a current C++ standard in the near future, but several C++ features are already implemented. The compiler can be switched into C++ mode with the command line option -pp or by providing a source file with a .cpp extension.
Supported Features:
* namespaces
* reference types
* member functions
* constructors and destructors
* operator overloading (assignment)
## Installation and Usage
### Installing on windows
@ -62,7 +74,7 @@ The compiler can also be built using MSVC or GCC. A visual studio project and a
The compiler is command line driven, and creates an executable .prg file.
oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c}
oscar64 {-i=includePath} [-o=output.prg] [-rt=runtime.c] [-tf=format] [-tm=machine] [-e] [-n] [-dSYMBOL[=value]] {source.c|source.cpp}
* -v : verbose output for diagnostics
* -v2 : more verbose output
@ -90,6 +102,7 @@ The compiler is command line driven, and creates an executable .prg file.
* -fz : add a compressed binary file to the disk image
* -xz : extended zero page usage, more zero page space, but no return to basic
* -cid : cartridge type ID, used by vice emulator
* -pp : compile in C++ mode
A list of source files can be provided.

151
autotest/arrayconstruct.cpp Normal file
View File

@ -0,0 +1,151 @@
#include <assert.h>
int t, n, m, k;
struct C1
{
int a;
C1(void);
~C1(void);
C1(const C1 & c);
C1 & operator=(const C1 & c);
};
struct C2
{
C1 nc[10], mc[20];
};
C1::C1(void)
{
a = 1;
n++;
t++;
}
C1::C1(const C1 & c)
{
a = c.a;
k++;
t++;
}
C1 & C1::operator=(const C1 & c)
{
a = c.a;
m++;
return *this;
}
C1::~C1(void)
{
t--;
}
void test_local_init(void)
{
n = 0;
{
C1 c[10];
}
assert(n == 10 && t == 0);
}
void test_member_init(void)
{
n = 0;
{
C2 d;
}
assert(n == 30 && t == 0);
}
void test_member_array_init(void)
{
n = 0;
{
C2 d[5];
}
assert(n == 150 && t == 0);
}
void test_local_copy(void)
{
n = 0;
k = 0;
{
C1 c[10];
C1 d(c[4]);
}
assert(n == 10 && k == 1 && t == 0);
}
void test_member_copy(void)
{
n = 0;
k = 0;
{
C2 d;
C2 e(d);
}
assert(n == 30 && k == 30 && t == 0);
}
void test_local_assign(void)
{
n = 0;
k = 0;
m = 0;
{
C1 c[10];
C1 d[5];
d[4] = c[2];
}
assert(n == 15 && k == 0 && m == 1 && t == 0);
}
void test_member_assign(void)
{
n = 0;
k = 0;
m = 0;
{
C2 d;
C2 e;
e = d;
}
assert(n == 60 && k == 0 && m == 30 && t == 0);
}
int main(void)
{
test_local_init();
test_member_init();
test_member_array_init();
test_local_copy();
test_member_copy();
test_local_assign();
test_member_assign();
return 0;
}

View File

@ -9,6 +9,9 @@ rem @echo off
@call :test copyassign.cpp
@if %errorlevel% neq 0 goto :error
@call :test arrayconstruct.cpp
@if %errorlevel% neq 0 goto :error
@call :test stdlibtest.c
@if %errorlevel% neq 0 goto :error

View File

@ -778,7 +778,8 @@ Declaration::Declaration(const Location& loc, DecType type)
: mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr),
mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0),
mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr),
mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr),
mConstructor(nullptr), mDestructor(nullptr), mCopyConstructor(nullptr), mCopyAssignment(nullptr),
mVectorConstructor(nullptr), mVectorDestructor(nullptr), mVectorCopyConstructor(nullptr), mVectorCopyAssignment(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)

View File

@ -222,7 +222,10 @@ public:
Location mLocation, mEndLocation;
DecType mType;
Token mToken;
Declaration* mBase, *mParams, * mNext, * mPrev, * mConst, * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
Declaration * mBase, * mParams, * mNext, * mPrev, * mConst;
Declaration * mConstructor, * mDestructor, * mCopyConstructor, * mCopyAssignment;
Declaration * mVectorConstructor, * mVectorDestructor, * mVectorCopyConstructor, * mVectorCopyAssignment;
Expression* mValue;
DeclarationScope* mScope;
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe;

View File

@ -16017,7 +16017,7 @@ void InterCodeProcedure::Close(void)
{
GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "test_retparam_value");
CheckFunc = !strcmp(mIdent->mString, "test");
mEntryBlock = mBlocks[0];

View File

@ -4329,6 +4329,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value"))
exp->Dump(0);
#endif
#if 0
if (proc->mIdent)
{
printf("TRANS %s\n", proc->mIdent->mString);
exp->Dump(0);
}
#endif
uint64 outerCompilerOptions = mCompilerOptions;
mCompilerOptions = dec->mCompilerOptions;

View File

@ -36463,6 +36463,7 @@ bool NativeCodeBasicBlock::PeepHoleOptimizer(NativeCodeProcedure* proc, int pass
mIns[i + 2].mType == ASMIT_LDA && mIns[i + 2].mMode == ASMIM_ZERO_PAGE &&
mIns[i + 3].mType == ASMIT_ORA && mIns[i + 3].SameEffectiveAddress(mIns[i + 0]) && mIns[i + 3].mMode != ASMIM_IMMEDIATE)
{
mIns[i + 1].mLive |= LIVE_CPU_REG_A;
mIns[i + 2].mType = ASMIT_ORA; mIns[i + 2].mLive |= mIns[i + 3].mLive & LIVE_CPU_REG_Z;
mIns[i + 3].mType = ASMIT_NOP; mIns[i + 3].mMode = ASMIM_IMPLIED;

View File

@ -1243,43 +1243,79 @@ void Parser::PrependMemberConstructor(Declaration* pthis, Declaration* cfunc)
sexp->mRight = cfunc->mValue;
cfunc->mValue = sexp;
}
else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor)
else
{
Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
qexp->mLeft = thisexp;
qexp->mDecValue = dec;
qexp->mDecType = dec->mBase;
Declaration* bdec = dec->mBase;
while (bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = qexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
Declaration* mdec = dec->mBase->mConstructor;
while (mdec && mdec->mBase->mParams->mNext)
mdec = mdec->mNext;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
if (mdec)
if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor)
{
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
qexp->mLeft = thisexp;
qexp->mDecValue = dec;
Expression* dexp;
if (dec->mSize == bdec->mSize)
{
qexp->mDecType = bdec;
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = qexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = bdec;
pexp->mDecType->mSize = 2;
Declaration* mdec = bdec->mConstructor;
while (mdec && mdec->mBase->mParams->mNext)
mdec = mdec->mNext;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
if (mdec)
{
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
}
else
mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor");
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = pexp;
}
else
{
qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
qexp->mDecType->mBase = bdec;
qexp->mDecType->mSize = 2;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorConstructor;
cexp->mDecType = cexp->mDecValue->mBase;
Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
ncdec->mBase = TheUnsignedIntTypeDeclaration;
ncdec->mInteger = dec->mSize / bdec->mSize;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
dexp->mRight->mLeft = qexp;
dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT);
dexp->mRight->mRight->mDecType = ncdec->mBase;
dexp->mRight->mRight->mDecValue = ncdec;
}
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
sexp->mLeft = dexp;
sexp->mRight = cfunc->mValue;
cfunc->mValue = sexp;
}
else
mErrors->Error(dec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor");
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = pexp;
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
sexp->mLeft = dexp;
sexp->mRight = cfunc->mValue;
cfunc->mValue = sexp;
}
}
@ -1352,12 +1388,21 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
Declaration* dec = pthis->mBase->mParams;
while (dec)
{
if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT)
if (dec->mType == DT_ELEMENT)
{
if (dec->mBase->mDestructor)
simpleDestructor = false;
if (dec->mBase->mCopyAssignment)
simpleAssignment = false;
Declaration* bdec = dec->mBase;
int nitems = 1;
while (bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
if (bdec->mType == DT_TYPE_STRUCT)
{
if (bdec->mDestructor)
simpleDestructor = false;
if (bdec->mCopyAssignment)
simpleAssignment = false;
}
}
dec = dec->mNext;
}
@ -1521,27 +1566,65 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
Expression* mexp;
if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyConstructor)
Declaration* bdec = dec->mBase;
while (bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
if (bdec->mType == DT_TYPE_STRUCT && bdec->mCopyConstructor)
{
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = lexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
if (dec->mSize == bdec->mSize)
{
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = lexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
Declaration* mdec = dec->mBase->mCopyConstructor;
Declaration* mdec = dec->mBase->mCopyConstructor;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp;
}
else
{
lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
lexp->mDecType->mBase = bdec;
lexp->mDecType->mSize = 2;
rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
rexp->mDecType->mBase = bdec;
rexp->mDecType->mSize = 2;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorCopyConstructor;
cexp->mDecType = cexp->mDecValue->mBase;
Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
ncdec->mBase = TheUnsignedIntTypeDeclaration;
ncdec->mInteger = dec->mSize / bdec->mSize;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = lexp;
mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mRight->mLeft = rexp;
mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT);
mexp->mRight->mRight->mRight->mDecType = ncdec->mBase;
mexp->mRight->mRight->mRight->mDecValue = ncdec;
}
}
else
{
@ -1661,27 +1744,64 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
Expression* mexp;
if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mCopyAssignment)
Declaration* bdec = dec->mBase;
while (bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
if (bdec->mType == DT_TYPE_STRUCT && bdec->mCopyAssignment)
{
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = lexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
if (dec->mSize == bdec->mSize)
{
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = lexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
Declaration* mdec = dec->mBase->mCopyAssignment;
Declaration* mdec = bdec->mCopyAssignment;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp;
}
else
{
lexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
lexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
lexp->mDecType->mBase = bdec;
lexp->mDecType->mSize = 2;
rexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
rexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
rexp->mDecType->mBase = bdec;
rexp->mDecType->mSize = 2;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorCopyAssignment;
cexp->mDecType = cexp->mDecValue->mBase;
Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
ncdec->mBase = TheUnsignedIntTypeDeclaration;
ncdec->mInteger = dec->mSize / bdec->mSize;
mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = lexp;
mexp->mRight->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mRight->mLeft = rexp;
mexp->mRight->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT);
mexp->mRight->mRight->mRight->mDecType = ncdec->mBase;
mexp->mRight->mRight->mRight->mDecValue = ncdec;
}
}
else
{
@ -1707,6 +1827,373 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
}
}
Declaration* dcons = pthis->mBase->mConstructor;
while (dcons && dcons->mBase->mParams->mNext)
dcons = dcons->mNext;
if (dcons && !pthis->mBase->mVectorConstructor)
{
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
ctdec->mSize = 0;
Declaration* pdec = nullptr;
ctdec->mBase = TheVoidTypeDeclaration;
ctdec->mFlags |= DTF_DEFINED;
Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
adec->mVarIndex = 0;
adec->mOffset = 0;
adec->mBase = TheUnsignedIntTypeDeclaration;
adec->mSize = adec->mBase->mSize;
adec->mIdent = adec->mQualIdent = Ident::Unique("n");
ctdec->mParams = adec;
Declaration* vthis = pthis->Clone();
vthis->mFlags &= ~DTF_CONST;
PrependThisArgument(ctdec, vthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
cdec->mFlags |= DTF_FUNC_CONSTRUCTOR;
cdec->mSection = mCodeSection;
if (mCompilerOptions & COPT_NATIVE)
cdec->mFlags |= DTF_NATIVE;
pthis->mBase->mVectorConstructor = cdec;
cdec->mIdent = pthis->mBase->mIdent;
cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent);
cdec->mCompilerOptions = mCompilerOptions;
cdec->mBase->mCompilerOptions = mCompilerOptions;
cdec->mVarIndex = -1;
cdec->mFlags |= DTF_DEFINED;
cdec->mNumVars = mLocalIndex;
Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE);
pexp->mDecType = vthis;
pexp->mDecValue = ctdec->mParams;
Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE);
aexp->mDecType = TheUnsignedIntTypeDeclaration;
aexp->mDecValue = adec;
Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
iexp->mToken = TK_INC;
iexp->mLeft = pexp;
Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
dexp->mToken = TK_DEC;
dexp->mLeft = aexp;
Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT);
fexp->mDecValue = dcons;
fexp->mDecType = fexp->mDecValue->mBase;
Expression*cexp = new Expression(mScanner->mLocation, EX_CALL);
cexp->mLeft = fexp;
cexp->mRight = iexp;
Expression * wexp = new Expression(mScanner->mLocation, EX_WHILE);
wexp->mLeft = aexp;
wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
wexp->mRight->mLeft = cexp;
wexp->mRight->mRight = dexp;
cdec->mValue = wexp;
}
if (pthis->mBase->mDestructor && !pthis->mBase->mVectorDestructor)
{
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
ctdec->mSize = 0;
Declaration* pdec = nullptr;
ctdec->mBase = TheVoidTypeDeclaration;
ctdec->mFlags |= DTF_DEFINED;
Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
adec->mVarIndex = 0;
adec->mOffset = 0;
adec->mBase = TheUnsignedIntTypeDeclaration;
adec->mSize = adec->mBase->mSize;
adec->mIdent = adec->mQualIdent = Ident::Unique("n");
ctdec->mParams = adec;
Declaration* vthis = pthis->Clone();
vthis->mFlags &= ~DTF_CONST;
PrependThisArgument(ctdec, vthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
cdec->mFlags |= DTF_FUNC_CONSTRUCTOR;
cdec->mSection = mCodeSection;
if (mCompilerOptions & COPT_NATIVE)
cdec->mFlags |= DTF_NATIVE;
pthis->mBase->mVectorDestructor = cdec;
char dname[100];
strcpy_s(dname, "~");
strcat_s(dname, pthis->mBase->mIdent->mString);
cdec->mIdent = Ident::Unique(dname);
cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent);
cdec->mCompilerOptions = mCompilerOptions;
cdec->mBase->mCompilerOptions = mCompilerOptions;
cdec->mVarIndex = -1;
cdec->mFlags |= DTF_DEFINED;
cdec->mNumVars = mLocalIndex;
Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE);
pexp->mDecType = vthis;
pexp->mDecValue = ctdec->mParams;
Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE);
aexp->mDecType = TheUnsignedIntTypeDeclaration;
aexp->mDecValue = adec;
Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
iexp->mToken = TK_INC;
iexp->mLeft = pexp;
Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
dexp->mToken = TK_DEC;
dexp->mLeft = aexp;
Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT);
fexp->mDecValue = pthis->mBase->mDestructor;
fexp->mDecType = fexp->mDecValue->mBase;
Expression* cexp = new Expression(mScanner->mLocation, EX_CALL);
cexp->mLeft = fexp;
cexp->mRight = iexp;
Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE);
wexp->mLeft = aexp;
wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
wexp->mRight->mLeft = cexp;
wexp->mRight->mRight = dexp;
cdec->mValue = wexp;
}
if (pthis->mBase->mCopyConstructor && !pthis->mBase->mVectorCopyConstructor)
{
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
ctdec->mSize = 0;
Declaration* pdec = nullptr;
ctdec->mBase = TheVoidTypeDeclaration;
ctdec->mFlags |= DTF_DEFINED;
Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
sdec->mVarIndex = 0;
sdec->mOffset = 0;
sdec->mBase = pthis->Clone();
sdec->mBase->mFlags &= ~DTF_CONST;
sdec->mSize = sdec->mBase->mSize;
sdec->mIdent = sdec->mQualIdent = Ident::Unique("_");
Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
adec->mVarIndex = 2;
adec->mOffset = 0;
adec->mBase = TheUnsignedIntTypeDeclaration;
adec->mSize = adec->mBase->mSize;
adec->mIdent = adec->mQualIdent = Ident::Unique("n");
sdec->mNext = adec;
ctdec->mParams = sdec;
Declaration* vthis = pthis->Clone();
vthis->mFlags &= ~DTF_CONST;
PrependThisArgument(ctdec, vthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
cdec->mFlags |= DTF_FUNC_CONSTRUCTOR;
cdec->mSection = mCodeSection;
if (mCompilerOptions & COPT_NATIVE)
cdec->mFlags |= DTF_NATIVE;
pthis->mBase->mVectorCopyConstructor = cdec;
cdec->mIdent = pthis->mBase->mIdent;
cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent);
cdec->mCompilerOptions = mCompilerOptions;
cdec->mBase->mCompilerOptions = mCompilerOptions;
cdec->mVarIndex = -1;
cdec->mFlags |= DTF_DEFINED;
cdec->mNumVars = mLocalIndex;
Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE);
pexp->mDecType = vthis;
pexp->mDecValue = ctdec->mParams;
Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE);
psexp->mDecType = vthis;
psexp->mDecValue = sdec;
Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE);
aexp->mDecType = TheUnsignedIntTypeDeclaration;
aexp->mDecValue = adec;
Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
iexp->mToken = TK_INC;
iexp->mLeft = pexp;
Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
isexp->mToken = TK_INC;
isexp->mLeft = psexp;
Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX);
disexp->mToken = TK_MUL;
disexp->mLeft = isexp;
disexp->mDecType = vthis->mBase;
Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
dexp->mToken = TK_DEC;
dexp->mLeft = aexp;
Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT);
fexp->mDecValue = pthis->mBase->mCopyConstructor;
fexp->mDecType = fexp->mDecValue->mBase;
Expression* cexp = new Expression(mScanner->mLocation, EX_CALL);
cexp->mLeft = fexp;
cexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
cexp->mRight->mLeft = iexp;
cexp->mRight->mRight = disexp;
Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE);
wexp->mLeft = aexp;
wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
wexp->mRight->mLeft = cexp;
wexp->mRight->mRight = dexp;
cdec->mValue = wexp;
}
if (pthis->mBase->mCopyAssignment && !pthis->mBase->mVectorCopyAssignment)
{
Declaration* ctdec = new Declaration(mScanner->mLocation, DT_TYPE_FUNCTION);
ctdec->mSize = 0;
Declaration* pdec = nullptr;
ctdec->mBase = TheVoidTypeDeclaration;
ctdec->mFlags |= DTF_DEFINED;
Declaration* sdec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
sdec->mVarIndex = 0;
sdec->mOffset = 0;
sdec->mBase = pthis->Clone();
sdec->mBase->mFlags &= ~DTF_CONST;
sdec->mSize = sdec->mBase->mSize;
sdec->mIdent = sdec->mQualIdent = Ident::Unique("_");
Declaration* adec = new Declaration(mScanner->mLocation, DT_ARGUMENT);
adec->mVarIndex = 2;
adec->mOffset = 0;
adec->mBase = TheUnsignedIntTypeDeclaration;
adec->mSize = adec->mBase->mSize;
adec->mIdent = adec->mQualIdent = Ident::Unique("n");
sdec->mNext = adec;
ctdec->mParams = sdec;
Declaration* vthis = pthis->Clone();
vthis->mFlags &= ~DTF_CONST;
PrependThisArgument(ctdec, vthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
cdec->mFlags |= DTF_FUNC_CONSTRUCTOR;
cdec->mSection = mCodeSection;
if (mCompilerOptions & COPT_NATIVE)
cdec->mFlags |= DTF_NATIVE;
pthis->mBase->mVectorCopyAssignment = cdec;
cdec->mIdent = pthis->mBase->mIdent;
cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent);
cdec->mCompilerOptions = mCompilerOptions;
cdec->mBase->mCompilerOptions = mCompilerOptions;
cdec->mVarIndex = -1;
cdec->mFlags |= DTF_DEFINED;
cdec->mNumVars = mLocalIndex;
Expression* pexp = new Expression(mScanner->mLocation, EX_VARIABLE);
pexp->mDecType = vthis;
pexp->mDecValue = ctdec->mParams;
Expression* psexp = new Expression(mScanner->mLocation, EX_VARIABLE);
psexp->mDecType = vthis;
psexp->mDecValue = sdec;
Expression* aexp = new Expression(mScanner->mLocation, EX_VARIABLE);
aexp->mDecType = TheUnsignedIntTypeDeclaration;
aexp->mDecValue = adec;
Expression* iexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
iexp->mToken = TK_INC;
iexp->mLeft = pexp;
Expression* isexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
isexp->mToken = TK_INC;
isexp->mLeft = psexp;
Expression* disexp = new Expression(mScanner->mLocation, EX_PREFIX);
disexp->mToken = TK_MUL;
disexp->mLeft = isexp;
disexp->mDecType = vthis->mBase;
Expression* dexp = new Expression(mScanner->mLocation, EX_POSTINCDEC);
dexp->mToken = TK_DEC;
dexp->mLeft = aexp;
Expression* fexp = new Expression(mScanner->mLocation, EX_CONSTANT);
fexp->mDecValue = pthis->mBase->mCopyAssignment;
fexp->mDecType = fexp->mDecValue->mBase;
Expression* cexp = new Expression(mScanner->mLocation, EX_CALL);
cexp->mLeft = fexp;
cexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
cexp->mRight->mLeft = iexp;
cexp->mRight->mRight = disexp;
Expression* wexp = new Expression(mScanner->mLocation, EX_WHILE);
wexp->mLeft = aexp;
wexp->mRight = new Expression(mScanner->mLocation, EX_SEQUENCE);
wexp->mRight->mLeft = cexp;
wexp->mRight->mRight = dexp;
cdec->mValue = wexp;
}
}
void Parser::AppendMemberDestructor(Declaration* pthis)
@ -1730,35 +2217,71 @@ void Parser::AppendMemberDestructor(Declaration* pthis)
dec = dec->Last();
while (dec)
{
if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mDestructor)
if (dec->mType == DT_ELEMENT)
{
Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
qexp->mLeft = thisexp;
qexp->mDecValue = dec;
qexp->mDecType = dec->mBase;
Declaration* bdec = dec->mBase;
while (bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = qexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor)
{
Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
qexp->mLeft = thisexp;
qexp->mDecValue = dec;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = dec->mBase->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* dexp;
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = pexp;
if (dec->mSize == bdec->mSize)
{
qexp->mDecType = bdec;
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mLeft = qexp;
pexp->mToken = TK_BINARY_AND;
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
pexp->mDecType->mBase = bdec;
pexp->mDecType->mSize = 2;
sexp->mLeft = pthis->mBase->mDestructor->mValue;
sexp->mRight = dexp;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
pthis->mBase->mDestructor->mValue = sexp;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = pexp;
}
else
{
qexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
qexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
qexp->mDecType->mBase = bdec;
qexp->mDecType->mSize = 2;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
ncdec->mBase = TheUnsignedIntTypeDeclaration;
ncdec->mInteger = dec->mSize / bdec->mSize;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
dexp->mRight->mLeft = qexp;
dexp->mRight->mRight = new Expression(mScanner->mLocation, EX_CONSTANT);
dexp->mRight->mRight->mDecType = ncdec->mBase;
dexp->mRight->mRight->mDecValue = ncdec;
}
Expression* sexp = new Expression(mScanner->mLocation, EX_SEQUENCE);
sexp->mLeft = pthis->mBase->mDestructor->mValue;
sexp->mRight = dexp;
pthis->mBase->mDestructor->mValue = sexp;
}
}
dec = dec->mPrev;
@ -2615,62 +3138,116 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
{
ParseVariableInit(ndec);
}
else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mBase->mConstructor && ndec->mType == DT_VARIABLE && !pthis)
else if ((mCompilerOptions & COPT_CPLUSPLUS) && ndec->mType == DT_VARIABLE && !pthis)
{
// Find default constructor
Declaration* cdec = ndec->mBase->mConstructor;
while (cdec && cdec->mBase->mParams->mNext)
cdec = cdec->mNext;
Declaration* bdec = ndec->mBase;
while (bdec && bdec->mType == DT_TYPE_ARRAY)
bdec = bdec->mBase;
if (cdec)
if (bdec && bdec->mConstructor)
{
Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE);
vexp->mDecType = ndec->mBase;
vexp->mDecValue = ndec;
Declaration* cdec = bdec->mConstructor;
while (cdec && cdec->mBase->mParams->mNext)
cdec = cdec->mNext;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = cdec;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp;
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = vexp;
texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = ndec->mBase;
texp->mDecType->mSize = 2;
fexp->mRight = texp;
Expression* dexp = nullptr;
if (ndec->mBase->mDestructor)
if (cdec)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = ndec->mBase->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE);
vexp->mDecType = ndec->mBase;
vexp->mDecValue = ndec;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = texp;
Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = vexp;
texp->mDecType = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_DEFINED;
texp->mDecType->mBase = bdec;
texp->mDecType->mSize = 2;
if (bdec->mSize == ndec->mBase->mSize)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = cdec;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp;
fexp->mRight = texp;
Expression* dexp = nullptr;
if (ndec->mBase->mDestructor)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = ndec->mBase->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = texp;
}
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT);
nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST);
nexp->mLeft->mLeft = fexp;
nexp->mLeft->mRight = dexp;
nexp->mRight = vexp;
nexp->mDecType = vexp->mDecType;
ndec->mValue = nexp;
}
else
{
Declaration* ncdec = new Declaration(mScanner->mLocation, DT_CONST_INTEGER);
ncdec->mBase = TheUnsignedIntTypeDeclaration;
ncdec->mInteger = ndec->mSize / bdec->mSize;
Expression * ncexp = new Expression(mScanner->mLocation, EX_CONSTANT);
ncexp->mDecType = ncdec->mBase;
ncexp->mDecValue = ncdec;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorConstructor;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* fexp = new Expression(mScanner->mLocation, EX_CALL);
fexp->mLeft = cexp;
fexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
fexp->mRight->mLeft = vexp;
fexp->mRight->mRight = ncexp;
Expression* dexp = nullptr;
if (bdec->mDestructor)
{
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT);
cexp->mDecValue = bdec->mVectorDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
dexp = new Expression(mScanner->mLocation, EX_CALL);
dexp->mLeft = cexp;
dexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
dexp->mRight->mLeft = vexp;
dexp->mRight->mRight = ncexp;
}
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT);
nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST);
nexp->mLeft->mLeft = fexp;
nexp->mLeft->mRight = dexp;
nexp->mRight = vexp;
nexp->mDecType = vexp->mDecType;
ndec->mValue = nexp;
}
}
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT);
nexp->mLeft = new Expression(mScanner->mLocation, EX_LIST);
nexp->mLeft->mLeft = fexp;
nexp->mLeft->mRight = dexp;
nexp->mRight = vexp;
nexp->mDecType = vexp->mDecType;
ndec->mValue = nexp;
else
mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent);
}
else
mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent);
}
if (storageFlags & DTF_EXPORT)