Improve cpp code generation

This commit is contained in:
drmortalwombat 2023-07-17 07:52:59 +02:00
parent 18c21b3fda
commit 9cdfad7d34
13 changed files with 331 additions and 23 deletions

View File

@ -44,6 +44,18 @@ string::string(const char * s)
cstr = nullptr; cstr = nullptr;
} }
string::string(const char * s, char size)
{
if (size)
{
cstr = malloc(char(size + 2));
cstr[0] = size;
smemcpy(cstr + 1, s, size + 1);
}
else
cstr = nullptr;
}
string::string(char c) string::string(char c)
{ {
cstr = malloc(3); cstr = malloc(3);
@ -64,6 +76,11 @@ string::~string(void)
free(cstr); free(cstr);
} }
void string::copyseg(char * p, char at, char num) const
{
smemcpy(p, cstr + 1 + at, num);
}
string & string::operator=(const string & s) string & string::operator=(const string & s)
{ {
if (cstr != s.cstr) if (cstr != s.cstr)

View File

@ -10,6 +10,7 @@ public:
string(void); string(void);
string(const string & s); string(const string & s);
string(const char * s); string(const char * s);
string(const char * s, char size);
string(char c); string(char c);
~string(void); ~string(void);
@ -61,6 +62,8 @@ public:
int find(const string & s, char pos) const; int find(const string & s, char pos) const;
int find(const char * s, char pos) const; int find(const char * s, char pos) const;
int find(char c, char pos) const; int find(char c, char pos) const;
void copyseg(char * p, char at, char num) const;
protected: protected:
string(char l, char * b); string(char l, char * b);
}; };

View File

