compiler/bootstrap: Fixes
[sdk] / compiler / libec / src / ecdefs.ec
index 95685c8..7b55810 100644 (file)
@@ -183,6 +183,9 @@ class DBIndexItem : struct
 bool inCompiler = false;
 public void SetInCompiler(bool b) { inCompiler = b; }
 
+bool inDebugger = false;
+public void SetInDebugger(bool b) { inDebugger = b; }
+
 Context curContext;
 Context globalContext;
 OldList * excludedSymbols;
@@ -197,16 +200,16 @@ public void SetMainModule(ModuleImport moduleImport) { mainModule = moduleImport
 File fileInput;
 public void SetFileInput(File file) { fileInput = file; }
 char * symbolsDir = null;
-public void SetSymbolsDir(char * s) {
+public void SetSymbolsDir(const char * s) {
    delete symbolsDir;
    symbolsDir = CopyString(s);
-} public char * GetSymbolsDir() { return symbolsDir ? symbolsDir : ""; }
-char * outputFile;
-public void SetOutputFile(char * s) { outputFile = s; } public char * GetOutputFile() { return outputFile; }
-char * sourceFile;
-public void SetSourceFile(char * s) { sourceFile = s; } public char * GetSourceFile() { return sourceFile; }
-char * i18nModuleName;
-public void SetI18nModuleName(char * s) { i18nModuleName = s; } public char * GetI18nModuleName() { return i18nModuleName; }
+} public const char * GetSymbolsDir() { return symbolsDir ? symbolsDir : ""; }
+const char * outputFile;
+public void SetOutputFile(const char * s) { outputFile = s; } public const char * GetOutputFile() { return outputFile; }
+const char * sourceFile;
+public void SetSourceFile(const char * s) { sourceFile = s; } public const char * GetSourceFile() { return sourceFile; }
+const char * i18nModuleName;
+public void SetI18nModuleName(const char * s) { i18nModuleName = s; } public const char * GetI18nModuleName() { return i18nModuleName; }
 
 public void SetGlobalContext(Context context) { globalContext = context; } public Context GetGlobalContext() { return globalContext; }
 public void SetTopContext(Context context) { topContext = context; } public Context GetTopContext() { return topContext; }
@@ -229,29 +232,31 @@ public void FixModuleName(char *moduleName)
 // todo support %var% variables for windows and $var for linux?
 public char * PassArg(char * output, const char * input)
 {
-#ifdef __WIN32__
-//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
-   const char * escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping;
-   const char * escCharsQuoted = "\"";
-#else
-//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
-   const char * escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping;
-   const char * escCharsQuoted = "\"()$";
-#endif
+   const char * escChars, * escCharsQuoted;
    bool quoting = false;
-   char *o = output, *i = input, *l = input;
-#ifdef __WIN32__
-   while(*l && !strchr(escChars, *l)) l++;
-   if(*l) quoting = true;
-#else
-   if(*i == '-')
+   char *o = output;
+   const char *i = input, *l = input;
+   if(__runtimePlatform == win32)
    {
-      l++;
+//define windowsFileNameCharsNeedEscaping = " !%&'()+,;=[]^`{}~"; // "#$-.@_" are ok
+      escChars = " !\"%&'()+,;=[]^`{}~"; // windowsFileNameCharsNeedEscaping;
+      escCharsQuoted = "\"";
       while(*l && !strchr(escChars, *l)) l++;
       if(*l) quoting = true;
-      *o++ = *i++;
    }
-#endif
+//define linuxFileNameCharsNeedEscaping = " !\"$&'()*:;<=>?[\\`{|"; // "#%+,-.@]^_}~" are ok
+   else
+   {
+      escChars = " !\"$&'()*:;<=>?[\\`{|"; // linuxFileNameCharsNeedEscaping;
+      escCharsQuoted = "\"()$";
+      if(*i == '-')
+      {
+         l++;
+         while(*l && !strchr(escChars, *l)) l++;
+         if(*l) quoting = true;
+         *o++ = *i++;
+      }
+   }
    if(quoting)
       *o++ = '\"';
    while(*i)
@@ -441,7 +446,7 @@ public:
    TemplateArgument defaultArgument;
 
    // For type parameters
-   char * dataTypeString;
+   const char * dataTypeString;
    Type baseType;
 }
 
@@ -488,13 +493,14 @@ public:
          ExtDecl extDecl;
          char * name;
          Symbol symbol;
-         OldList * templateArgs;
+         OldList/*<TemplateArgument>*/ * templateArgs;
+         Specifier nsSpec;
       };
       struct
       {
          Identifier id;
-         OldList * list;
-         OldList * baseSpecs;
+         OldList/*<Enumerator>*/ * list;
+         OldList/*<Specifier>*/ * baseSpecs;
          OldList/*<ClassDef>*/ * definitions;
          bool addNameSpace;
          Context ctx;
@@ -559,6 +565,7 @@ public:
       {
          char * string;
          bool intlString;
+         bool wideString;
       };
       OldList * list;
       struct
@@ -659,6 +666,7 @@ public:
    bool needCast;
    bool thisPtr;
    bool opDestType;
+   uint needTemplateCast;
 
    void Clear()
    {
@@ -678,6 +686,7 @@ public:
       needCast = false;
       thisPtr = false;
       opDestType = false;
+      needTemplateCast = 0;
    }
 };
 
