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

@ -48,6 +48,18 @@ There are still several open areas, but most targets have been reached. The cur
### Native code generation ### 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 ## Installation and Usage
### Installing on windows ### 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. 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 * -v : verbose output for diagnostics
* -v2 : more verbose output * -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 * -fz : add a compressed binary file to the disk image
* -xz : extended zero page usage, more zero page space, but no return to basic * -xz : extended zero page usage, more zero page space, but no return to basic
* -cid : cartridge type ID, used by vice emulator * -cid : cartridge type ID, used by vice emulator
* -pp : compile in C++ mode
A list of source files can be provided. 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 @call :test copyassign.cpp
@if %errorlevel% neq 0 goto :error @if %errorlevel% neq 0 goto :error
@call :test arrayconstruct.cpp
@if %errorlevel% neq 0 goto :error
@call :test stdlibtest.c @call :test stdlibtest.c
@if %errorlevel% neq 0 goto :error @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), : mLocation(loc), mEndLocation(loc), mType(type), mScope(nullptr), mData(nullptr), mIdent(nullptr), mQualIdent(nullptr),
mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0), mSize(0), mOffset(0), mFlags(0), mComplexity(0), mLocalSize(0),
mBase(nullptr), mParams(nullptr), mValue(nullptr), mNext(nullptr), mPrev(nullptr), mConst(nullptr), 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), 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)

View File

@ -222,7 +222,10 @@ public:
Location mLocation, mEndLocation; Location mLocation, mEndLocation;
DecType mType; DecType mType;
Token mToken; 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; Expression* mValue;
DeclarationScope* mScope; DeclarationScope* mScope;
int mOffset, mSize, mVarIndex, mNumVars, mComplexity, mLocalSize, mAlignment, mFastCallBase, mFastCallSize, mStride, mStripe; 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); GrowingTypeArray tstack(IT_NONE);
CheckFunc = !strcmp(mIdent->mString, "test_retparam_value"); CheckFunc = !strcmp(mIdent->mString, "test");
mEntryBlock = mBlocks[0]; mEntryBlock = mBlocks[0];

View File

