///////////////// INSTANCE DECLARATION PASS ///////////////////////
// Returns true if we should add a * to the declarator
-static bool ReplaceClassSpec(OldList specs, Specifier spec, bool param)
+static int ReplaceClassSpec(OldList specs, Specifier spec, bool param)
{
if(spec.type == templateTypeSpecifier)
{
TemplateParameter parameter = spec.templateParameter;
-
+
if(!param && parameter.dataTypeString)
{
OldList * newSpecs = MkList();
delete newSpec;
}
FreeList(newSpecs, FreeSpecifier);
-
+
if(decl)
{
bool isPointer = decl.type == pointerDeclarator;
if(decl)
FreeDeclarator(decl);
if(isPointer)
- return true;
+ return 1;
}
}
else if(!param && parameter.dataType)
*spec = *newSpec;
delete newSpec;
}
-
+
if(decl)
{
bool isPointer = decl.type == pointerDeclarator;
if(isPointer)
- return true;
+ return 1;
}
}
else
if(classSym)
{
Class _class = classSym.registered;
- spec.type = nameSpecifier;
- if(spec.templateArgs)
- {
- FreeList(spec.templateArgs, FreeTemplateArgument);
- spec.templateArgs = null;
- }
+ FreeSpecifierContents(spec);
+ spec.type = nameSpecifier;
if(_class && _class.type == structClass)
{
//Externalexternal;
char name[1024];
name[0] = 0;
FullClassNameCat(name, _class.fullName, false);
- //spec.name = CopyString(name);
- delete spec.name;
+ FreeSpecifierContents(spec);
spec.type = structSpecifier;
spec.baseSpecs = null;
spec.id = MkIdentifier(name);
{
char name[1024] = "";
FullClassNameCat(name, _class.fullName, false);
- delete spec.name;
spec.type = structSpecifier;
spec.baseSpecs = null;
spec.id = MkIdentifier(name);
{
if((_class.type != systemClass ||
!strcmp(_class.fullName, "enum") ||
- !strcmp(_class.fullName, "ecere::com::Instance") ||
(_class.dataTypeString && !strcmp(_class.dataTypeString, "char *")) ||
//strcmp(_class.fullName, "bool") &&
!strcmp(_class.fullName, "uint64") ||
!strcmp(_class.fullName, "uint32") ||
!strcmp(_class.fullName, "uint16") ||
+ !strcmp(_class.fullName, "uintptr") ||
+ !strcmp(_class.fullName, "intptr") ||
+ !strcmp(_class.fullName, "uintsize") ||
+ !strcmp(_class.fullName, "intsize") ||
!strcmp(_class.fullName, "uint") ||
!strcmp(_class.fullName, "byte")))
{
- delete spec.name;
if(_class.dataTypeString)
{
if(!strcmp(_class.dataTypeString, "uint64") ||
!strcmp(_class.dataTypeString, "uint32") ||
!strcmp(_class.dataTypeString, "uint16") ||
+ !strcmp(_class.dataTypeString, "uintptr") ||
+ !strcmp(_class.dataTypeString, "intptr") ||
+ !strcmp(_class.dataTypeString, "uintsize") ||
+ !strcmp(_class.dataTypeString, "intsize") ||
!strcmp(_class.dataTypeString, "uint") ||
!strcmp(_class.dataTypeString, "byte"))
{
if(!_class.dataType)
_class.dataType = ProcessTypeString(_class.dataTypeString, false);
- if(_class.dataType && _class.dataType.kind == classType)
+ if(_class.dataType && _class.dataType.kind == classType)
classSym = _class.dataType._class;
else
classSym = FindClass(_class.dataTypeString);
_class = classSym ? classSym.registered : null;
}
- if(!strcmp(_class.dataTypeString, "char *"))
- spec.name = CopyString("char");
- else
- spec.name = CopyString(_class.dataTypeString);
+ spec.name = CopyString(!strcmp(_class.dataTypeString, "char *") ? "char" : _class.dataTypeString);
spec.symbol = null;
}
else
}
else if(!_class.base)
{
- delete spec.name;
spec.type = baseSpecifier;
spec.specifier = VOID;
- return true;
+ return 1;
}
}
else
{
- delete spec.name;
spec.type = structSpecifier;
spec.id = MkIdentifier("__ecereNameSpace__ecere__com__Instance");
spec.list = null;
}
if(_class && _class.dataTypeString && !strcmp(_class.dataTypeString, "char *"))
- return true; //false;
- if(!_class || _class.type == normalClass || _class.type == noHeadClass || !strcmp(_class.fullName, "ecere::com::Instance"))
- return true;
+ return 1; //false;
+ if(!_class || _class.type == normalClass || _class.type == noHeadClass)
+ return 1;
else if(param && _class.type == structClass)
return 2;
}
}
else if(spec.type == baseSpecifier)
{
- if(spec.specifier == ANY_OBJECT)
+ if(spec.specifier == ANY_OBJECT || spec.specifier == CLASS)
{
- spec.specifier = VOID;
- return true;
+ spec.specifier = CONST;
+ specs.Add(MkSpecifier(VOID));
+ return 1;
}
}
- return false;
+ return 0;
}
static void ReplaceByInstancePtr(Specifier spec, Declarator * declPtr, int type)
else
decl = newDecl;
decl.type = pointerDeclarator;
- decl.pointer.pointer = MkPointer(null, null);
+ decl.pointer.pointer = MkPointer(null, null);
*declPtr = decl;
}
}
-static void InstDeclPassSpecifier(Specifier spec)
+static void InstDeclPassSpecifier(Specifier spec, bool byRefTypedObject)
{
switch(spec.type)
{
if(spec.specifier == TYPED_OBJECT)
{
spec.type = extendedSpecifier;
- spec.extDecl = MkExtDeclString(CopyString("struct __ecereNameSpace__ecere__com__Class * class, void *"));
+ spec.extDecl = MkExtDeclString(CopyString(byRefTypedObject ?
+ "struct __ecereNameSpace__ecere__com__Class * class, void *" :
+ "struct __ecereNameSpace__ecere__com__Class * class, const void *"));
+ DeclareStruct(curExternal, "ecere::com::Class", false, true);
}
break;
case nameSpecifier:
{
for(e = spec.list->first; e; e = e.next)
{
-
+
}
}
break;
break;
}
case extendedSpecifier:
- if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s && !strcmp(spec.extDecl.s, "dllexport"))
+ if(spec.extDecl && spec.extDecl.type == extDeclString && spec.extDecl.s)
{
- Specifier prevSpec;
- delete spec.extDecl.s;
- for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
- if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
- break;
- if(prevSpec)
+ if(!strcmp(spec.extDecl.s, "dllexport"))
{
- if(targetPlatform == win32)
- spec.extDecl.s = CopyString("__declspec(dllexport)");
+ Specifier prevSpec;
+ delete spec.extDecl.s;
+ for(prevSpec = spec.prev; prevSpec; prevSpec = prevSpec.prev)
+ if(prevSpec.type == baseSpecifier && prevSpec.specifier == EXTERN)
+ break;
+ if(prevSpec)
+ {
+ if(targetPlatform == win32)
+ spec.extDecl.s = CopyString("__declspec(dllexport)");
+ else
+ spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
+ }
else
- spec.extDecl.s = CopyString("__attribute__ ((visibility(\"default\")))");
+ {
+ if(targetPlatform == win32)
+ spec.extDecl.s = CopyString("extern __declspec(dllexport)");
+ else
+ spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
+ }
}
- else
+ else if(!strcmp(spec.extDecl.s, "stdcall") || !strcmp(spec.extDecl.s, "_stdcall") ||
+ !strcmp(spec.extDecl.s, "__stdcall") || !strcmp(spec.extDecl.s, "__stdcall__"))
{
+ delete spec.extDecl.s;
if(targetPlatform == win32)
- spec.extDecl.s = CopyString("extern __declspec(dllexport)");
+ spec.extDecl.s = CopyString("__attribute__((__stdcall__))");
else
- spec.extDecl.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
+ spec.extDecl.s = CopyString("");
}
}
break;
qualifiers = MkListOne(MkStructOrUnion(structSpecifier, MkIdentifier("__ecereNameSpace__ecere__com__Class"), null));
declarator = MkDeclaratorPointer(MkPointer(null,null), MkDeclaratorIdentifier(MkIdentifier("class")));
};
+ DeclareStruct(curExternal, "ecere::com::Class", false, true);
decl.function.parameters->Insert(spec.prev, _class);
}
}
decl.extended.extended.s = CopyString("extern __attribute__ ((visibility(\"default\")))");
}
else if(decl.extended.extended.type == extDeclString && decl.extended.extended.s &&
- (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") ||
+ (!strcmp(decl.extended.extended.s, "stdcall") || !strcmp(decl.extended.extended.s, "_stdcall") ||
!strcmp(decl.extended.extended.s, "__stdcall") || !strcmp(decl.extended.extended.s, "__stdcall__")))
{
delete decl.extended.extended.s;
else
{
Symbol classSym = (spec.type == nameSpecifier) ? spec.symbol /*FindClass(spec.name)*/ : null;
- if(type.classObjectType && (!classSym || (classSym && classSym.registered &&
- (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass ||
- (classSym.registered.type == systemClass && strcmp(classSym.string, "ecere::com::Instance") && strcmp(classSym.string, "ecere::com::Class"))))))
+ if(type.classObjectType && (!classSym || (classSym && classSym.registered &&
+ (classSym.registered.type == enumClass || classSym.registered.type == bitClass || classSym.registered.type == unitClass))))
ReplaceByInstancePtr(spec, &type.declarator, 2);
}
- InstDeclPassSpecifier(spec);
+ InstDeclPassSpecifier(spec, type.declarator && type.declarator.type == pointerDeclarator);
}
}
if(type.declarator)
}
}
+/*static */bool IsVoidPtrCast(TypeName typeName)
+{
+ bool result = false;
+ Declarator d = typeName.declarator;
+ if(d && d.type == pointerDeclarator && d.pointer.pointer && !d.pointer.pointer.pointer)
+ {
+ if(typeName.qualifiers)
+ {
+ Specifier s;
+ for(s = typeName.qualifiers->first; s; s = s.next)
+ {
+ if(s.type == baseSpecifier && s.specifier == VOID)
+ result = true;
+ }
+ }
+ }
+ return result;
+}
+
+static void AddPointerCast(Expression e)
+{
+ Type src = e.expType;
+
+ if(src && (src.kind == templateType || src.kind == classType))
+ {
+ if(e.type != castExp || !IsVoidPtrCast(e.cast.typeName))
+ {
+ if(src) src.refCount++;
+ if(src.kind == templateType && src.templateParameter && src.templateParameter.type == type)
+ {
+ Type newType = null;
+ if(src.templateParameter.dataTypeString)
+ newType = ProcessTypeString(src.templateParameter.dataTypeString, false);
+ else if(src.templateParameter.dataType)
+ newType = ProcessType(src.templateParameter.dataType.specifiers, src.templateParameter.dataType.decl);
+ if(newType)
+ {
+ FreeType(src);
+ src = newType;
+ }
+ }
+ if(src && src.kind == classType && src._class)
+ {
+ Class sc = src._class.registered;
+ if(src.thisClassFrom)
+ sc = src.thisClassFrom;
+
+ if(sc && (sc.type == structClass || sc.type == noHeadClass))
+ {
+ Type dest = e.destType;
+
+ if(dest && (dest.kind == templateType || dest.kind == classType))
+ {
+ if(dest) dest.refCount++;
+
+ if(dest.kind == templateType && dest.templateParameter && dest.templateParameter.type == type)
+ {
+ Type newType = null;
+ if(dest.templateParameter.dataTypeString)
+ newType = ProcessTypeString(dest.templateParameter.dataTypeString, false);
+ else if(dest.templateParameter.dataType)
+ newType = ProcessType(dest.templateParameter.dataType.specifiers, dest.templateParameter.dataType.decl);
+ if(newType)
+ {
+ FreeType(dest);
+ dest = newType;
+ }
+ }
+ if(!dest.passAsTemplate && dest.kind == classType && dest._class && dest._class.registered)
+ {
+ Class dc = dest._class.registered;
+ if(dest.thisClassFrom)
+ dc = dest.thisClassFrom;
+
+ if(sc.templateClass) sc = sc.templateClass;
+ if(dc.templateClass) dc = dc.templateClass;
+ if(dc.base && sc != dc)
+ {
+ e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+ e.type = castExp;
+ e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+ }
+ }
+ FreeType(dest);
+ }
+ }
+ }
+ FreeType(src);
+ }
+ }
+}
+
static void InstDeclPassExpression(Expression exp)
{
switch(exp.type)
if(exp.op.exp1)
InstDeclPassExpression(exp.op.exp1);
if(exp.op.exp2)
+ {
InstDeclPassExpression(exp.op.exp2);
+ if(exp.op.op != '=' && exp.op.exp1 && exp.op.exp1.expType && exp.op.exp1.expType.kind == pointerType && exp.op.exp1.expType.type && exp.op.exp1.expType.type.kind == templateType &&
+ exp.op.exp2.expType && exp.op.exp2.expType.kind == pointerType && exp.op.exp2.expType.type && exp.op.exp2.expType.type.kind == templateType)
+ {
+ Expression e = exp.op.exp2;
+ e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+ e.type = castExp;
+ e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+
+ e = exp.op.exp1;
+ e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+ e.type = castExp;
+ e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+ }
+ else if(exp.op.exp1 && (exp.op.op == '=' || exp.op.op == EQ_OP || exp.op.op == NE_OP))
+ AddPointerCast(exp.op.exp2);
+ }
break;
case extensionExpressionExp:
case bracketsExp:
if(exp.call.arguments)
{
for(e = exp.call.arguments->first; e; e = e.next)
+ {
+ bool addCast = false;
InstDeclPassExpression(e);
+ AddPointerCast(e);
+
+ if(e.expType && e.expType.kind == pointerType && e.expType.type && (e.expType.type.kind == classType || (e.expType.type.kind == pointerType && e.expType.type.type && e.expType.type.type.kind != voidType)) &&
+ e.destType && e.destType.kind == pointerType && e.destType.type && e.destType.type.kind == pointerType && e.destType.type.type && e.destType.type.type.kind == voidType)
+ addCast = true;
+ // Fix for adding a cast to Unserialize with a struct passed as a parameter:
+ else if(e.expType && e.expType.kind == classType && e.expType._class && e.expType._class.registered && e.expType._class.registered.type == structClass && e.byReference &&
+ e.destType && e.destType.kind == classType && e.destType.classObjectType && e.destType.byReference)
+ addCast = true;
+
+ if(addCast && (e.type != castExp || !IsVoidPtrCast(e.cast.typeName)))
+ {
+ e.cast.exp = MkExpBrackets(MkListOne(MoveExpContents(e)));
+ e.type = castExp;
+ e.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), QMkPtrDecl(null));
+ }
+ }
}
break;
}
case memberExp:
{
- InstDeclPassExpression(exp.member.exp);
+ if(exp.member.exp)
+ InstDeclPassExpression(exp.member.exp);
break;
}
case pointerExp:
{
- InstDeclPassExpression(exp.member.exp);
+ if(exp.member.exp)
+ InstDeclPassExpression(exp.member.exp);
break;
}
case typeSizeExp:
{
Type type = exp.expType;
// Remove casts to simple structs... (Watch out for pointers later...)
- if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass)
- {
- Expression castExp = exp.cast.exp;
- Expression prev = exp.prev, next = exp.next;
- exp.cast.exp = null;
- FreeExpContents(exp);
- FreeType(exp.expType);
- FreeType(exp.destType);
- *exp = *castExp;
- delete castExp;
- exp.prev = prev;
- exp.next = next;
- InstDeclPassExpression(exp);
+ if(type && type.kind == classType && type._class.registered && type._class.registered.type == structClass && !exp.needCast)
+ {
+ if(exp.destType && exp.destType.classObjectType == typedObject && exp.destType.byReference)
+ {
+ // For Unserialize with a StaticString
+ FreeTypeName(exp.cast.typeName);
+ exp.cast.typeName = MkTypeName(MkListOne(MkSpecifier(VOID)), MkDeclaratorPointer(MkPointer(null, MkPointer(null, null)), null));
+ }
+ else
+ {
+ Expression castExp = exp.cast.exp;
+ Expression prev = exp.prev, next = exp.next;
+ exp.cast.exp = null;
+ FreeExpContents(exp);
+ FreeType(exp.expType);
+ FreeType(exp.destType);
+ *exp = *castExp;
+ delete castExp;
+ exp.prev = prev;
+ exp.next = next;
+ InstDeclPassExpression(exp);
+ }
}
else
{
- InstDeclPassTypeName(exp.cast.typeName, false);
+ if(exp.expType && exp.expType.kind == pointerType)
+ {
+ if(exp.cast.exp && exp.cast.exp.expType && exp.cast.exp.expType.kind == templateType && !exp.cast.exp.expType.isPointerType)
+ exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
+ }
+
+ InstDeclPassTypeName(exp.cast.typeName, exp.usage.usageArg /*false*/);
if(exp.cast.exp)
+ {
+ if(exp.expType && exp.expType.kind == templateType && exp.destType &&
+ (exp.destType.passAsTemplate || (!exp.destType.templateParameter || (!exp.destType.templateParameter.dataType && !exp.destType.templateParameter.dataTypeString))) &&
+ exp.cast.exp.expType && !exp.cast.exp.expType.passAsTemplate && exp.cast.exp.expType.isPointerType)
+ exp.cast.exp = MkExpCast(MkTypeName(MkListOne(MkSpecifierName("uintptr")), null), exp.cast.exp);
InstDeclPassExpression(exp.cast.exp);
+ }
}
break;
}
switch(init.type)
{
case expInitializer:
- InstDeclPassExpression(init.exp);
+ if(init.exp)
+ {
+ InstDeclPassExpression(init.exp);
+ AddPointerCast(init.exp);
+ }
break;
case listInitializer:
{
ReplaceByInstancePtr(spec, &d.declarator, type);
}
}
- InstDeclPassSpecifier(spec);
+ InstDeclPassSpecifier(spec, false);
}
}
if(decl.declarators)
ReplaceByInstancePtr(spec, &d, type);
}
}
- InstDeclPassSpecifier(spec);
+ InstDeclPassSpecifier(spec, false);
}
}
{
switch(stmt.type)
{
+ case badDeclarationStmt:
+ if(stmt.decl)
+ InstDeclPassDeclaration(stmt.decl);
+ break;
case labeledStmt:
InstDeclPassStatement(stmt.labeled.stmt);
break;
if(!stmt.compound.isSwitch)
curContext = stmt.compound.context;
-
+
if(stmt.compound.declarations)
{
for(decl = stmt.compound.declarations->first; decl; decl = decl.next)
case switchStmt:
{
Expression exp;
- for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
- InstDeclPassExpression(exp);
+ if(stmt.switchStmt.exp)
+ {
+ for(exp = stmt.switchStmt.exp->first; exp; exp = exp.next)
+ InstDeclPassExpression(exp);
+ }
InstDeclPassStatement(stmt.switchStmt.stmt);
break;
}
case whileStmt:
{
Expression exp;
- for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
- InstDeclPassExpression(exp);
+ if(stmt.whileStmt.exp)
+ {
+ for(exp = stmt.whileStmt.exp->first; exp; exp = exp.next)
+ InstDeclPassExpression(exp);
+ }
InstDeclPassStatement(stmt.whileStmt.stmt);
break;
}
{
for(exp = stmt.expressions->first; exp; exp = exp.next)
InstDeclPassExpression(exp);
+ AddPointerCast(stmt.expressions->last);
}
break;
}
}
}
+void TopoSort(OldList * input)
+{
+ OldList L { };
+ OldList S { };
+ OldList B { };
+ External n, next;
+ //External x;
+
+ for(n = input->first; n; n = next)
+ {
+ next = n.next;
+ if(n.type == declarationExternal && !n.declaration)
+ {
+ input->Remove(n);
+ if(n.symbol && n.symbol.structExternal == n)
+ n.symbol.structExternal = null;
+ FreeExternal(n);
+ }
+ else if(!n.incoming.count)
+ {
+ input->Remove(n);
+ S.Add(n);
+ }
+ else if(!n.nonBreakableIncoming)
+ {
+ input->Remove(n);
+ B.Add(n);
+ }
+ }
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }*/
+
+ while(true)
+ {
+ TopoEdge e, ne;
+ if((n = S.first))
+ {
+ /*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }*/
+
+ //DebugPrint("*** Free Node: [", n.id, "]\n\t", n.output);
+ S.Remove((IteratorPointer)n);
+
+ /*
+ if(n && n.symbol && n.symbol.string && !strcmp(n.symbol.string, "ecere::com::Instance"))
+ printf("Adding Instance\n");
+ */
+
+ L.Add(n);
+ for(e = n.outgoing.first; e; e = ne)
+ {
+ External m = e.to;
+ OldList * list;
+
+ //DebugPrint(" This Free Node has an edge to [", m.id, "] ", m.output);
+ if(m.nonBreakableIncoming)
+ {
+ //DebugPrint("... which we think is in input");
+ list = input;
+ }
+ else
+ {
+ //DebugPrint("... which we think is in B");
+ list = &B;
+ }
+
+ if(!list->count)
+ PrintLn("!!! Something's wrong !!!");
+ ne = e.out.next;
+
+ if(!e.breakable)
+ {
+#ifdef _DEBUG
+ if(!m.nonBreakableIncoming)
+ printf("Bug");
+#endif
+ m.nonBreakableIncoming--;
+ //DebugPrint("Reducing non breakable incoming, now ", m.nonBreakableIncoming);
+ }
+
+ n.outgoing.Remove((IteratorPointer)e);
+ m.incoming.Remove((IteratorPointer)e);
+ delete e;
+
+ if(!m.incoming.count)
+ {
+ //DebugPrint("Last edge to this node taken out, moving to S...");
+ list->Remove(m);
+ S.Add(m);
+ }
+ else if(!m.nonBreakableIncoming)
+ {
+ //DebugPrint("Last non-breakable edge to this node taken out, moving to B...");
+ list->Remove(m);
+ B.Add(m);
+ }
+ }
+ }
+ else if((n = B.first))
+ {
+ //DebugPrint("Breaking some of the ", n.incoming.count, " incoming edges to [", n.id, "] ", n.output);
+ B.Remove((IteratorPointer)n);
+
+ // Break the edges of this node
+ for(e = n.incoming.first; e; e = ne)
+ {
+ TopoEdge e2, n2;
+ External m = e.from;
+ External f;
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y && from != n)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }*/
+
+ f = m.ForwardDeclare();
+ ne = e.in.next;
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y && from != n && from != f)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }
+*/
+ // Recheck input for edges created by forward declaration
+ {
+ External c, next;
+ for(c = input->first; c; c = next)
+ {
+ next = c.next;
+ if(!c.incoming.count)
+ {
+ input->Remove(c);
+ S.Add(c);
+ }
+ else if(!c.nonBreakableIncoming)
+ {
+ input->Remove(c);
+ B.Add(c);
+ }
+ }
+ }
+
+ //DebugPrint("Breaking edge from ", e.from.id, " to ", e.to.id);
+ //DebugPrint("Creating a forward decl node [", f.id, "] for [", m.id, "]");
+
+ for(e2 = m.outgoing.first; e2; e2 = n2)
+ {
+ n2 = e2.out.next;
+ if(e2.breakable)
+ {
+ External to = e2.to;
+
+ if(e2 == e)
+ ;//DebugPrint("Breaking this particular connection");
+ else
+ ;//DebugPrint("Also redirecting connection from ", m.id, " to ", to.id, " to come from ", f.id, " instead.");
+ e2.breakable = false;
+ e2.from = f;
+ m.outgoing.Remove((IteratorPointer)e2);
+ f.outgoing.Add(e2);
+ to.nonBreakableIncoming++;
+ if(e2 != e && to.nonBreakableIncoming == 1)
+ {
+ // If this node was previously in B, move it to input
+ B.Remove(to);
+ input->Add(to);
+ }
+
+ //DebugPrint("Node ", e2.to.id, " now has ", e2.to.nonBreakableIncoming, " non-breakable incoming edges.");
+ }
+ }
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y && from != n && from != f)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }*/
+ if(!f.incoming.count)
+ S.Add(f);
+ else if(!f.nonBreakableIncoming)
+ B.Add(f);
+ else
+ input->Add(f);
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = L.first; y; y = y.next)
+ if(y == from)
+ {
+ PrintLn("This node is already in L!");
+ break;
+ }
+ }
+
+ if(!y && from != n)
+ {
+ ConsoleFile file { };
+ printf("This node is nowhere!\n");
+ OutputExternal(from, file);
+ delete file;
+ }
+ }
+ }
+*/
+ // Avoid needless edge breaking by processing a node as soon as one shows up in S
+ if(S.first)
+ break;
+ }
+
+ // Put n back in input because it now has unbreakable edges
+ input->Add(n);
+ }
+ else
+ {
+ if(input->count)
+ {
+#ifdef _DEBUG
+ ConsoleFile f { };
+ External e = input->first;
+#endif
+ Compiler_Error("declarations cycles found\n");
+#ifdef _DEBUG
+ //OutputTree(input, f);
+/*
+ for(x = input->first; x; x = x.next)
+ {
+ int count = 0;
+ for(e : x.incoming; !e.breakable)
+ count++;
+ if(count != x.nonBreakableIncoming)
+ printf("Bug in input");
+ if(!x.incoming.count)
+ printf("This node should be in S!\n");
+
+ for(e : x.incoming)
+ {
+ External y, from = e.from;
+ for(y = input->first; y; y = y.next)
+ if(y == from)
+ break;
+ if(!y)
+ {
+ for(y = B.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+
+ if(!y)
+ {
+ for(y = S.first; y; y = y.next)
+ if(y == from)
+ break;
+ }
+ if(!y)
+ {
+ printf("This node is nowhere!\n");
+ }
+ }
+ }
+*/
+ SetOutputLineNumbers(false);
+ OutputExternal(e, f);
+
+ PrintLn("\nDepends on:\n");
+ { TopoEdge i; for(i = e.incoming.last; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+ OutputExternal(e, f);
+
+ PrintLn("\nWhile that depends on:\n");
+ { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+ OutputExternal(e, f);
+
+ PrintLn("\nWhile that depends on:\n");
+ { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+ OutputExternal(e, f);
+
+ PrintLn("\nWhile that depends on:\n");
+ { TopoEdge i; for(i = e.incoming.first; i && !i.breakable && i.from.incoming.count; i = i.in.next) { e = i.from; break; } }
+
+ OutputExternal(e, f);
+ delete f;
+
+ system("pause");
+
+ while((e = input->first))
+ {
+ input->Remove(e);
+ L.Add(e);
+ }
+ *input = L;
+#endif
+ }
+ else
+ *input = L;
+ break;
+ }
+ }
+
+ for(n = input->first; n; n = next)
+ {
+ next = n.next;
+ if(n.type == declarationExternal && (!n.declaration || ((!n.declaration.specifiers || !n.declaration.specifiers->count) && (!n.declaration.declarators || !n.declaration.declarators->count))))
+ {
+ input->Remove(n);
+ if(n.symbol && n.symbol.structExternal == n)
+ n.symbol.structExternal = null;
+ FreeExternal(n);
+ }
+ }
+}
+
public void ProcessInstanceDeclarations()
{
External external;
int type;
if((type = ReplaceClassSpec(func.specifiers, spec, false)))
ReplaceByInstancePtr(spec, &func.declarator, type);
- InstDeclPassSpecifier(spec);
+ InstDeclPassSpecifier(spec, false);
}
}
InstDeclPassDeclarator(func.declarator);
else if(external.type == declarationExternal)
{
if(external.declaration)
- InstDeclPassDeclaration(external.declaration);
+ InstDeclPassDeclaration(external.declaration);
}
}
+
+ // Perform topological sort
+ TopoSort(ast);
}