@@ -755,6 +764,7 @@ public:
       OldList * list;
    };
    bool isConstant;
+   Identifier id;
 };
 
 public class InitDeclarator : struct
@@ -1014,7 +1024,6 @@ public:
    Symbol symbol;
    Location blockStart;
    Location nameLoc;
-   int endid;
    AccessMode declMode;
    bool deleteWatchable;
 };
@@ -1085,6 +1094,14 @@ public:
    void * object;
 };
 
+// An 'edge from' is a 'dependency on'
+class TopoEdge : struct
+{
+   public LinkElement<TopoEdge> in, out;
+   External from, to;
+   bool breakable;
+};
+
 public enum ExternalType { functionExternal, declarationExternal, classExternal, importExternal, nameSpaceExternal, dbtableExternal };
 
 public class External : struct
@@ -1104,6 +1121,109 @@ public:
       DBTableDef table;
    };
    ImportType importType;
+
+   // For the TopoSort
+   External fwdDecl;
+   LinkList<TopoEdge, link = out> outgoing { };
+   LinkList<TopoEdge, link = in> incoming { };
+   int nonBreakableIncoming;
+
+   void CreateUniqueEdge(External from, bool soft)
+   {
+      for(i : from.outgoing; i.to == this)
+      {
+         if(i.breakable && !soft)
+         {
+#ifdef _DEBUG
+            if(from == this)
+               PrintLn("bug: self-dependency");
+#endif
+            i.breakable = false;
+            nonBreakableIncoming++;
+         }
+         return;
+      }
+      CreateEdge(from, soft);
+   }
+
+   void CreateEdge(External from, bool soft)
+   {
+      TopoEdge e { from = from, to = this, breakable = soft };
+
+#ifdef _DEBUG
+      if(from == this && !soft)
+         PrintLn("bug: self-dependency");
+
+      /*for(i : from.outgoing)
+      {
+         if(i.to == this)
+            PrintLn("Warning: adding a duplicate edge");
+      }*/
+#endif
+
+      from.outgoing.Add(e);
+      incoming.Add(e);
+      if(!soft)
+         nonBreakableIncoming++;
+   }
+
+   External ForwardDeclare()
+   {
+      External f = null;
+      Context tmpContext = curContext;
+
+      switch(type)
+      {
+         case declarationExternal:
+         {
+            if(declaration.type == initDeclaration)
+            {
+               OldList * specs = declaration.specifiers;
+               if(specs)
+               {
+                  Specifier s;
+                  for(s = specs->first; s; s = s.next)
+                  {
+                     if(s.type == structSpecifier || s.type == unionSpecifier)
+                        break;
+                  }
+                  if(s)
+                  {
+                     curContext = null;
+                     f = MkExternalDeclaration(MkDeclaration(MkListOne(MkStructOrUnion(s.type, CopyIdentifier(s.id), null)), null));
+                     curContext = tmpContext;
+                  }
+               }
+            }
+            break;
+         }
+         case functionExternal:
+         {
+            curContext = null;
+            f = MkExternalDeclaration(MkDeclaration(CopyList(function.specifiers, CopySpecifier), MkListOne(MkInitDeclarator(CopyDeclarator(function.declarator), null))));
+            curContext = tmpContext;
+            f.symbol = symbol;
+
+            DeclareTypeForwardDeclare(f, symbol.type, false, false);
+            break;
+         }
+      }
+
+      /*
+      for(i : m.protoDepsExternal)
+      {
+         // If the edge is already added, don't bother
+         if(i.incoming.count)
+            CreateEdge(f, i.fwdDecl ? i.fwdDecl : i, i.fwdDecl ? false : true);
+      }
+      */
+
+      fwdDecl = f;
+
+      if(!f)
+         PrintLn("warning: unhandled forward declaration requested");
+      return f;
+   }
 };
 
 public class Context : struct