@ -4329,6 +4329,13 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value")) if (proc->mIdent && !strcmp(proc->mIdent->mString, "test_retparam_value"))
exp->Dump(0); exp->Dump(0);
#endif #endif
#if 0
if (proc->mIdent)
{
printf("TRANS %s\n", proc->mIdent->mString);
exp->Dump(0);
}
#endif
uint64 outerCompilerOptions = mCompilerOptions; uint64 outerCompilerOptions = mCompilerOptions;
mCompilerOptions = dec->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 + 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 + 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 + 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; 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; sexp->mRight = cfunc->mValue;
cfunc->mValue = sexp; cfunc->mValue = sexp;
} }
else if (dec->mBase->mType == DT_TYPE_STRUCT && dec->mBase->mConstructor) else
{ {
Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY); Declaration* bdec = dec->mBase;
qexp->mLeft = thisexp; while (bdec->mType == DT_TYPE_ARRAY)
qexp->mDecValue = dec; bdec = bdec->mBase;
qexp->mDecType = dec->mBase;
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor)
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)
{ {
cexp->mDecValue = mdec; Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
cexp->mDecType = cexp->mDecValue->mBase; 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; Declaration* dec = pthis->mBase->mParams;
while (dec) while (dec)
{ {
if (dec->mType == DT_ELEMENT && dec->mBase->mType == DT_TYPE_STRUCT) if (dec->mType == DT_ELEMENT)
{ {
if (dec->mBase->mDestructor) Declaration* bdec = dec->mBase;
simpleDestructor = false; int nitems = 1;
if (dec->mBase->mCopyAssignment)
simpleAssignment = false; 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; dec = dec->mNext;
} }
@ -1521,27 +1566,65 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
Expression* mexp; 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); if (dec->mSize == bdec->mSize)
pexp->mLeft = lexp; {
pexp->mToken = TK_BINARY_AND; Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); pexp->mLeft = lexp;
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; pexp->mToken = TK_BINARY_AND;
pexp->mDecType->mBase = dec->mBase; pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mSize = 2; 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); Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec; cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase; cexp->mDecType = cexp->mDecValue->mBase;
mexp = new Expression(mScanner->mLocation, EX_CALL); mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp; mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp; mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp; 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 else
{ {
@ -1661,27 +1744,64 @@ void Parser::AddDefaultConstructors(Declaration* pthis)
Expression* mexp; 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); if (dec->mSize == bdec->mSize)
pexp->mLeft = lexp; {
pexp->mToken = TK_BINARY_AND; Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX);
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); pexp->mLeft = lexp;
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; pexp->mToken = TK_BINARY_AND;
pexp->mDecType->mBase = dec->mBase; pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER);
pexp->mDecType->mSize = 2; 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); Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
cexp->mDecValue = mdec; cexp->mDecValue = mdec;
cexp->mDecType = cexp->mDecValue->mBase; cexp->mDecType = cexp->mDecValue->mBase;
mexp = new Expression(mScanner->mLocation, EX_CALL); mexp = new Expression(mScanner->mLocation, EX_CALL);
mexp->mLeft = cexp; mexp->mLeft = cexp;
mexp->mRight = new Expression(mScanner->mLocation, EX_LIST); mexp->mRight = new Expression(mScanner->mLocation, EX_LIST);
mexp->mRight->mLeft = pexp; mexp->mRight->mLeft = pexp;
mexp->mRight->mRight = rexp; 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 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) void Parser::AppendMemberDestructor(Declaration* pthis)
@ -1730,35 +2217,71 @@ void Parser::AppendMemberDestructor(Declaration* pthis)
dec = dec->Last(); dec = dec->Last();
while (dec) 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); Declaration* bdec = dec->mBase;
qexp->mLeft = thisexp; while (bdec->mType == DT_TYPE_ARRAY)
qexp->mDecValue = dec; bdec = bdec->mBase;
qexp->mDecType = dec->mBase;
Expression* pexp = new Expression(pthis->mLocation, EX_PREFIX); if (bdec->mType == DT_TYPE_STRUCT && bdec->mConstructor)
pexp->mLeft = qexp; {
pexp->mToken = TK_BINARY_AND; Expression* qexp = new Expression(pthis->mLocation, EX_QUALIFY);
pexp->mDecType = new Declaration(pthis->mLocation, DT_TYPE_POINTER); qexp->mLeft = thisexp;
pexp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; qexp->mDecValue = dec;
pexp->mDecType->mBase = dec->mBase;
pexp->mDecType->mSize = 2;
Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT); Expression* dexp;
cexp->mDecValue = dec->mBase->mDestructor;
cexp->mDecType = cexp->mDecValue->mBase;
Expression* dexp = new Expression(mScanner->mLocation, EX_CALL); if (dec->mSize == bdec->mSize)
dexp->mLeft = cexp; {
dexp->mRight = pexp; 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; Expression* cexp = new Expression(pthis->mLocation, EX_CONSTANT);
sexp->mRight = dexp; 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; dec = dec->mPrev;
@ -2615,62 +3138,116 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
{ {
ParseVariableInit(ndec); 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 // Find default constructor
Declaration* cdec = ndec->mBase->mConstructor; Declaration* bdec = ndec->mBase;
while (cdec && cdec->mBase->mParams->mNext) while (bdec && bdec->mType == DT_TYPE_ARRAY)
cdec = cdec->mNext; bdec = bdec->mBase;
if (cdec) if (bdec && bdec->mConstructor)
{ {
Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE); Declaration* cdec = bdec->mConstructor;
vexp->mDecType = ndec->mBase; while (cdec && cdec->mBase->mParams->mNext)
vexp->mDecValue = ndec; cdec = cdec->mNext;
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); if (cdec)
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)
{ {
Expression* cexp = new Expression(mScanner->mLocation, EX_CONSTANT); Expression* vexp = new Expression(ndec->mLocation, EX_VARIABLE);
cexp->mDecValue = ndec->mBase->mDestructor; vexp->mDecType = ndec->mBase;
cexp->mDecType = cexp->mDecValue->mBase; vexp->mDecValue = ndec;
dexp = new Expression(mScanner->mLocation, EX_CALL); Expression* texp = new Expression(mScanner->mLocation, EX_PREFIX);
dexp->mLeft = cexp; texp->mToken = TK_BINARY_AND;
dexp->mRight = texp; 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;
}
} }
else
Expression* nexp = new Expression(mScanner->mLocation, EX_CONSTRUCT); mErrors->Error(ndec->mLocation, EERR_NO_DEFAULT_CONSTRUCTOR, "No default constructor for class", ndec->mBase->mIdent);
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);
} }
if (storageFlags & DTF_EXPORT) if (storageFlags & DTF_EXPORT)