@ -1238,6 +1238,31 @@ bool Declaration::IsSameParams(const Declaration* dec) const
return false; return false;
} }
bool Declaration::IsDerivedFrom(const Declaration* dec) const
{
if (mType != DT_TYPE_FUNCTION || dec->mType != DT_TYPE_FUNCTION)
return false;
if (!(mFlags & DTF_FUNC_THIS) || !(dec->mFlags & DTF_FUNC_THIS))
return false;
if (!mBase->IsSame(dec->mBase))
return false;
Declaration* dl = mParams->mNext, * dr = dec->mParams->mNext;
while (dl && dr)
{
if (!dl->mBase->IsSame(dr->mBase))
return false;
dl = dl->mNext;
dr = dr->mNext;
}
if (dl || dr)
return false;
return true;
}
bool Declaration::IsSame(const Declaration* dec) const bool Declaration::IsSame(const Declaration* dec) const
{ {
if (this == dec) if (this == dec)

View File

@ -262,6 +262,7 @@ public:
bool CanAssign(const Declaration* fromType) const; bool CanAssign(const Declaration* fromType) const;
bool IsSame(const Declaration* dec) const; bool IsSame(const Declaration* dec) const;
bool IsDerivedFrom(const Declaration* dec) const;
bool IsSubType(const Declaration* dec) const; bool IsSubType(const Declaration* dec) const;
bool IsConstSame(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const;
bool IsSameValue(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const;

View File

@ -284,7 +284,7 @@ void GlobalAnalyzer::MarkRecursions(void)
void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head) void GlobalAnalyzer::CheckFastcall(Declaration* procDec, bool head)
{ {
if (!(procDec->mBase->mFlags & DTF_FASTCALL) && !(procDec->mBase->mFlags & DTF_STACKCALL) && (procDec->mType == DT_CONST_FUNCTION) && !(procDec->mFlags & DTF_FUNC_ANALYZING)) if (!(procDec->mBase->mFlags & DTF_FASTCALL) && (procDec->mType == DT_CONST_FUNCTION) && !(procDec->mFlags & DTF_FUNC_ANALYZING))
{ {
procDec->mFlags |= DTF_FUNC_ANALYZING; procDec->mFlags |= DTF_FUNC_ANALYZING;
int nbase = 0; int nbase = 0;

View File

@ -15331,7 +15331,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l
mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false),
mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false),
mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false),
mCheckUnreachable(true), mCheckUnreachable(true), mReturnType(IT_NONE),
mDeclaration(nullptr) mDeclaration(nullptr)
{ {
mID = mModule->mProcedures.Size(); mID = mModule->mProcedures.Size();

View File

@ -604,7 +604,7 @@ public:
LinkerObject * mLinkerObject, * mSaveTempsLinkerObject; LinkerObject * mLinkerObject, * mSaveTempsLinkerObject;
Declaration * mDeclaration; Declaration * mDeclaration;
InterType mReturnType;
uint64 mCompilerOptions; uint64 mCompilerOptions;
InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject);

View File

@ -4591,6 +4591,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
proc->mCompilerOptions = mCompilerOptions; proc->mCompilerOptions = mCompilerOptions;
dec->mVarIndex = proc->mID; dec->mVarIndex = proc->mID;
dec->mLinkerObject = proc->mLinkerObject; dec->mLinkerObject = proc->mLinkerObject;
proc->mNumLocals = dec->mNumVars; proc->mNumLocals = dec->mNumVars;
@ -4632,7 +4633,10 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod
proc->mFastCallBase = BC_REG_FPARAMS_END - BC_REG_FPARAMS; proc->mFastCallBase = BC_REG_FPARAMS_END - BC_REG_FPARAMS;
if (dec->mBase->mBase->mType != DT_TYPE_VOID && dec->mBase->mBase->mType != DT_TYPE_STRUCT) if (dec->mBase->mBase->mType != DT_TYPE_VOID && dec->mBase->mBase->mType != DT_TYPE_STRUCT)
{
proc->mValueReturn = true; proc->mValueReturn = true;
proc->mReturnType = InterTypeOf(dec->mBase->mBase);
}
InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(proc); InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(proc);

View File

@ -40370,7 +40370,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
{ {
mInterProc = proc; mInterProc = proc;
CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_find"); CheckFunc = !strcmp(mInterProc->mIdent->mString, "getchar");
int nblocks = proc->mBlocks.Size(); int nblocks = proc->mBlocks.Size();
tblocks = new NativeCodeBasicBlock * [nblocks]; tblocks = new NativeCodeBasicBlock * [nblocks];
@ -40425,7 +40425,25 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
// Place a temporary RTS // Place a temporary RTS
mExitBlock->mIns.Push(NativeCodeInstruction(nullptr, ASMIT_RTS, ASMIM_IMPLIED, 0, nullptr, 0)); uint32 rflags = 0;
switch (proc->mReturnType)
{
case IT_BOOL:
case IT_INT8:
rflags = NCIF_LOWER;
break;
case IT_INT16:
case IT_POINTER:
rflags = NCIF_LOWER | NCIF_UPPER;
break;
case IT_INT32:
case IT_FLOAT:
rflags = NCIF_LOWER | NCIF_UPPER | NCIF_LONG;
break;
}
mExitBlock->mIns.Push(NativeCodeInstruction(nullptr, ASMIT_RTS, ASMIM_IMPLIED, 0, nullptr, rflags));
mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]); mEntryBlock->mTrueJump = CompileBlock(mInterProc, mInterProc->mBlocks[0]);
mEntryBlock->mBranch = ASMIT_JMP; mEntryBlock->mBranch = ASMIT_JMP;
@ -40443,7 +40461,6 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc)
} }
#endif #endif
#if 1 #if 1
if (mExitBlock->mIns[0].mFlags == NCIF_LOWER)
if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) if (mExitBlock->mIns[0].mFlags == NCIF_LOWER)
{ {
mExitBlock->mIns[0].mFlags = 0; mExitBlock->mIns[0].mFlags = 0;
@ -41021,6 +41038,8 @@ void NativeCodeProcedure::Optimize(void)
mEntryBlock->ReplaceFinalZeroPageUse(this); mEntryBlock->ReplaceFinalZeroPageUse(this);
} }
#endif #endif
int t = 0; int t = 0;
#if 1 #if 1
do do
@ -41029,8 +41048,8 @@ void NativeCodeProcedure::Optimize(void)
BuildDataFlowSets(); BuildDataFlowSets();
ResetVisited(); ResetVisited();
changed = mEntryBlock->RemoveUnusedResultInstructions();
changed = mEntryBlock->RemoveUnusedResultInstructions();
if (step == 0) if (step == 0)
{ {
@ -41646,8 +41665,10 @@ void NativeCodeProcedure::Optimize(void)
else else
cnt++; cnt++;
} while (changed); } while (changed);
#if 1 #if 1
ResetVisited(); ResetVisited();
mEntryBlock->ReduceLocalYPressure(); mEntryBlock->ReduceLocalYPressure();

View File

@ -28,8 +28,52 @@ Parser::~Parser(void)
} }
Declaration* Parser::FindBaseMemberFunction(Declaration* dec, Declaration* mdec)
{
const Ident* ident = mdec->mIdent;
if (ident->mString[0] == '~')
{
// this is the destructor, need special search
Declaration * pdec = dec;
Declaration * pmdec = nullptr;
while (pdec->mBase && !pmdec)
{
pdec = pdec->mBase->mBase;
pmdec = pdec->mScope->Lookup(pdec->mIdent->PreMangle("~"));
}
return pmdec;
}
else
{
Declaration * pdec = dec;
Declaration * pmdec = nullptr;
while (pdec->mBase && !pmdec)
{
pdec = pdec->mBase->mBase;
pmdec = pdec->mScope->Lookup(ident);
while (pmdec && !mdec->mBase->IsDerivedFrom(pmdec->mBase))
pmdec = pmdec->mNext;
if (pmdec)
return pmdec;
}
return pmdec;
}
}
void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec)
{ {
Declaration* pmdec = FindBaseMemberFunction(dec, mdec);
if (pmdec)
mdec->mBase->mFlags |= pmdec->mBase->mFlags & DTF_VIRTUAL;
Declaration* gdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec); Declaration* gdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec);
if (gdec) if (gdec)
{ {
@ -50,6 +94,7 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec)
dec->mScope->Insert(mdec->mIdent, gdec); dec->mScope->Insert(mdec->mIdent, gdec);
if (dec->mConst) if (dec->mConst)
dec->mConst->mScope->Insert(mdec->mIdent, gdec); dec->mConst->mScope->Insert(mdec->mIdent, gdec);
} }
else else
mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent); mErrors->Error(mdec->mLocation, EERR_DUPLICATE_DEFINITION, "Duplicate struct member declaration", mdec->mIdent);
@ -341,7 +386,7 @@ Declaration* Parser::ParseStructDeclaration(uint64 flags, DecType dt)
Declaration* vmpdec = nullptr; Declaration* vmpdec = nullptr;
while (vmdec && vmdec->mBase->IsSame(mdec->mBase)) while (vmdec && !mdec->mBase->IsDerivedFrom(vmdec->mBase))
{ {
vmpdec = vmdec; vmpdec = vmdec;
vmdec = vmdec->mNext; vmdec = vmdec->mNext;
@ -3162,6 +3207,48 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
return cdec; return cdec;
} }
if ((mCompilerOptions & COPT_CPLUSPLUS) && pthis && mScanner->mToken == TK_OPERATOR)
{
mScanner->NextToken();
bdec = ParseBaseTypeDeclaration(typeFlags, false);
Declaration* ctdec = ParseFunctionDeclaration(bdec);
if (ctdec->mParams)
mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter");
PrependThisArgument(ctdec, pthis);
Declaration* cdec = new Declaration(ctdec->mLocation, DT_CONST_FUNCTION);
cdec->mBase = ctdec;
cdec->mFlags |= cdec->mBase->mFlags & (DTF_CONST | DTF_VOLATILE);
ctdec->mFlags |= storageFlags & DTF_VIRTUAL;
cdec->mSection = mCodeSection;
cdec->mBase->mFlags |= typeFlags;
if (mCompilerOptions & COPT_NATIVE)
cdec->mFlags |= DTF_NATIVE;
cdec->mIdent = Ident::Unique("(cast)");
cdec->mQualIdent = pthis->mBase->mScope->Mangle(cdec->mIdent);
if (mScanner->mToken == TK_OPEN_BRACE)
{
cdec->mCompilerOptions = mCompilerOptions;
cdec->mBase->mCompilerOptions = mCompilerOptions;
cdec->mVarIndex = -1;
cdec->mValue = ParseFunction(cdec->mBase);
cdec->mFlags |= DTF_DEFINED | DTF_REQUEST_INLINE;
cdec->mNumVars = mLocalIndex;
}
return cdec;
}
bdec = ParseBaseTypeDeclaration(typeFlags, false); bdec = ParseBaseTypeDeclaration(typeFlags, false);
} }
@ -3366,6 +3453,46 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex
return bdec->mDestructor; return bdec->mDestructor;
} }
else if (ConsumeTokenIf(TK_OPERATOR))
{
Declaration* tdec = ParseBaseTypeDeclaration(0, true);
Declaration* ctdec = ParseFunctionDeclaration(tdec);
if (ctdec->mParams)
mErrors->Error(ctdec->mLocation, EERR_WRONG_PARAMETER, "Cast operators can't have parameter");
Declaration* bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER);
bthis->mFlags |= DTF_CONST | DTF_DEFINED;
if (ConsumeTokenIf(TK_CONST))
bthis->mBase = bdec->ToConstType();
else
bthis->mBase = bdec;
bthis->mSize = 2;
PrependThisArgument(ctdec, bthis);
Declaration* fdec = bdec->mScope->Lookup(Ident::Unique("(cast)"));
while (fdec && !fdec->mBase->IsSame(ctdec))
fdec = fdec->mNext;
if (fdec)
{
fdec->mCompilerOptions = mCompilerOptions;
fdec->mBase->mCompilerOptions = mCompilerOptions;
fdec->mVarIndex = -1;
fdec->mValue = ParseFunction(fdec->mBase);
fdec->mFlags |= DTF_DEFINED;
fdec->mNumVars = mLocalIndex;
}
else
mErrors->Error(ctdec->mLocation, EERR_DUPLICATE_DEFINITION, "Cast operator not declared", tdec->mIdent);
return fdec;
}
} }
} }
@ -4536,7 +4663,10 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
int ncast = 0; int ncast = 0;
Declaration* ext = ex->mDecType; Declaration* ext = ex->mDecType;
while (ext && !ext->IsConstSame(ptype->mBase)) while (ext && !ext->IsConstSame(ptype->mBase))
{
ncast++;
ext = ext->mBase; ext = ext->mBase;
}
if (ext) if (ext)
{ {
@ -4548,12 +4678,19 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
else else
return NOOVERLOAD; return NOOVERLOAD;
} }
else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_ARRAY && ptype->mBase->IsSameMutable(etype->mBase)) else if (ptype->mType == DT_TYPE_POINTER && (etype->mType == DT_TYPE_ARRAY || etype->mType == DT_TYPE_POINTER) && ptype->mBase->IsSameMutable(etype->mBase))
dist += 1; dist += 1;
else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype))
dist += 0; dist += 0;
else if (ptype->IsSubType(etype)) else if (ptype->IsSubType(etype))
dist += 256; dist += 256;
else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype))
{
if (ex->mType == EX_VARIABLE)
dist += 1;
else
return NOOVERLOAD;
}
else else
return NOOVERLOAD; return NOOVERLOAD;
@ -4574,6 +4711,41 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp)
return dist; return dist;
} }
Expression* Parser::CoerceExpression(Expression* exp, Declaration* type)
{
Declaration* tdec = exp->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* fexp = tdec->mScope->Lookup(Ident::Unique("(cast)"));
if (fexp)
{
while (fexp && !fexp->mBase->mBase->IsSame(type))
fexp = fexp->mNext;
if (fexp)
{
Expression* aexp = new Expression(exp->mLocation, EX_PREFIX);
aexp->mToken = TK_BINARY_AND;
aexp->mDecType = tdec->BuildPointer(exp->mLocation);
aexp->mLeft = exp;
Expression* nexp = new Expression(exp->mLocation, EX_CALL);
nexp->mLeft = new Expression(exp->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = fexp->mBase;
nexp->mLeft->mDecValue = fexp;
nexp->mRight = aexp;
return nexp;
}
}
}
return exp;
}
Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2) Expression * Parser::ResolveOverloadCall(Expression* exp, Expression* exp2)
{ {
if (exp->mType == EX_CALL && exp->mLeft->mDecValue) if (exp->mType == EX_CALL && exp->mLeft->mDecValue)
@ -4647,7 +4819,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs)
nexp->mRight = ParseExpression(false); nexp->mRight = ParseExpression(false);
ConsumeToken(TK_CLOSE_BRACKET); ConsumeToken(TK_CLOSE_BRACKET);
if (exp->mDecType->mType == DT_TYPE_STRUCT) if (exp->mDecType->mType == DT_TYPE_STRUCT || exp->mDecType->mType == DT_TYPE_REFERENCE && exp->mDecType->mBase->mType == DT_TYPE_STRUCT)
{ {
nexp = CheckOperatorOverload(nexp); nexp = CheckOperatorOverload(nexp);
} }
@ -4899,6 +5071,8 @@ Expression* Parser::ParsePrefixExpression(bool lhs)
mScanner->NextToken(); mScanner->NextToken();
nexp = ParsePrefixExpression(false); nexp = ParsePrefixExpression(false);
nexp = nexp->LogicInvertExpression(); nexp = nexp->LogicInvertExpression();
nexp = CheckOperatorOverload(nexp);
} }
else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC) else if (mScanner->mToken == TK_INC || mScanner->mToken == TK_DEC)
{ {
@ -5403,9 +5577,9 @@ Expression* Parser::ParseLogicAndExpression(bool lhs)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_AND); Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_AND);
nexp->mToken = mScanner->mToken; nexp->mToken = mScanner->mToken;
nexp->mLeft = exp; nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration);
mScanner->NextToken(); mScanner->NextToken();
nexp->mRight = ParseBinaryOrExpression(false); nexp->mRight = CoerceExpression(ParseBinaryOrExpression(false), TheBoolTypeDeclaration);
nexp->mDecType = TheBoolTypeDeclaration; nexp->mDecType = TheBoolTypeDeclaration;
exp = nexp->ConstantFold(mErrors); exp = nexp->ConstantFold(mErrors);
} }
@ -5421,9 +5595,9 @@ Expression* Parser::ParseLogicOrExpression(bool lhs)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_OR); Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_OR);
nexp->mToken = mScanner->mToken; nexp->mToken = mScanner->mToken;
nexp->mLeft = exp; nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration);
mScanner->NextToken(); mScanner->NextToken();
nexp->mRight = ParseLogicAndExpression(false); nexp->mRight = CoerceExpression(ParseLogicAndExpression(false), TheBoolTypeDeclaration);
nexp->mDecType = TheBoolTypeDeclaration; nexp->mDecType = TheBoolTypeDeclaration;
exp = nexp->ConstantFold(mErrors); exp = nexp->ConstantFold(mErrors);
} }
@ -5438,7 +5612,7 @@ Expression* Parser::ParseConditionalExpression(bool lhs)
if (mScanner->mToken == TK_QUESTIONMARK) if (mScanner->mToken == TK_QUESTIONMARK)
{ {
Expression* nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); Expression* nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL);
nexp->mLeft = exp; nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration);
mScanner->NextToken(); mScanner->NextToken();
Expression* texp = new Expression(mScanner->mLocation, EX_SEQUENCE); Expression* texp = new Expression(mScanner->mLocation, EX_SEQUENCE);
nexp->mRight = texp; nexp->mRight = texp;
@ -5578,6 +5752,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
else if (exp->mType == EX_INDEX) else if (exp->mType == EX_INDEX)
{ {
Declaration* tdec = exp->mLeft->mDecType; Declaration* tdec = exp->mLeft->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
{ {
const Ident* opident = Ident::Unique("operator[]"); const Ident* opident = Ident::Unique("operator[]");
@ -5599,7 +5776,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
texp->mLeft = exp->mLeft; texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mBase = tdec;
texp->mDecType->mSize = 2; texp->mDecType->mSize = 2;
Expression* lexp = new Expression(nexp->mLocation, EX_LIST); Expression* lexp = new Expression(nexp->mLocation, EX_LIST);
@ -5851,6 +6028,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
if (opident) if (opident)
{ {
Declaration* tdec = exp->mLeft->mDecType; Declaration* tdec = exp->mLeft->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT) if (tdec->mType == DT_TYPE_STRUCT)
{ {
Declaration* mdec = tdec->mScope->Lookup(opident); Declaration* mdec = tdec->mScope->Lookup(opident);
@ -5870,7 +6050,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
texp->mLeft = exp->mLeft; texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mBase = tdec;
texp->mDecType->mSize = 2; texp->mDecType->mSize = 2;
nexp->mRight = texp; nexp->mRight = texp;
@ -5883,6 +6063,44 @@ Expression* Parser::CheckOperatorOverload(Expression* exp)
} }
} }
} }
else if (exp->mType == EX_LOGICAL_NOT)
{
const Ident* opident = Ident::Unique("operator!");
Declaration* tdec = exp->mLeft->mDecType;
while (tdec->mType == DT_TYPE_REFERENCE)
tdec = tdec->mBase;
if (tdec->mType == DT_TYPE_STRUCT)
{
Declaration* mdec = tdec->mScope->Lookup(opident);
if (mdec)
{
Expression* nexp = new Expression(mScanner->mLocation, EX_CALL);
nexp->mLeft = new Expression(mScanner->mLocation, EX_CONSTANT);
nexp->mLeft->mDecType = mdec->mBase;
nexp->mLeft->mDecValue = mdec;
nexp->mDecType = mdec->mBase;
nexp->mRight = exp->mRight;
Expression* texp = new Expression(nexp->mLocation, EX_PREFIX);
texp->mToken = TK_BINARY_AND;
texp->mLeft = exp->mLeft;
texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER);
texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED;
texp->mDecType->mBase = tdec;
texp->mDecType->mSize = 2;
nexp->mRight = texp;
nexp = ResolveOverloadCall(nexp);
nexp->mDecType = nexp->mLeft->mDecType->mBase;
exp = nexp;
}
}
}
} }
return exp; return exp;
@ -6080,7 +6298,7 @@ Expression* Parser::ParseStatement(void)
case TK_IF: case TK_IF:
mScanner->NextToken(); mScanner->NextToken();
exp = new Expression(mScanner->mLocation, EX_IF); exp = new Expression(mScanner->mLocation, EX_IF);
exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration);
exp->mRight = new Expression(mScanner->mLocation, EX_ELSE); exp->mRight = new Expression(mScanner->mLocation, EX_ELSE);
exp->mRight->mLeft = ParseStatement(); exp->mRight->mLeft = ParseStatement();
if (mScanner->mToken == TK_ELSE) if (mScanner->mToken == TK_ELSE)
@ -6099,7 +6317,7 @@ Expression* Parser::ParseStatement(void)
mScope = scope; mScope = scope;
exp = new Expression(mScanner->mLocation, EX_WHILE); exp = new Expression(mScanner->mLocation, EX_WHILE);
exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration);
exp->mRight = ParseStatement(); exp->mRight = ParseStatement();
mScope->End(mScanner->mLocation); mScope->End(mScanner->mLocation);
@ -6113,7 +6331,7 @@ Expression* Parser::ParseStatement(void)
if (mScanner->mToken == TK_WHILE) if (mScanner->mToken == TK_WHILE)
{ {
mScanner->NextToken(); mScanner->NextToken();
exp->mLeft = CleanupExpression(ParseParenthesisExpression()); exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration);
ConsumeToken(TK_SEMICOLON); ConsumeToken(TK_SEMICOLON);
} }
else else
@ -6147,7 +6365,7 @@ Expression* Parser::ParseStatement(void)
// Condition // Condition
if (mScanner->mToken != TK_SEMICOLON) if (mScanner->mToken != TK_SEMICOLON)
conditionExp = CleanupExpression(ParseExpression(false)); conditionExp = CoerceExpression(CleanupExpression(ParseExpression(false)), TheBoolTypeDeclaration);
if (mScanner->mToken == TK_SEMICOLON) if (mScanner->mToken == TK_SEMICOLON)
mScanner->NextToken(); mScanner->NextToken();