@@ -1138,7 +1258,7 @@ public:
       Property _property;
       Class registered;
    };
-   int id, idCode;
+   bool notYetDeclared;
    union
    {
       struct
@@ -1183,6 +1303,7 @@ public:
    Context ctx;
    int isIterator;
    Expression propCategory;
+   bool mustRegister;   // Must register the class within the RegisterClass (also used to check whether this class is declared in this module)
 };
 
 // For the .imp file:
@@ -1288,12 +1409,13 @@ public:
    uint size;
    char * name;
    char * typeName;
+   Class thisClassFrom;
 
    ClassObjectType classObjectType;
    int alignment;
    uint offset;
    int bitFieldCount;
-   int count;
+   int count;  // This is used to avoid outputting warnings when non-zero
 
    bool isSigned:1;
    bool constant:1;
@@ -1308,10 +1430,14 @@ public:
    bool attrStdcall:1;
    bool declaredWithStruct:1;
    bool typedByReference:1;      // Originally typed by reference, regardless of class type
+   bool casted:1;
+   bool pointerAlignment:1; // true if the alignment is the pointer size
+   bool isLong:1;    // true if this is truly a long set as a int/int64 (need to improve long support)
+   // bool wasThisClass:1;
    // TODO: Add _Complex & _Imaginary support
    // bool complex:1, imaginary:1;
 
