changeset 707:efa5fcb9aa14

Added semantic code related to enums. Added member symbol to EnumMemberDeclaration. Added genAnonEnumID() to IdTable. Added class EnumMember. Wrote code for SemanticPass2.visit(EnumDeclaration). Revised code in SemanticPass1.visit(EnumDeclaration).
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Tue, 29 Jan 2008 01:07:39 +0100
parents 684ec5932b2e
children 3a4c7d444467
files trunk/src/dil/ast/Declarations.d trunk/src/dil/lexer/IdTable.d trunk/src/dil/semantic/Pass1.d trunk/src/dil/semantic/Pass2.d trunk/src/dil/semantic/Symbol.d trunk/src/dil/semantic/Symbols.d
diffstat 6 files changed, 106 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/ast/Declarations.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/ast/Declarations.d	Tue Jan 29 01:07:39 2008 +0100
@@ -192,6 +192,8 @@
     this.name = name;
     this.value = value;
   }
+
+  EnumMember symbol;
 }
 
 class TemplateDeclaration : Declaration
--- a/trunk/src/dil/lexer/IdTable.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/lexer/IdTable.d	Tue Jan 29 01:07:39 2008 +0100
@@ -139,6 +139,11 @@
     while (x /= 10)
     return Identifier(str, TOK.Identifier);
   }
+
+  Identifier* genAnonEnumID()
+  {
+    return genAnonymousID("__anonenum");
+  }
 }
 
 unittest
--- a/trunk/src/dil/semantic/Pass1.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/semantic/Pass1.d	Tue Jan 29 01:07:39 2008 +0100
@@ -72,41 +72,53 @@
   }
 
   /// Insert a symbol into the current scope.
-  void insert(Symbol sym, Identifier* ident)
+  void insert(Symbol sym, Identifier* name)
   {
-    auto sym2 = scop.symbol.lookup(ident);
+    auto sym2 = scop.symbol.lookup(name);
     if (sym2)
-      reportSymbolConflict(sym, sym2, ident);
+      reportSymbolConflict(sym, sym2, name);
     else
-      scop.symbol.insert(sym, ident);
+      scop.symbol.insert(sym, name);
     // Set the current scope symbol as the parent.
     sym.parent = scop.symbol;
   }
 
+  /// Insert a symbol into scopeSym.
+  void insert(Symbol symbol, ScopeSymbol scopeSym)
+  {
+    auto symX = scopeSym.lookup(symbol.name);
+    if (symX)
+      reportSymbolConflict(symbol, symX, symbol.name);
+    else
+      scopeSym.insert(symbol, symbol.name);
+    // Set the current scope symbol as the parent.
+    symbol.parent = scopeSym;
+  }
+
   /// Insert a symbol, overloading on the name, into the current scope.
-  void insertOverload(Symbol sym, Identifier* ident)
+  void insertOverload(Symbol sym, Identifier* name)
   {
-    auto sym2 = scop.symbol.lookup(ident);
+    auto sym2 = scop.symbol.lookup(name);
     if (sym2)
     {
       if (sym2.isOverloadSet)
         (cast(OverloadSet)cast(void*)sym2).add(sym);
       else
-        reportSymbolConflict(sym, sym2, ident);
+        reportSymbolConflict(sym, sym2, name);
     }
     else
       // Create a new overload set.
-      scop.symbol.insert(new OverloadSet(ident, sym.node), ident);
+      scop.symbol.insert(new OverloadSet(name, sym.node), name);
     // Set the current scope symbol as the parent.
     sym.parent = scop.symbol;
   }
 
   /// Report error: new symbol s1 conflicts with existing symbol s2.
-  void reportSymbolConflict(Symbol s1, Symbol s2, Identifier* ident)
+  void reportSymbolConflict(Symbol s1, Symbol s2, Identifier* name)
   {
     auto loc = s2.node.begin.getErrorLocation();
     auto locString = Format("{}({},{})", loc.filePath, loc.lineNum, loc.colNum);
-    error(s1.node.begin, MSG.DeclConflictsWithDecl, ident.str, locString);
+    error(s1.node.begin, MSG.DeclConflictsWithDecl, name.str, locString);
   }
 
   void error(Token* token, char[] formatMsg, ...)
@@ -186,24 +198,30 @@
   {
     // Create the symbol.
     d.symbol = new Enum(d.name, d);
-    if (d.name)
-    { // Declare named enum.
-      insert(d.symbol, d.name);
-      enterScope(d.symbol);
-    }
+    auto isAnonymous = d.name is null;
+    if (isAnonymous)
+      d.symbol.name = IdTable.genAnonEnumID();
+    insert(d.symbol, d.name);
+    auto parentScopeSymbol = scop.symbol;
+    enterScope(d.symbol);
     // Declare members.
     foreach (member; d.members)
     {
-      auto variable = new Variable(member.name, protection, storageClass, linkageType, member);
-      insert(variable, variable.name);
+      visitD(member);
+      if (isAnonymous) // Also insert into parent scope if enum is anonymous.
+        insert(member.symbol, parentScopeSymbol);
+      member.symbol.parent = d.symbol;
     }
-    if (d.name)
-      exitScope();
+    exitScope();
     return d;
   }
 
