mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 22:02:49 -06:00
315 lines
8.1 KiB
C++
315 lines
8.1 KiB
C++
#include "CppBase.h"
|
|
#include "Internal.h"
|
|
|
|
namespace Upp {
|
|
|
|
#define LLOG(x) // DLOG(x)
|
|
#define LTIMING(x) // DTIMING(x)
|
|
|
|
bool DoQualify(ScopeInfo& nf, const String& type, const String& usings, String& qt);
|
|
|
|
bool Qualify0(ScopeInfo& nf, const String& type, const String& usings, String& qt)
|
|
{ // Qualify single type based on scoping information
|
|
const Vector<String>& nd = nf.GetScopes(usings);
|
|
if(nd.GetCount()) {
|
|
LTIMING("First test");
|
|
qt = nd[0] + type;
|
|
if(nf.base.Find(qt) >= 0)
|
|
return true;
|
|
}
|
|
if(nf.GetScope() >= 0) {
|
|
int q = type.ReverseFind(':');
|
|
if(q > 0) {
|
|
LTIMING("Qualifying qualification");
|
|
ScopeInfo hnf(nf);
|
|
hnf.NoBases();
|
|
String qn;
|
|
String qs = type.Mid(0, q - 1);
|
|
if(IsDigit(*qs)) {
|
|
qt = type;
|
|
return true;
|
|
}
|
|
if(DoQualify(hnf, qs, usings, qn)) {
|
|
String tp = type.Mid(q + 1);
|
|
if(nf.base.Find(qn) >= 0) {
|
|
qt = qn + "::" + tp;
|
|
return true;
|
|
}
|
|
int scopei = nf.base.Find(qn);
|
|
if(scopei >= 0) {
|
|
ScopeInfo nnf(nf.base, scopei);
|
|
const Vector<String>& bs = nnf.GetBases();
|
|
for(int i = 0; i < bs.GetCount(); i++) {
|
|
qt = bs[i] + tp;
|
|
if(nf.base.Find(qt) >= 0)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if(nf.base.Find(qs) >= 0) {
|
|
qt = qs;
|
|
return true;
|
|
}
|
|
qt = type;
|
|
if(nf.base.Find(qt) >= 0) // e.g. std::string
|
|
return true;
|
|
qt = type.Mid(q + 1);
|
|
return true;
|
|
}
|
|
else {
|
|
LTIMING("Bases");
|
|
const Vector<String>& bs = nf.GetBases();
|
|
for(int i = 0; i < bs.GetCount(); i++) {
|
|
qt = bs[i] + type;
|
|
if(nf.base.Find(qt) >= 0)
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
if(type[0] != ':') {
|
|
LTIMING("Testing scopes");
|
|
for(int i = 1; i < nd.GetCount(); i++) {
|
|
qt = nd[i] + type;
|
|
if(nf.base.Find(qt) >= 0)
|
|
return true;
|
|
}
|
|
}
|
|
int q = type.Find(':');
|
|
if(q < 0)
|
|
return false;
|
|
return Qualify0(nf, type.Mid(q + 1), usings, qt);
|
|
}
|
|
|
|
bool DoQualify(ScopeInfo& nf, const String& type, const String& usings, String& qt)
|
|
{
|
|
LTIMING("Qualify");
|
|
int q = nf.cache.Find(type);
|
|
if(q >= 0) {
|
|
qt = nf.cache[q];
|
|
return true;
|
|
}
|
|
LTIMING("Qualify0");
|
|
if(!Qualify0(nf, type, usings, qt))
|
|
return false;
|
|
nf.cache.Add(type, qt);
|
|
return true;
|
|
}
|
|
|
|
String DoQualify(ScopeInfo& nf, const String& type, const String& usings)
|
|
{
|
|
String qt;
|
|
return DoQualify(nf, type, usings, qt) ? qt : type;
|
|
}
|
|
|
|
static String s_int("int");
|
|
static String s_void("void");
|
|
static String s_double("double");
|
|
static String s_char("char");
|
|
static String s_float("float");
|
|
static String s_long("long");
|
|
static String s_const("const");
|
|
static String s_struct("struct");
|
|
static String s_class("class");
|
|
static String s_unsigned("unsigned");
|
|
|
|
inline void Qualify(String& r, ScopeInfo& nf, const char *b, const char *s, const String& usings)
|
|
{
|
|
String type(b, s);
|
|
if(type.GetCount() == 0 || type == s_const ||
|
|
type == s_int || type == s_double || type == s_char ||
|
|
type == s_long || type == s_unsigned || type == s_struct || type == s_class ||
|
|
type == s_float) {
|
|
r << type;
|
|
return;
|
|
}
|
|
r << DoQualify(nf, type, usings);
|
|
}
|
|
|
|
String QualifyIds(ScopeInfo& nf, const String& k, const String& usings, bool all)
|
|
{
|
|
LTIMING("QualifyIds");
|
|
String r;
|
|
const char *s = k;
|
|
Vector<String> empty;
|
|
while(*s) {
|
|
int c = *s;
|
|
if(c == ':') {
|
|
const char *b = s++;
|
|
while(*s == ':' || iscid(*s)) s++;
|
|
/* if(all) {
|
|
if(iscid(*r.Last()))
|
|
r << ' ';
|
|
ScopeInfo nnf(nf.GetScope(), nf.base);
|
|
Qualify(r, nnf, b, s, usings);
|
|
}
|
|
else*/
|
|
r.Cat(b, s);
|
|
}
|
|
else
|
|
if(iscid(c)) {
|
|
if(iscid(*r.Last()))
|
|
r << ' ';
|
|
if(s[0] == 'c' && s[1] == 'o' && s[2] == 'n' && s[3] == 's' && s[4] == 't' && !iscid(s[5])) {
|
|
r << s_const;
|
|
s += 5;
|
|
}
|
|
else
|
|
if(s[0] == 'm' && s[1] == 'u' && s[2] == 't' && s[3] == 'a' && s[4] == 'b' && s[5] == 'l' && s[6] == 'e' && !iscid(s[7])) {
|
|
r << "mutable";
|
|
s += 7;
|
|
}
|
|
else
|
|
if(s[0] == 'v' && s[1] == 'o' && s[2] == 'l' && s[3] == 'a' && s[4] == 't' && s[5] == 'i' && s[6] == 'l' && s[7] == 'e' && !iscid(s[8])) {
|
|
r << "volatile";
|
|
s += 8;
|
|
}
|
|
else {
|
|
const char *b = s++;
|
|
while(*s == ':' || iscid(*s)) s++;
|
|
if(all)
|
|
Qualify(r, nf, b, s, usings);
|
|
else
|
|
r.Cat(b, s);
|
|
}
|
|
}
|
|
else {
|
|
if(c == '(')
|
|
all = true;
|
|
if(c != ' ')
|
|
r.Cat(c);
|
|
s++;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
|
|
String Qualify(const CppBase& base, const String& scope, const String& type, const String& usings)
|
|
{
|
|
if(type.StartsWith("::"))
|
|
return type.Mid(2);
|
|
ScopeInfo nf(base, scope);
|
|
return QualifyIds(nf, type, usings, true);
|
|
}
|
|
|
|
String QualifyKey(const CppBase& base, const String& scope, const String& type, const String& usings)
|
|
{
|
|
ScopeInfo nf(base, scope);
|
|
return QualifyIds(nf, type, usings, false);
|
|
}
|
|
|
|
void QualifyTypes(CppBase& base, const String& scope, CppItem& m)
|
|
{
|
|
ScopeInfo nf(base, scope);
|
|
m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true);
|
|
m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true);
|
|
}
|
|
|
|
void QualifyPass0(CppBase& base)
|
|
{ // Move scopes - solve: namespace X { struct C { void Foo(); }; using namespace X; void C::Foo() {}
|
|
Vector<int> remove_scope;
|
|
for(int ni = 0; ni < base.GetCount(); ni++) {
|
|
Array<CppItem>& n = base[ni];
|
|
ScopeInfo nf(base);
|
|
String scope = base.GetKey(ni);
|
|
String usings;
|
|
int toscopei = -1;
|
|
Vector<int> remove_item;
|
|
for(int i = 0; i < n.GetCount(); i++) {
|
|
CppItem& m = n[i];
|
|
if(m.qualify && m.impl) {
|
|
if(usings != m.using_namespaces) {
|
|
usings = m.using_namespaces;
|
|
toscopei = -1;
|
|
Vector<String> h = Split(m.using_namespaces, ';');
|
|
for(int i = 0; i < h.GetCount(); i++) {
|
|
String ns = h[i] + "::" + scope;
|
|
toscopei = base.Find(ns);
|
|
if(toscopei >= 0)
|
|
break;
|
|
}
|
|
}
|
|
if(toscopei >= 0 && toscopei != ni) {
|
|
base[toscopei].Add(m);
|
|
remove_item.Add(i);
|
|
}
|
|
}
|
|
}
|
|
n.Remove(remove_item);
|
|
if(scope.GetCount() && n.GetCount() == 0)
|
|
remove_scope.Add(ni);
|
|
}
|
|
base.Remove(remove_scope);
|
|
}
|
|
|
|
void QualifyPass1(CppBase& base)
|
|
{ // Qualify types
|
|
LTIMING("QualifyPass1");
|
|
for(int ni = 0; ni < base.GetCount(); ni++) {
|
|
Array<CppItem>& n = base[ni];
|
|
ScopeInfo nf(base, ni);
|
|
for(int i = 0; i < n.GetCount(); i++) {
|
|
CppItem& m = n[i];
|
|
if(m.kind == NAMESPACE)
|
|
base.namespaces.FindAdd(base.GetKey(ni));
|
|
if(m.IsType() && m.qualify) {
|
|
m.qualify = false;
|
|
m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true); // type of item, now qualified (probaly already was)
|
|
m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true); // base classes
|
|
m.qitem = m.item; // name of type (struct) item is already qualified
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void QualifyPass2(CppBase& base)
|
|
{ // Qualify function parameters
|
|
LTIMING("QualifyPass2");
|
|
for(int ni = 0; ni < base.GetCount(); ni++) {
|
|
Array<CppItem>& n = base[ni];
|
|
ScopeInfo nf(base, ni);
|
|
for(int i = 0; i < n.GetCount(); i++) {
|
|
CppItem& m = n[i];
|
|
if(m.uname.GetCount() == 0 && m.name.GetCount())
|
|
m.uname = ToUpper(m.name);
|
|
if(!m.IsType() && m.qualify) {
|
|
m.qualify = false;
|
|
m.qtype = QualifyIds(nf, m.type, m.using_namespaces, true);
|
|
m.qptype = QualifyIds(nf, m.ptype, m.using_namespaces, true);
|
|
m.qitem = m.IsCode() ? QualifyIds(nf, m.item, m.using_namespaces, false)
|
|
: m.item;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Qualify(CppBase& base)
|
|
{
|
|
Md5Stream md5;
|
|
Vector<int> no = GetSortOrder(base.GetKeys());
|
|
for(int q = 0; q < base.GetCount(); q++) {
|
|
int ni = no[q];
|
|
md5 << base.GetKey(ni);
|
|
const Array<CppItem>& n = base[ni];
|
|
for(int i = 0; i < n.GetCount(); i++) {
|
|
const CppItem& m = n[i];
|
|
if(m.IsType())
|
|
md5 << ';' << m.ptype;
|
|
}
|
|
md5 << '\n';
|
|
}
|
|
String c5 = md5.FinishString();
|
|
if(c5 != base.types_md5) { // set of types changed, requalify everything
|
|
base.types_md5 = c5;
|
|
for(int ni = 0; ni < base.GetCount(); ni++) {
|
|
Array<CppItem>& n = base[ni];
|
|
for(int i = 0; i < n.GetCount(); i++)
|
|
n[i].qualify = true;
|
|
}
|
|
}
|
|
base.namespaces.Clear();
|
|
QualifyPass0(base);
|
|
QualifyPass1(base);
|
|
QualifyPass2(base);
|
|
}
|
|
|
|
}
|