View File

@ -50,6 +50,7 @@ protected:
void ParseVariableInit(Declaration* ndec); void ParseVariableInit(Declaration* ndec);
void AddMemberFunction(Declaration* dec, Declaration* mdec); void AddMemberFunction(Declaration* dec, Declaration* mdec);
Declaration* FindBaseMemberFunction(Declaration* dec, Declaration* mdec);
Expression * AddFunctionCallRefReturned(Expression * exp); Expression * AddFunctionCallRefReturned(Expression * exp);
Expression* CleanupExpression(Expression* exp); Expression* CleanupExpression(Expression* exp);
@ -88,6 +89,7 @@ protected:
int OverloadDistance(Declaration* pdec, Expression* pexp); int OverloadDistance(Declaration* pdec, Expression* pexp);
Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr);
Expression* CoerceExpression(Expression* exp, Declaration* type);
Expression* ParseSimpleExpression(bool lhs); Expression* ParseSimpleExpression(bool lhs);
Expression* ParsePrefixExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs);

View File

@ -161,6 +161,7 @@ const char* TokenNames[] =
"'new'", "'new'",
"'delete'", "'delete'",
"'virtual'", "'virtual'",
"'operator'",
}; };
@ -321,6 +322,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor)
mDefines = new MacroDict(); mDefines = new MacroDict();
mDefineArguments = nullptr; mDefineArguments = nullptr;
mToken = TK_NONE; mToken = TK_NONE;
mUngetToken = TK_NONE;
NextChar(); NextChar();
@ -873,7 +875,12 @@ void Scanner::NextToken(void)
void Scanner::NextRawToken(void) void Scanner::NextRawToken(void)
{ {
if (mToken != TK_EOF) if (mUngetToken)
{
mToken = mUngetToken;
mUngetToken = TK_NONE;
}
else if (mToken != TK_EOF)
{ {
mToken = TK_ERROR; mToken = TK_ERROR;
@ -1480,6 +1487,9 @@ void Scanner::NextRawToken(void)
case TK_BINARY_XOR: case TK_BINARY_XOR:
mTokenIdent = Ident::Unique("operator^"); mTokenIdent = Ident::Unique("operator^");
break; break;
case TK_LOGICAL_NOT:
mTokenIdent = Ident::Unique("operator!");
break;
case TK_LEFT_SHIFT: case TK_LEFT_SHIFT:
mTokenIdent = Ident::Unique("operator<<"); mTokenIdent = Ident::Unique("operator<<");
@ -1522,7 +1532,11 @@ void Scanner::NextRawToken(void)
break; break;
default: default:
mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); // dirty little hack to implement token preview, got to fix
// this with an infinit preview sequence at one point
mUngetToken = mToken;
mToken = TK_OPERATOR;
return;
} }
mToken = TK_IDENT; mToken = TK_IDENT;

View File

@ -160,6 +160,7 @@ enum Token
TK_NEW, TK_NEW,
TK_DELETE, TK_DELETE,
TK_VIRTUAL, TK_VIRTUAL,
TK_OPERATOR,
NUM_TOKENS NUM_TOKENS
}; };
@ -260,6 +261,8 @@ protected:
MacroDict* mDefines, * mDefineArguments; MacroDict* mDefines, * mDefineArguments;
Token mUngetToken;
void StringToken(char terminator, char mode); void StringToken(char terminator, char mode);
void CharToken(char mode); void CharToken(char mode);
bool NextChar(void); bool NextChar(void);