diff --git a/uppsrc/CppBase/Body.cpp b/uppsrc/CppBase/Body.cpp new file mode 100644 index 000000000..081d91256 --- /dev/null +++ b/uppsrc/CppBase/Body.cpp @@ -0,0 +1,211 @@ +#include "CppBase.h" + +NAMESPACE_UPP + +bool Parser::TryDecl() +{ // attempt to interpret code as local variable declaration + for(;;) { + if(lex[0] == tk_static || lex[0] == tk_const || + lex[0] == tk_register || lex[0] == tk_volatile) + ++lex; + else + if(!VCAttribute()) + break; + } + int t = lex[0]; + int q = 0; + if(t == tk_int || t == tk_bool || t == tk_float || t == tk_double || t == tk_void || + t == tk_long || t == tk_signed || t == tk_unsigned || t == tk_short || + t == tk_char || t == tk___int8 || t == tk___int16 || t == tk___int32 || t == tk___int64 || + t == tk_auto) { + q++; + while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and || lex[q] == tk_const) // t_and is r-value here + q++; + if(!lex.IsId(q)) + return false; + static String aut("*"), empty; + Locals(t == tk_auto ? aut : empty); + return true; + } + String type; + if(lex[q] == t_dblcolon) { + type << "::"; + q++; + } + if(lex.IsId(q)) { + type << lex.Id(q++); + type << Tparam(q); + } + else + return false; + while(lex[q] == t_dblcolon) { + type << "::"; + if(lex.IsId(++q)) + type << lex.Id(q++); + else + return false; + type << Tparam(q); + } + while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and) // t_and is r-value here + q++; + if(!lex.IsId(q)) + return false; + type = Qualify(*base, current_scope, type, context.namespace_using); + if(base->Find(NoTemplatePars(type)) >= 0) { + Locals(type); + return true; + } + return false; +} + +void Parser::MatchPars() +{ + int level = 1; + while(level && lex != t_eof) { + if(Key('(')) level++; + else + if(Key(')')) level--; + else + ++lex; + } +} + +void Parser::Statement() +{ + RecursionCounter recursionCounter(currentScopeDepth, lex == '{' ? 0 : 1); + maxScopeDepth = max(maxScopeDepth, currentScopeDepth); + + if(Key(tk_case)) { + if(lex.IsId()) + ++lex; + Key(':'); + } + if(Key(tk_default)) + Key(':'); + if(lex.IsId() && lex[1] == ':') { + ++lex; + ++lex; + } + if(Key('{')) { + Context cc; + cc <<= context; + int l = local.GetCount(); + while(!Key('}')) { + if(lex == t_eof) + ThrowError("eof"); + Statement(); + } + context <<= cc; + local.Trim(l); + } + else + if(Key(tk_if)) { + int l = local.GetCount(); + Key('('); + TryDecl(); + MatchPars(); + Statement(); + if(Key(tk_else)) + Statement(); + local.Trim(l); + } + else + if(Key(tk_for)) { + int l = local.GetCount(); + Key('('); + TryDecl(); + MatchPars(); + Statement(); + local.Trim(l); + } + else + if(Key(tk_while)) { + int l = local.GetCount(); + Key('('); + TryDecl(); + MatchPars(); + Statement(); + local.Trim(l); + } + else + if(Key(tk_try)) + Statement(); + else + if(Key(tk_catch)) { + Key('('); + MatchPars(); + Statement(); + } + else + if(Key(tk_do)) { + Statement(); + Key(tk_while); + Key('('); + MatchPars(); + } + else + if(Key(tk_switch)) { + int l = local.GetCount(); + Key('('); + TryDecl(); + MatchPars(); + Statement(); + local.Trim(l); + } + else + if(UsingNamespace()) + ; + else + if(TryDecl()) + Key(';'); + else + for(;;) { + if(lex == t_eof) + ThrowError(""); + if(Key(';') || lex == '{' || lex == '}' || lex >= tk_if && lex <= tk_do) + break; + ++lex; + } +} + +bool Parser::EatBody() +{ + if(lex != '{') { + local.Clear(); + return false; + } + lex.BeginBody(); + maxScopeDepth = currentScopeDepth = dobody ? 0 : 1; + if(dobody) { + inbody = true; + Statement(); + inbody = false; + local.Clear(); + } + else { + Key('{'); + int level = 1; + while(level && lex != t_eof) { + if(Key('{')) level++; + else + if(Key('}')) level--; + else + ++lex; + maxScopeDepth = max(level, maxScopeDepth); + } + } + lex.EndBody(); + return true; +} + +String Parser::ResolveAutoType() +{ + Vector xp = MakeXP(lex.Pos()); + if(lex == ':') // resolve for declaration, like 'for(auto i: vector)' + xp << "." << "begin" << "()" << "->"; // incorrect, should rather use operator*(), but sufficient for now + Index s = GetExpressionType(*base, *this, xp); + int i = FindMin(s); // Ugly hack: we are not resolving overloading at all, so just choose stable type if there are more + return i < 0 ? String() : s[i]; +} + +END_UPP_NAMESPACE diff --git a/uppsrc/CppBase/CppBase.h b/uppsrc/CppBase/CppBase.h index 2d98939e3..64877488c 100644 --- a/uppsrc/CppBase/CppBase.h +++ b/uppsrc/CppBase/CppBase.h @@ -512,6 +512,7 @@ struct Parser { bool Key(int code); bool EatBody(); + String ResolveAutoType(); void Cv(); String TType(); @@ -667,7 +668,7 @@ String ResolveTParam(const CppBase& codebase, const String& type, void ResolveTParam(const CppBase& codebase, Vector& type, const Vector& tparam); Index GetExpressionType(const CppBase& codebase, const Parser& parser, const Vector& xp); -Index GetExpressionType(const CppBase& codebase, const Parser& parser, const char *s); +Vector MakeXP(const char *s); END_UPP_NAMESPACE diff --git a/uppsrc/CppBase/CppBase.upp b/uppsrc/CppBase/CppBase.upp index a605790d3..660c065cb 100644 --- a/uppsrc/CppBase/CppBase.upp +++ b/uppsrc/CppBase/CppBase.upp @@ -16,6 +16,7 @@ file Pre.cpp, cpplex.cpp, Parser.cpp, + Body.cpp, Base.cpp, ScopeInfo.cpp, Qualify.cpp, diff --git a/uppsrc/CppBase/Expression.cpp b/uppsrc/CppBase/Expression.cpp index d18095aa0..2e0ea4d32 100644 --- a/uppsrc/CppBase/Expression.cpp +++ b/uppsrc/CppBase/Expression.cpp @@ -50,7 +50,6 @@ String ParseTemplatedType(const String& type, Vector& tparam) } } tparam.Add(t); - break; } else r.Cat(*s++); @@ -213,6 +212,8 @@ void ExpressionTyper::ExpressionType(const String& ttype, int ii, String t = ResolveReturnType(m, tparam); if(done.Find(t) < 0) { bool skipfnpars = m.IsCode() && ii + 1 < xp.GetCount() && xp[ii + 1] == "()"; + if(t.StartsWith(type + "::")) // Resolve Vector::Iterator -> Vector::Iterator + t.Insert(type.GetCount(), "<" + Join(tparam, ",") + ">"); ExpressionType(ResolveTParam(codebase, t, tparam), ii + skipfnpars + 1, m.IsData() && !m.isptr, lvl + 1); } @@ -361,9 +362,4 @@ Vector MakeXP(const char *s) return xp; } -Index GetExpressionType(const CppBase& codebase, const Parser& parser, const char *s) -{ - return GetExpressionType(codebase, parser, MakeXP(s)); -} - }; \ No newline at end of file diff --git a/uppsrc/CppBase/Parser.cpp b/uppsrc/CppBase/Parser.cpp index 53252ccf4..9074f1584 100644 --- a/uppsrc/CppBase/Parser.cpp +++ b/uppsrc/CppBase/Parser.cpp @@ -821,10 +821,10 @@ void Parser::Declarator(Decl& d, const char *p) // else if(lex.IsId() || lex == t_dblcolon || lex == tk_operator) { d.name = Name(d.castoper, d.oper); - bool dummy; - if(Key(':')) - if(!Key(t_integer)) - Name(dummy, dummy); + if(IsNull(d.type) && lex == ':' && lex[1] == t_integer) { // Bitfield, like 'unsigned x:5' + ++lex; + ++lex; + } } if(Key('(')) { if(inbody || (lex < 256 || lex == tk_true || lex == tk_false) @@ -852,12 +852,10 @@ void Parser::Declarator(Decl& d, const char *p) ++lex; } } - if(*d.type == '*') { // C++11 auto declaration - Index s = GetExpressionType(*base, *this, lex.Pos()); - int i = FindMin(s); // Ugly hack: we are not resolving overloading at all, so just choose stable type if there are more - d.type = i < 0 ? String() : s[i]; - } - EatInitializers(); + if(*d.type == '*') // C++11 auto declaration + d.type = ResolveAutoType(); + else + EatInitializers(); while(Key('[')) { d.isptr = true; int level = 1; @@ -1098,201 +1096,6 @@ bool Parser::VCAttribute() return false; } -bool Parser::TryDecl() -{ // attempt to interpret code as local variable declaration - for(;;) { - if(lex[0] == tk_static || lex[0] == tk_const || - lex[0] == tk_register || lex[0] == tk_volatile) - ++lex; - else - if(!VCAttribute()) - break; - } - int t = lex[0]; - int q = 0; - if(t == tk_int || t == tk_bool || t == tk_float || t == tk_double || t == tk_void || - t == tk_long || t == tk_signed || t == tk_unsigned || t == tk_short || - t == tk_char || t == tk___int8 || t == tk___int16 || t == tk___int32 || t == tk___int64 || - t == tk_auto) { - q++; - while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and || lex[q] == tk_const) // t_and is r-value here - q++; - if(!lex.IsId(q)) - return false; - Locals(t == tk_auto ? "*" : String()); - return true; - } - String type; - if(lex[q] == t_dblcolon) { - type << "::"; - q++; - } - if(lex.IsId(q)) { - type << lex.Id(q++); - type << Tparam(q); - } - else - return false; - while(lex[q] == t_dblcolon) { - type << "::"; - if(lex.IsId(++q)) - type << lex.Id(q++); - else - return false; - type << Tparam(q); - } - while(lex[q] == '*' || lex[q] == '&' || lex[q] == t_and) // t_and is r-value here - q++; - if(!lex.IsId(q)) - return false; - type = Qualify(*base, current_scope, type, context.namespace_using); - if(base->Find(NoTemplatePars(type)) >= 0) { - Locals(type); - return true; - } - return false; -} - -void Parser::MatchPars() -{ - int level = 1; - while(level && lex != t_eof) { - if(Key('(')) level++; - else - if(Key(')')) level--; - else - ++lex; - } -} - -void Parser::Statement() -{ - RecursionCounter recursionCounter(currentScopeDepth, lex == '{' ? 0 : 1); - maxScopeDepth = max(maxScopeDepth, currentScopeDepth); - - if(Key(tk_case)) { - if(lex.IsId()) - ++lex; - Key(':'); - } - if(Key(tk_default)) - Key(':'); - if(lex.IsId() && lex[1] == ':') { - ++lex; - ++lex; - } - if(Key('{')) { - Context cc; - cc <<= context; - int l = local.GetCount(); - while(!Key('}')) { - if(lex == t_eof) - ThrowError("eof"); - Statement(); - } - context <<= cc; - local.Trim(l); - } - else - if(Key(tk_if)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - if(Key(tk_else)) - Statement(); - local.Trim(l); - } - else - if(Key(tk_for)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(Key(tk_while)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(Key(tk_try)) - Statement(); - else - if(Key(tk_catch)) { - Key('('); - MatchPars(); - Statement(); - } - else - if(Key(tk_do)) { - Statement(); - Key(tk_while); - Key('('); - MatchPars(); - } - else - if(Key(tk_switch)) { - int l = local.GetCount(); - Key('('); - TryDecl(); - MatchPars(); - Statement(); - local.Trim(l); - } - else - if(UsingNamespace()) - ; - else - if(TryDecl()) - Key(';'); - else - for(;;) { - if(lex == t_eof) - ThrowError(""); - if(Key(';') || lex == '{' || lex == '}' || lex >= tk_if && lex <= tk_do) - break; - ++lex; - } -} - -bool Parser::EatBody() -{ - if(lex != '{') { - local.Clear(); - return false; - } - lex.BeginBody(); - maxScopeDepth = currentScopeDepth = dobody ? 0 : 1; - if(dobody) { - inbody = true; - Statement(); - inbody = false; - local.Clear(); - } - else { - Key('{'); - int level = 1; - while(level && lex != t_eof) { - if(Key('{')) level++; - else - if(Key('}')) level--; - else - ++lex; - maxScopeDepth = max(level, maxScopeDepth); - } - } - lex.EndBody(); - return true; -} - void Parser::SetScopeCurrent() { current_scope = context.scope;