From 9cdfad7d34a9a2b9a329a2fdc4c5acb615655716 Mon Sep 17 00:00:00 2001 From: drmortalwombat <90205530+drmortalwombat@users.noreply.github.com> Date: Mon, 17 Jul 2023 07:52:59 +0200 Subject: [PATCH] Improve cpp code generation --- include/opp/string.cpp | 17 +++ include/opp/string.h | 3 + oscar64/Declaration.cpp | 25 ++++ oscar64/Declaration.h | 1 + oscar64/GlobalAnalyzer.cpp | 2 +- oscar64/InterCode.cpp | 2 +- oscar64/InterCode.h | 2 +- oscar64/InterCodeGenerator.cpp | 4 + oscar64/NativeCodeGenerator.cpp | 29 +++- oscar64/Parser.cpp | 246 ++++++++++++++++++++++++++++++-- oscar64/Parser.h | 2 + oscar64/Scanner.cpp | 18 ++- oscar64/Scanner.h | 3 + 13 files changed, 331 insertions(+), 23 deletions(-) diff --git a/include/opp/string.cpp b/include/opp/string.cpp index 5c15b2e..4973fda 100644 --- a/include/opp/string.cpp +++ b/include/opp/string.cpp @@ -44,6 +44,18 @@ string::string(const char * s) 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) { cstr = malloc(3); @@ -64,6 +76,11 @@ string::~string(void) free(cstr); } +void string::copyseg(char * p, char at, char num) const +{ + smemcpy(p, cstr + 1 + at, num); +} + string & string::operator=(const string & s) { if (cstr != s.cstr) diff --git a/include/opp/string.h b/include/opp/string.h index b2132f0..747c120 100644 --- a/include/opp/string.h +++ b/include/opp/string.h @@ -10,6 +10,7 @@ public: string(void); string(const string & s); string(const char * s); + string(const char * s, char size); string(char c); ~string(void); @@ -61,6 +62,8 @@ public: int find(const string & s, char pos) const; int find(const char * s, char pos) const; int find(char c, char pos) const; + + void copyseg(char * p, char at, char num) const; protected: string(char l, char * b); }; diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index a8ecab6..21953ac 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -1238,6 +1238,31 @@ bool Declaration::IsSameParams(const Declaration* dec) const 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 { if (this == dec) diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index c13bfc5..89075ca 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -262,6 +262,7 @@ public: bool CanAssign(const Declaration* fromType) const; bool IsSame(const Declaration* dec) const; + bool IsDerivedFrom(const Declaration* dec) const; bool IsSubType(const Declaration* dec) const; bool IsConstSame(const Declaration* dec) const; bool IsSameValue(const Declaration* dec) const; diff --git a/oscar64/GlobalAnalyzer.cpp b/oscar64/GlobalAnalyzer.cpp index 64d3be3..d9d11fe 100644 --- a/oscar64/GlobalAnalyzer.cpp +++ b/oscar64/GlobalAnalyzer.cpp @@ -284,7 +284,7 @@ void GlobalAnalyzer::MarkRecursions(void) 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; int nbase = 0; diff --git a/oscar64/InterCode.cpp b/oscar64/InterCode.cpp index 91ce94e..d1f3d71 100644 --- a/oscar64/InterCode.cpp +++ b/oscar64/InterCode.cpp @@ -15331,7 +15331,7 @@ InterCodeProcedure::InterCodeProcedure(InterCodeModule * mod, const Location & l mNativeProcedure(false), mLeafProcedure(false), mCallsFunctionPointer(false), mCalledFunctions(nullptr), mFastCallProcedure(false), mInterrupt(false), mHardwareInterrupt(false), mCompiled(false), mInterruptCalled(false), mDynamicStack(false), mSaveTempsLinkerObject(nullptr), mValueReturn(false), mFramePointer(false), - mCheckUnreachable(true), + mCheckUnreachable(true), mReturnType(IT_NONE), mDeclaration(nullptr) { mID = mModule->mProcedures.Size(); diff --git a/oscar64/InterCode.h b/oscar64/InterCode.h index b54cee6..d6ff5ea 100644 --- a/oscar64/InterCode.h +++ b/oscar64/InterCode.h @@ -604,7 +604,7 @@ public: LinkerObject * mLinkerObject, * mSaveTempsLinkerObject; Declaration * mDeclaration; - + InterType mReturnType; uint64 mCompilerOptions; InterCodeProcedure(InterCodeModule * module, const Location & location, const Ident * ident, LinkerObject* linkerObject); diff --git a/oscar64/InterCodeGenerator.cpp b/oscar64/InterCodeGenerator.cpp index 6778906..b939d3c 100644 --- a/oscar64/InterCodeGenerator.cpp +++ b/oscar64/InterCodeGenerator.cpp @@ -4591,6 +4591,7 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod proc->mCompilerOptions = mCompilerOptions; + dec->mVarIndex = proc->mID; dec->mLinkerObject = proc->mLinkerObject; proc->mNumLocals = dec->mNumVars; @@ -4632,7 +4633,10 @@ InterCodeProcedure* InterCodeGenerator::TranslateProcedure(InterCodeModule * mod proc->mFastCallBase = BC_REG_FPARAMS_END - BC_REG_FPARAMS; if (dec->mBase->mBase->mType != DT_TYPE_VOID && dec->mBase->mBase->mType != DT_TYPE_STRUCT) + { proc->mValueReturn = true; + proc->mReturnType = InterTypeOf(dec->mBase->mBase); + } InterCodeBasicBlock* entryBlock = new InterCodeBasicBlock(proc); diff --git a/oscar64/NativeCodeGenerator.cpp b/oscar64/NativeCodeGenerator.cpp index 16b1567..c854b74 100644 --- a/oscar64/NativeCodeGenerator.cpp +++ b/oscar64/NativeCodeGenerator.cpp @@ -40370,7 +40370,7 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) { mInterProc = proc; - CheckFunc = !strcmp(mInterProc->mIdent->mString, "test_find"); + CheckFunc = !strcmp(mInterProc->mIdent->mString, "getchar"); int nblocks = proc->mBlocks.Size(); tblocks = new NativeCodeBasicBlock * [nblocks]; @@ -40425,7 +40425,25 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) // 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->mBranch = ASMIT_JMP; @@ -40443,7 +40461,6 @@ void NativeCodeProcedure::Compile(InterCodeProcedure* proc) } #endif #if 1 - if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) if (mExitBlock->mIns[0].mFlags == NCIF_LOWER) { mExitBlock->mIns[0].mFlags = 0; @@ -41021,6 +41038,8 @@ void NativeCodeProcedure::Optimize(void) mEntryBlock->ReplaceFinalZeroPageUse(this); } #endif + + int t = 0; #if 1 do @@ -41029,8 +41048,8 @@ void NativeCodeProcedure::Optimize(void) BuildDataFlowSets(); ResetVisited(); - changed = mEntryBlock->RemoveUnusedResultInstructions(); + changed = mEntryBlock->RemoveUnusedResultInstructions(); if (step == 0) { @@ -41646,8 +41665,10 @@ void NativeCodeProcedure::Optimize(void) else cnt++; + } while (changed); + #if 1 ResetVisited(); mEntryBlock->ReduceLocalYPressure(); diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 99507e2..8edbff8 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -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) { + Declaration* pmdec = FindBaseMemberFunction(dec, mdec); + if (pmdec) + mdec->mBase->mFlags |= pmdec->mBase->mFlags & DTF_VIRTUAL; + Declaration* gdec = mCompilationUnits->mScope->Insert(mdec->mQualIdent, mdec); if (gdec) { @@ -50,6 +94,7 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) dec->mScope->Insert(mdec->mIdent, gdec); if (dec->mConst) dec->mConst->mScope->Insert(mdec->mIdent, gdec); + } else 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; - while (vmdec && vmdec->mBase->IsSame(mdec->mBase)) + while (vmdec && !mdec->mBase->IsDerivedFrom(vmdec->mBase)) { vmpdec = vmdec; vmdec = vmdec->mNext; @@ -3162,6 +3207,48 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex 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); } @@ -3366,6 +3453,46 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex 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; Declaration* ext = ex->mDecType; while (ext && !ext->IsConstSame(ptype->mBase)) + { + ncast++; ext = ext->mBase; + } if (ext) { @@ -4548,12 +4678,19 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) else 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; else if (ptype->mType == DT_TYPE_POINTER && etype->mType == DT_TYPE_FUNCTION && ptype->mBase->IsSame(etype)) dist += 0; else if (ptype->IsSubType(etype)) dist += 256; + else if (ptype->mType == DT_TYPE_REFERENCE && ptype->mBase->IsSame(etype)) + { + if (ex->mType == EX_VARIABLE) + dist += 1; + else + return NOOVERLOAD; + } else return NOOVERLOAD; @@ -4574,6 +4711,41 @@ int Parser::OverloadDistance(Declaration* fdec, Expression* pexp) 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) { if (exp->mType == EX_CALL && exp->mLeft->mDecValue) @@ -4647,7 +4819,7 @@ Expression* Parser::ParsePostfixExpression(bool lhs) nexp->mRight = ParseExpression(false); 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); } @@ -4899,6 +5071,8 @@ Expression* Parser::ParsePrefixExpression(bool lhs) mScanner->NextToken(); nexp = ParsePrefixExpression(false); nexp = nexp->LogicInvertExpression(); + nexp = CheckOperatorOverload(nexp); + } 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); nexp->mToken = mScanner->mToken; - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); - nexp->mRight = ParseBinaryOrExpression(false); + nexp->mRight = CoerceExpression(ParseBinaryOrExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); } @@ -5421,9 +5595,9 @@ Expression* Parser::ParseLogicOrExpression(bool lhs) { Expression* nexp = new Expression(mScanner->mLocation, EX_LOGICAL_OR); nexp->mToken = mScanner->mToken; - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); - nexp->mRight = ParseLogicAndExpression(false); + nexp->mRight = CoerceExpression(ParseLogicAndExpression(false), TheBoolTypeDeclaration); nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); } @@ -5438,7 +5612,7 @@ Expression* Parser::ParseConditionalExpression(bool lhs) if (mScanner->mToken == TK_QUESTIONMARK) { Expression* nexp = new Expression(mScanner->mLocation, EX_CONDITIONAL); - nexp->mLeft = exp; + nexp->mLeft = CoerceExpression(exp, TheBoolTypeDeclaration); mScanner->NextToken(); Expression* texp = new Expression(mScanner->mLocation, EX_SEQUENCE); nexp->mRight = texp; @@ -5578,6 +5752,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) else if (exp->mType == EX_INDEX) { Declaration* tdec = exp->mLeft->mDecType; + while (tdec->mType == DT_TYPE_REFERENCE) + tdec = tdec->mBase; + if (tdec->mType == DT_TYPE_STRUCT) { const Ident* opident = Ident::Unique("operator[]"); @@ -5599,7 +5776,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); @@ -5851,6 +6028,9 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) if (opident) { 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); @@ -5870,7 +6050,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) texp->mLeft = exp->mLeft; texp->mDecType = new Declaration(nexp->mLocation, DT_TYPE_POINTER); texp->mDecType->mFlags |= DTF_CONST | DTF_DEFINED; - texp->mDecType->mBase = exp->mLeft->mDecType; + texp->mDecType->mBase = tdec; texp->mDecType->mSize = 2; 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; @@ -6080,7 +6298,7 @@ Expression* Parser::ParseStatement(void) case TK_IF: mScanner->NextToken(); 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->mLeft = ParseStatement(); if (mScanner->mToken == TK_ELSE) @@ -6099,7 +6317,7 @@ Expression* Parser::ParseStatement(void) mScope = scope; exp = new Expression(mScanner->mLocation, EX_WHILE); - exp->mLeft = CleanupExpression(ParseParenthesisExpression()); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); exp->mRight = ParseStatement(); mScope->End(mScanner->mLocation); @@ -6113,7 +6331,7 @@ Expression* Parser::ParseStatement(void) if (mScanner->mToken == TK_WHILE) { mScanner->NextToken(); - exp->mLeft = CleanupExpression(ParseParenthesisExpression()); + exp->mLeft = CoerceExpression(CleanupExpression(ParseParenthesisExpression()), TheBoolTypeDeclaration); ConsumeToken(TK_SEMICOLON); } else @@ -6147,7 +6365,7 @@ Expression* Parser::ParseStatement(void) // Condition if (mScanner->mToken != TK_SEMICOLON) - conditionExp = CleanupExpression(ParseExpression(false)); + conditionExp = CoerceExpression(CleanupExpression(ParseExpression(false)), TheBoolTypeDeclaration); if (mScanner->mToken == TK_SEMICOLON) mScanner->NextToken(); diff --git a/oscar64/Parser.h b/oscar64/Parser.h index 326787a..66f153c 100644 --- a/oscar64/Parser.h +++ b/oscar64/Parser.h @@ -50,6 +50,7 @@ protected: void ParseVariableInit(Declaration* ndec); void AddMemberFunction(Declaration* dec, Declaration* mdec); + Declaration* FindBaseMemberFunction(Declaration* dec, Declaration* mdec); Expression * AddFunctionCallRefReturned(Expression * exp); Expression* CleanupExpression(Expression* exp); @@ -88,6 +89,7 @@ protected: int OverloadDistance(Declaration* pdec, Expression* pexp); Expression * ResolveOverloadCall(Expression* exp, Expression * exp2 = nullptr); + Expression* CoerceExpression(Expression* exp, Declaration* type); Expression* ParseSimpleExpression(bool lhs); Expression* ParsePrefixExpression(bool lhs); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 06bc2fb..535736b 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -161,6 +161,7 @@ const char* TokenNames[] = "'new'", "'delete'", "'virtual'", + "'operator'", }; @@ -321,6 +322,7 @@ Scanner::Scanner(Errors* errors, Preprocessor* preprocessor) mDefines = new MacroDict(); mDefineArguments = nullptr; mToken = TK_NONE; + mUngetToken = TK_NONE; NextChar(); @@ -873,7 +875,12 @@ void Scanner::NextToken(void) void Scanner::NextRawToken(void) { - if (mToken != TK_EOF) + if (mUngetToken) + { + mToken = mUngetToken; + mUngetToken = TK_NONE; + } + else if (mToken != TK_EOF) { mToken = TK_ERROR; @@ -1480,6 +1487,9 @@ void Scanner::NextRawToken(void) case TK_BINARY_XOR: mTokenIdent = Ident::Unique("operator^"); break; + case TK_LOGICAL_NOT: + mTokenIdent = Ident::Unique("operator!"); + break; case TK_LEFT_SHIFT: mTokenIdent = Ident::Unique("operator<<"); @@ -1522,7 +1532,11 @@ void Scanner::NextRawToken(void) break; 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; diff --git a/oscar64/Scanner.h b/oscar64/Scanner.h index 580ef40..51d8b0a 100644 --- a/oscar64/Scanner.h +++ b/oscar64/Scanner.h @@ -160,6 +160,7 @@ enum Token TK_NEW, TK_DELETE, TK_VIRTUAL, + TK_OPERATOR, NUM_TOKENS }; @@ -260,6 +261,8 @@ protected: MacroDict* mDefines, * mDefineArguments; + Token mUngetToken; + void StringToken(char terminator, char mode); void CharToken(char mode); bool NextChar(void);