-   char * OnGetString(char * tempString, void * fieldData, bool * needClass)
+   const char * OnGetString(char * tempString, void * fieldData, bool * needClass)
    {
       Type type = (Type)this;
       tempString[0] = '\0';
@@ -1324,6 +1450,98 @@ public:
    {
 
    }
+
+   property bool specConst
+   {
+      get
+      {
+         Type t = this;
+         while((t.kind == pointerType || t.kind == arrayType) && t.type) t = t.type;
+         return t.constant;
+      }
+   }
+
+   // Used for generating calls to eClass_AddDataMember (differs slightly from 'isPointerType' below), meant to return true where ComputeTypeSize returns targetBits / 8
+   property bool isPointerTypeSize
+   {
+      get
+      {
+         bool result = false;
+         if(this)
+         {
+            switch(kind)
+            {
+               case classType:
+               {
+                  Class _class = this._class ? this._class.registered : null;
+                  if(!_class || (_class.type != structClass && _class.type != unitClass && _class.type != enumClass && _class.type != bitClass))
+                     result = true;
+                  break;
+               }
+               case pointerType:
+               case subClassType:
+               case thisClassType:
+               case intPtrType:
+               case intSizeType:
+                  result = true;
+                  break;
+               case templateType:
+               {
+                  TemplateParameter param = templateParameter;
+                  Type baseType = ProcessTemplateParameterType(param);
+                  if(baseType)
+                     result = baseType.isPointerTypeSize;
+                  break;
+               }
+            }
+         }
+         return result;
+      }
+   }
+
+   property bool isPointerType
+   {
+      get
+      {
+         if(this)
+         {
+            if(kind == pointerType || kind == methodType || kind == functionType || kind == arrayType || kind == subClassType)
+               return true;
+            else if(kind == classType)
+            {
+               if(_class && _class.registered)
+               {
+                  Class c = _class.registered;
+                  if(c.type == bitClass || c.type == unitClass || c.type == enumClass || c.type == systemClass)
+                     return false;
+                  else if(c.type == structClass && !byReference)
+                     return false;
+               }
+               return true;
+            }
+            else if(kind == templateType)
+            {
+               if(passAsTemplate) return false;
+               if(templateParameter)
+               {
+                  if(templateParameter.dataType)
+                  {
+                     Specifier spec = templateParameter.dataType.specifiers ? templateParameter.dataType.specifiers->first : null;
+                     if(templateParameter.dataType.decl && templateParameter.dataType.decl.type == pointerDeclarator)
+                        return true;
+                     if(spec && spec.type == nameSpecifier && strcmp(spec.name, "uint64"))
+                        return true;
+                  }
+                  if(templateParameter.dataTypeString)
+                     return true;
+               }
+            }
+            else
+               return false;
+         }
+         return false;
+      }
+   }
 };
 
 public struct Operand
@@ -1415,7 +1633,7 @@ define MAX_INCLUDE_DEPTH = 30;
 
 #include <stdarg.h>
 
-void Compiler_Error(char * format, ...)
+void Compiler_Error(const char * format, ...)
 {
    if(inCompiler)
    {
@@ -1434,7 +1652,7 @@ void Compiler_Error(char * format, ...)
             GetWorkingDir(string, sizeof(string));
             PathCat(string, sourceFile);
          }
-         printf(string);
+         printf("%s", string);
 
          /*
          yylloc.start.col = yylloc.end.col = 1;
@@ -1443,7 +1661,7 @@ void Compiler_Error(char * format, ...)
          */
 #ifdef _DEBUG
          if(!yylloc.start.line)
-            printf("");
+            printf("no line");
 #endif
 
          //printf("(%d, %d) : error: ", yylloc.start.line, yylloc.start.charPos);
@@ -1454,6 +1672,7 @@ void Compiler_Error(char * format, ...)
          string[sizeof(string)-1] = 0;
          va_end(args);
          fputs(string, stdout);
+         fflush(stdout);
          __thisModule.application.exitCode = 1;
       }
       else
@@ -1467,7 +1686,7 @@ void Compiler_Error(char * format, ...)
 int numWarnings;
 public int GetNumWarnings() { return numWarnings; }
 
-void Compiler_Warning(char * format, ...)
+void Compiler_Warning(const char * format, ...)
 {
    if(inCompiler)
    {
@@ -1491,7 +1710,7 @@ void Compiler_Warning(char * format, ...)
       GetLastDirectory(string, fileName);
       if(!strcmp(fileName, "intrin-impl.h")) return;
 
-      printf(string);
+      printf("%s", string);
 
       //printf("(%d, %d) : warning: ", yylloc.start.line, yylloc.start.charPos);
       printf($":%d:%d: warning: ", yylloc.start.line, yylloc.start.charPos);
@@ -1501,6 +1720,7 @@ void Compiler_Warning(char * format, ...)
       string[sizeof(string)-1] = 0;
       va_end(args);
       fputs(string, stdout);
+      fflush(stdout);
       numWarnings++;
    }
 }