diff --git a/include/opp/string.cpp b/include/opp/string.cpp new file mode 100644 index 0000000..9d79206 --- /dev/null +++ b/include/opp/string.cpp @@ -0,0 +1,147 @@ +#include "string.h" +#include +#include + +string::string(void) : cstr(nullptr) +{} + +string::string(const string & s) +{ + cstr = malloc(strlen(s.cstr) + 1); + strcpy(cstr, s.cstr); +} + +string::string(const char * s) +{ + cstr = malloc(strlen(s) + 1); + strcpy(cstr, s); +} + +string::string(const char * s1, const char * s2) +{ + cstr = malloc(strlen(s1) + strlen(s2) + 1); + strcpy(cstr, s1); + strcat(cstr, s2); +} + +string::~string(void) +{ + free(cstr); +} + +string & string::operator=(const string & s) +{ + if (cstr != s.cstr) + { + free(cstr); + cstr = malloc(strlen(s.cstr) + 1); + strcpy(cstr, s.cstr); + } + + return *this; +} + +string & string::operator=(const char * s) +{ + free(cstr); + cstr = malloc(strlen(s) + 1); + strcpy(cstr, s); + + return *this; +} + +string & string::operator+=(const string & s) +{ + char * nstr = malloc(strlen(cstr) + strlen(s.cstr) + 1); + strcpy(nstr, cstr); + strcat(nstr, s.cstr); + free(cstr); + cstr = nstr; + return *this; +} + +string & string::operator+=(const char * s) +{ + char * nstr = malloc(strlen(cstr) + strlen(s) + 1); + strcpy(nstr, cstr); + strcat(nstr, s); + free(cstr); + cstr = nstr; + return *this; +} + +inline const char * string::tocstr(void) const +{ + return cstr; +} + +string string::operator+(const string & s) +{ + return string(cstr, s.cstr); +} + +string string::operator+(const char * s) +{ + return string(cstr, s); +} + + +inline bool string::operator==(const string & s) const +{ + return strcmp(cstr, s.cstr) == 0; +} + +inline bool string::operator==(const char * s) const +{ + return strcmp(cstr, s) == 0; +} + +inline bool string::operator!=(const string & s) const +{ + return strcmp(cstr, s.cstr) != 0; +} + +inline bool string::operator!=(const char * s) const +{ + return strcmp(cstr, s) == 0; +} + +inline bool string::operator<(const string & s) const +{ + return strcmp(cstr, s.cstr) < 0; +} + +inline bool string::operator<(const char * s) const +{ + return strcmp(cstr, s) < 0; +} + +inline bool string::operator<=(const string & s) const +{ + return strcmp(cstr, s.cstr) <= 0; +} + +inline bool string::operator<=(const char * s) const +{ + return strcmp(cstr, s) <= 0; +} + +inline bool string::operator>(const string & s) const +{ + return strcmp(cstr, s.cstr) > 0; +} + +inline bool string::operator>(const char * s) const +{ + return strcmp(cstr, s) > 0; +} + +inline bool string::operator>=(const string & s) const +{ + return strcmp(cstr, s.cstr) >= 0; +} + +inline bool string::operator>=(const char * s) const +{ + return strcmp(cstr, s) >= 0; +} diff --git a/include/opp/string.h b/include/opp/string.h new file mode 100644 index 0000000..a0b4926 --- /dev/null +++ b/include/opp/string.h @@ -0,0 +1,45 @@ +#ifndef OPP_STRING_H +#define OPP_STRING_H + +class string +{ +private: + char * cstr; + +public: + string(void); + string(const string & s); + string(const char * s); + string(const char * s1, const char * s2); + ~string(void); + + string & operator=(const string & s); + string & operator=(const char * s); + + string & operator+=(const string & s); + string & operator+=(const char * s); + + string operator+(const string & s); + string operator+(const char * s); + + bool operator==(const string & s) const; + bool operator==(const char * s) const; + bool operator!=(const string & s) const; + bool operator!=(const char * s) const; + + bool operator<(const string & s) const; + bool operator<(const char * s) const; + bool operator<=(const string & s) const; + bool operator<=(const char * s) const; + + bool operator>(const string & s) const; + bool operator>(const char * s) const; + bool operator>=(const string & s) const; + bool operator>=(const char * s) const; + + const char * tocstr(void) const; +}; + +#pragma compile("string.cpp") + +#endif diff --git a/oscar64/Declaration.cpp b/oscar64/Declaration.cpp index 38b65d7..99b56f6 100644 --- a/oscar64/Declaration.cpp +++ b/oscar64/Declaration.cpp @@ -801,6 +801,15 @@ int Declaration::Stride(void) const return mStride > 0 ? mStride : mBase->mSize; } +Declaration* Declaration::BuildPointer(const Location& loc) +{ + Declaration* pdec = new Declaration(loc, DT_TYPE_POINTER); + pdec->mBase = this; + pdec->mFlags = DTF_DEFINED; + pdec->mSize = 2; + return pdec; +} + Declaration* Declaration::Last(void) { mPrev = nullptr; diff --git a/oscar64/Declaration.h b/oscar64/Declaration.h index 3667799..6c161db 100644 --- a/oscar64/Declaration.h +++ b/oscar64/Declaration.h @@ -262,6 +262,8 @@ public: Declaration* Clone(void); Declaration* Last(void); + Declaration* BuildPointer(const Location& loc); + int Stride(void) const; }; diff --git a/oscar64/Parser.cpp b/oscar64/Parser.cpp index 4f39d9f..5f08de3 100644 --- a/oscar64/Parser.cpp +++ b/oscar64/Parser.cpp @@ -48,6 +48,8 @@ void Parser::AddMemberFunction(Declaration* dec, Declaration* mdec) pcdec->mNext = 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); @@ -2993,7 +2995,10 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Declaration * bthis = new Declaration(mScanner->mLocation, DT_TYPE_POINTER); bthis->mFlags |= DTF_CONST | DTF_DEFINED; - bthis->mBase = bdec; + if (ConsumeTokenIf(TK_CONST)) + bthis->mBase = bdec->ToConstType(); + else + bthis->mBase = bdec; bthis->mSize = 2; PrependThisArgument(ctdec, bthis); @@ -3127,10 +3132,11 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex else { if (ndec->mBase->mType == DT_TYPE_FUNCTION && pthis) - { - - PrependThisArgument(ndec->mBase, pthis); - + { + if (ConsumeTokenIf(TK_CONST)) + PrependThisArgument(ndec->mBase, pthis->mBase->ToConstType()->BuildPointer(ndec->mLocation)); + else + PrependThisArgument(ndec->mBase, pthis); } if (variable) @@ -3180,6 +3186,9 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex Declaration* adec = pdec->mBase->mParams->Clone(); adec->mNext = ndec->mBase->mParams; + if (ConsumeTokenIf(TK_CONST)) + adec->mBase = adec->mBase->mBase->ToConstType()->BuildPointer(adec->mLocation); + Declaration* p = adec->mBase->mParams; while (p) { @@ -3230,6 +3239,8 @@ Declaration* Parser::ParseDeclaration(Declaration * pdec, bool variable, bool ex } } + pdec->mFlags |= ndec->mFlags & DTF_REQUEST_INLINE; + ndec = pdec; } } @@ -4603,6 +4614,8 @@ Expression* Parser::ParseShiftExpression(bool lhs) nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4622,6 +4635,8 @@ Expression* Parser::ParseRelationalExpression(bool lhs) nexp->mDecType = TheBoolTypeDeclaration; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4641,6 +4656,8 @@ Expression* Parser::ParseBinaryAndExpression(bool lhs) nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4659,6 +4676,8 @@ Expression* Parser::ParseBinaryXorExpression(bool lhs) nexp->mRight = ParseBinaryAndExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4677,6 +4696,8 @@ Expression* Parser::ParseBinaryOrExpression(bool lhs) nexp->mRight = ParseBinaryXorExpression(false); nexp->mDecType = exp->mDecType; exp = nexp->ConstantFold(mErrors); + + exp = CheckOperatorOverload(exp); } return exp; @@ -4772,9 +4793,47 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) Declaration* tdec = exp->mLeft->mDecType; if (tdec->mType == DT_TYPE_STRUCT) { - if (exp->mToken == TK_ASSIGN) + const Ident* opident = nullptr; + switch (exp->mToken) { - Declaration* mdec = tdec->mScope->Lookup(Ident::Unique("operator=")); + case TK_ASSIGN: + opident = Ident::Unique("operator="); + break; + case TK_ASSIGN_ADD: + opident = Ident::Unique("operator+="); + break; + case TK_ASSIGN_SUB: + opident = Ident::Unique("operator-="); + break; + case TK_ASSIGN_MUL: + opident = Ident::Unique("operator*="); + break; + case TK_ASSIGN_DIV: + opident = Ident::Unique("operator/="); + break; + case TK_ASSIGN_MOD: + opident = Ident::Unique("operator%="); + break; + case TK_ASSIGN_SHL: + opident = Ident::Unique("operator<<="); + break; + case TK_ASSIGN_SHR: + opident = Ident::Unique("operator>>="); + break; + case TK_ASSIGN_AND: + opident = Ident::Unique("operator&="); + break; + case TK_ASSIGN_XOR: + opident = Ident::Unique("operator^="); + break; + case TK_ASSIGN_OR: + opident = Ident::Unique("operator|="); + break; + } + + if (opident) + { + Declaration* mdec = tdec->mScope->Lookup(opident); if (mdec) { Expression * nexp = new Expression(mScanner->mLocation, EX_CALL); @@ -4807,7 +4866,7 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) } } } - else if (exp->mType == EX_BINARY) + else if (exp->mType == EX_BINARY || exp->mType == EX_RELATIONAL) { const Ident* opident = nullptr; switch (exp->mToken) @@ -4816,17 +4875,50 @@ Expression* Parser::CheckOperatorOverload(Expression* exp) opident = Ident::Unique("operator+"); break; case TK_SUB: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator-"); break; case TK_MUL: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator*"); break; case TK_DIV: - opident = Ident::Unique("operator+"); + opident = Ident::Unique("operator/"); break; case TK_MOD: opident = Ident::Unique("operator%"); break; + case TK_BINARY_AND: + opident = Ident::Unique("operator&"); + break; + case TK_BINARY_OR: + opident = Ident::Unique("operator|"); + break; + case TK_BINARY_XOR: + opident = Ident::Unique("operator^"); + break; + case TK_LEFT_SHIFT: + opident = Ident::Unique("operator<<"); + break; + case TK_RIGHT_SHIFT: + opident = Ident::Unique("operator>>"); + break; + case TK_EQUAL: + opident = Ident::Unique("operator=="); + break; + case TK_NOT_EQUAL: + opident = Ident::Unique("operator!="); + break; + case TK_GREATER_THAN: + opident = Ident::Unique("operator>"); + break; + case TK_GREATER_EQUAL: + opident = Ident::Unique("operator>="); + break; + case TK_LESS_THAN: + opident = Ident::Unique("operator<"); + break; + case TK_LESS_EQUAL: + opident = Ident::Unique("operator<="); + break; } if (opident) @@ -4851,7 +4943,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->mDecType; + texp->mDecType->mBase = exp->mLeft->mDecType; texp->mDecType->mSize = 2; Expression* lexp = new Expression(nexp->mLocation, EX_LIST); diff --git a/oscar64/Scanner.cpp b/oscar64/Scanner.cpp index 535e6f3..1a5e293 100644 --- a/oscar64/Scanner.cpp +++ b/oscar64/Scanner.cpp @@ -1415,6 +1415,37 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator="); break; + case TK_ASSIGN_ADD: + mTokenIdent = Ident::Unique("operator+="); + break; + case TK_ASSIGN_SUB: + mTokenIdent = Ident::Unique("operator-="); + break; + case TK_ASSIGN_MUL: + mTokenIdent = Ident::Unique("operator*="); + break; + case TK_ASSIGN_DIV: + mTokenIdent = Ident::Unique("operator/="); + break; + case TK_ASSIGN_MOD: + mTokenIdent = Ident::Unique("operator%="); + break; + case TK_ASSIGN_SHL: + mTokenIdent = Ident::Unique("operator<<="); + break; + case TK_ASSIGN_SHR: + mTokenIdent = Ident::Unique("operator>>="); + break; + case TK_ASSIGN_AND: + mTokenIdent = Ident::Unique("operator&="); + break; + case TK_ASSIGN_XOR: + mTokenIdent = Ident::Unique("operator^="); + break; + case TK_ASSIGN_OR: + mTokenIdent = Ident::Unique("operator|="); + break; + case TK_ADD: mTokenIdent = Ident::Unique("operator+"); break; @@ -1431,6 +1462,42 @@ void Scanner::NextRawToken(void) mTokenIdent = Ident::Unique("operator%"); break; + case TK_BINARY_AND: + mTokenIdent = Ident::Unique("operator&"); + break; + case TK_BINARY_OR: + mTokenIdent = Ident::Unique("operator|"); + break; + case TK_BINARY_XOR: + mTokenIdent = Ident::Unique("operator^"); + break; + + case TK_LEFT_SHIFT: + mTokenIdent = Ident::Unique("operator<<"); + break; + case TK_RIGHT_SHIFT: + mTokenIdent = Ident::Unique("operator>>"); + break; + + case TK_EQUAL: + mTokenIdent = Ident::Unique("operator=="); + break; + case TK_NOT_EQUAL: + mTokenIdent = Ident::Unique("operator!="); + break; + case TK_GREATER_THAN: + mTokenIdent = Ident::Unique("operator>"); + break; + case TK_GREATER_EQUAL: + mTokenIdent = Ident::Unique("operator>="); + break; + case TK_LESS_THAN: + mTokenIdent = Ident::Unique("operator<"); + break; + case TK_LESS_EQUAL: + mTokenIdent = Ident::Unique("operator<="); + break; + default: mErrors->Error(mLocation, EERR_INVALID_OPERATOR, "Invalid operator token"); }