-  D visit(EnumMemberDeclaration)
-  { return null; }
+  D visit(EnumMemberDeclaration d)
+  {
+    d.symbol = new EnumMember(d.name, protection, storageClass, linkageType, d);
+    insert(d.symbol, d.symbol.name);
+    return d;
+  }
 
   D visit(ClassDeclaration d)
   {
--- a/trunk/src/dil/semantic/Pass2.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/semantic/Pass2.d	Tue Jan 29 01:07:39 2008 +0100
@@ -68,6 +68,11 @@
   private alias Statement S;
   private alias TypeNode T;
 
+  /// The scope symbol to use in identifier or template instance expressions.
+  /// E.g.: object.method(); // After 'object' has been visited, dotIdScope is
+  ///                        // set, and 'method' will be looked up there.
+  ScopeSymbol dotIdScope;
+
 override
 {
   D visit(CompoundDeclaration d)
@@ -75,6 +80,31 @@
     return super.visit(d);
   }
 
+  D visit(EnumDeclaration d)
+  {
+    Type type = Types.Int; // Default to int.
+    if (d.baseType)
+      type = visitT(d.baseType).type;
+    d.symbol.type = new TypeEnum(d.symbol, type);
+    enterScope(d.symbol);
+    foreach (member; d.members)
+    {
+      Expression finalValue;
+      if (member.value)
+      {
+        member.value = visitE(member.value);
+        finalValue = Interpreter.interpret(member.value, modul.infoMan, scop);
+        if (finalValue is Interpreter.NAR)
+          continue;
+      }
+      //else
+        // TODO: increment a number variable and assign that to value.
+      member.symbol.value = finalValue;
+    }
+    exitScope();
+    return d;
+  }
+
   D visit(MixinDeclaration md)
   {
     if (md.decls)
--- a/trunk/src/dil/semantic/Symbol.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/semantic/Symbol.d	Tue Jan 29 01:07:39 2008 +0100
@@ -17,6 +17,7 @@
   Struct,
   Union,
   Enum,
+  EnumMember,
   Template,
   Variable,
   Function,
@@ -45,20 +46,21 @@
   }
 
   // A template macro for building isXYZ() methods.
-  private template is_(char[] kind)
+  private template isX(char[] kind)
   {
-    const char[] is_ = `bool is`~kind~`(){ return sid == SYM.`~kind~`; }`;
+    const char[] isX = `bool is`~kind~`(){ return sid == SYM.`~kind~`; }`;
   }
-  mixin(is_!("Module"));
-  mixin(is_!("Class"));
-  mixin(is_!("Interface"));
-  mixin(is_!("Struct"));
-  mixin(is_!("Union"));
-  mixin(is_!("Enum"));
-  mixin(is_!("Template"));
-  mixin(is_!("Variable"));
-  mixin(is_!("Function"));
-  mixin(is_!("Alias"));
-  mixin(is_!("OverloadSet"));
-//   mixin(is_!("Type"));
+  mixin(isX!("Module"));
+  mixin(isX!("Class"));
+  mixin(isX!("Interface"));
+  mixin(isX!("Struct"));
+  mixin(isX!("Union"));
+  mixin(isX!("Enum"));
+  mixin(isX!("EnumMember"));
+  mixin(isX!("Template"));
+  mixin(isX!("Variable"));
+  mixin(isX!("Function"));
+  mixin(isX!("Alias"));
+  mixin(isX!("OverloadSet"));
+//   mixin(isX!("Type"));
 }
--- a/trunk/src/dil/semantic/Symbols.d	Mon Jan 28 21:39:08 2008 +0100
+++ b/trunk/src/dil/semantic/Symbols.d	Tue Jan 29 01:07:39 2008 +0100
@@ -4,6 +4,7 @@
 +/
 module dil.semantic.Symbols;
 
+import dil.ast.Expression;
 import dil.semantic.Symbol;
 import dil.semantic.SymbolTable;
 import dil.semantic.Types;
@@ -136,6 +137,7 @@
   LinkageType linkType; /// The linkage type.
 
   Type type; /// The type of this variable.
+  Expression value; /// The value of this variable.
 
   this(Identifier* name,
        Protection prot, StorageClass stc, LinkageType linkType,
@@ -143,11 +145,23 @@
   {
     super(SYM.Variable, name, variableNode);
 
+    this.prot = prot;
     this.stc = stc;
     this.linkType = linkType;
   }
 }
 
+class EnumMember : Variable
+{
+  this(Identifier* name,
+       Protection prot, StorageClass stc, LinkageType linkType,
+       Node enumMemberNode)
+  {
+    super(name, prot, stc, linkType, enumMemberNode);
+    this.sid = SYM.EnumMember;
+  }
+}
+
 class Alias : Symbol
 {
   this(Identifier* name, Node aliasNode)