changeset 635:b2fc028d8b55

Added class Visitor. Moved enums NodeCategory and NodeKind to new module dil.ast.NodesEnum. Commented out some version(D2) statements. Added new module dil.semantic.Pass1.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 13 Jan 2008 21:53:01 +0100
parents 14e99ce74d06
children 15a0f37caabe
files trunk/src/dil/ast/Expressions.d trunk/src/dil/ast/Node.d trunk/src/dil/ast/NodesEnum.d trunk/src/dil/ast/Parameters.d trunk/src/dil/ast/Statements.d trunk/src/dil/ast/Types.d trunk/src/dil/ast/Visitor.d trunk/src/dil/semantic/Pass1.d trunk/src/main.d
diffstat 9 files changed, 475 insertions(+), 223 deletions(-) [+]
line wrap: on
line diff
--- a/trunk/src/dil/ast/Expressions.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/dil/ast/Expressions.d	Sun Jan 13 21:53:01 2008 +0100
@@ -1056,8 +1056,8 @@
   }
 }
 
-version(D2)
-{
+// version(D2)
+// {
 class TraitsExpression : Expression
 {
   Identifier* ident;
@@ -1070,7 +1070,7 @@
     this.targs = targs;
   }
 }
-}
+// }
 
 class VoidInitializer : Expression
 {
--- a/trunk/src/dil/ast/Node.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/dil/ast/Node.d	Sun Jan 13 21:53:01 2008 +0100
@@ -7,216 +7,7 @@
 import common;
 
 public import dil.lexer.Token;
-
-enum NodeCategory
-{
-  Declaration,
-  Statement,
-  Expression,
-  Type,
-  Other
-}
-
-enum NodeKind
-{
-  // Declarations:
-  Declarations,
-  EmptyDeclaration,
-  IllegalDeclaration,
-  ModuleDeclaration,
-  ImportDeclaration,
-  AliasDeclaration,
-  TypedefDeclaration,
-  EnumDeclaration,
-  ClassDeclaration,
-  InterfaceDeclaration,
-  StructDeclaration,
-  UnionDeclaration,
-  ConstructorDeclaration,
-  StaticConstructorDeclaration,
-  DestructorDeclaration,
-  StaticDestructorDeclaration,
-  FunctionDeclaration,
-  VariableDeclaration,
-  InvariantDeclaration,
-  UnittestDeclaration,
-  DebugDeclaration,
-  VersionDeclaration,
-  StaticIfDeclaration,
-  StaticAssertDeclaration,
-  TemplateDeclaration,
-  NewDeclaration,
-  DeleteDeclaration,
-  AttributeDeclaration,
-  ProtectionDeclaration,
-  StorageClassDeclaration,
-  LinkageDeclaration,
-  AlignDeclaration,
-  PragmaDeclaration,
-  MixinDeclaration,
-
-  // Statements:
-  Statements,
-  IllegalStatement,
-  EmptyStatement,
-  ScopeStatement,
-  LabeledStatement,
-  ExpressionStatement,
-  DeclarationStatement,
-  IfStatement,
-  ConditionalStatement,
-  WhileStatement,
-  DoWhileStatement,
-  ForStatement,
-  ForeachStatement,
-  ForeachRangeStatement, // D2.0
-  SwitchStatement,
-  CaseStatement,
-  DefaultStatement,
-  ContinueStatement,
-  BreakStatement,
-  ReturnStatement,
-  GotoStatement,
-  WithStatement,
-  SynchronizedStatement,
-  TryStatement,
-  CatchBody,
-  FinallyBody,
-  ScopeGuardStatement,
-  ThrowStatement,
-  VolatileStatement,
-  AsmStatement,
-  AsmInstruction,
-  AsmAlignStatement,
-  IllegalAsmInstruction,
-  PragmaStatement,
-  MixinStatement,
-  StaticIfStatement,
-  StaticAssertStatement,
-  DebugStatement,
-  VersionStatement,
-
-  // Expressions:
-  EmptyExpression,
-  BinaryExpression,
-  CondExpression,
-  CommaExpression,
-  OrOrExpression,
-  AndAndExpression,
-  OrExpression,
-  XorExpression,
-  AndExpression,
-  CmpExpression,
-  EqualExpression,
-  IdentityExpression,
-  RelExpression,
-  InExpression,
-  LShiftExpression,
-  RShiftExpression,
-  URShiftExpression,
-  PlusExpression,
-  MinusExpression,
-  CatExpression,
-  MulExpression,
-  DivExpression,
-  ModExpression,
-  AssignExpression,
-  LShiftAssignExpression,
-  RShiftAssignExpression,
-  URShiftAssignExpression,
-  OrAssignExpression,
-  AndAssignExpression,
-  PlusAssignExpression,
-  MinusAssignExpression,
-  DivAssignExpression,
-  MulAssignExpression,
-  ModAssignExpression,
-  XorAssignExpression,
-  CatAssignExpression,
-  UnaryExpression,
-  AddressExpression,
-  PreIncrExpression,
-  PreDecrExpression,
-  PostIncrExpression,
-  PostDecrExpression,
-  DerefExpression,
-  SignExpression,
-  NotExpression,
-  CompExpression,
-  CallExpression,
-  NewExpression,
-  NewAnonClassExpression,
-  DeleteExpression,
-  CastExpression,
-  IndexExpression,
-  SliceExpression,
-  ModuleScopeExpression,
-  IdentifierExpression,
-  SpecialTokenExpression,
-  DotExpression,
-  TemplateInstanceExpression,
-  ThisExpression,
-  SuperExpression,
-  NullExpression,
-  DollarExpression,
-  BoolExpression,
-  IntExpression,
-  RealExpression,
-  ComplexExpression,
-  CharExpression,
-  StringExpression,
-  ArrayLiteralExpression,
-  AArrayLiteralExpression,
-  AssertExpression,
-  MixinExpression,
-  ImportExpression,
-  TypeofExpression,
-  TypeDotIdExpression,
-  TypeidExpression,
-  IsExpression,
-  FunctionLiteralExpression,
-  TraitsExpression, // D2.0
-  VoidInitializer,
-  ArrayInitializer,
-  StructInitializer,
-  AsmTypeExpression,
-  AsmOffsetExpression,
-  AsmSegExpression,
-  AsmPostBracketExpression,
-  AsmBracketExpression,
-  AsmLocalSizeExpression,
-  AsmRegisterExpression,
-
-  // Types:
-  UndefinedType,
-  IntegralType,
-  QualifiedType,
-  ModuleScopeType,
-  IdentifierType,
-  TypeofType,
-  TemplateInstanceType,
-  PointerType,
-  ArrayType,
-  FunctionType,
-  DelegateType,
-  CFuncPointerType,
-  ConstType, // D2.0
-  InvariantType, // D2.0
-
-  // Other:
-  FunctionBody,
-  Parameter,
-  Parameters,
-  BaseClass,
-  TemplateAliasParameter,
-  TemplateTypeParameter,
-  TemplateThisParameter, // D2.0
-  TemplateValueParameter,
-  TemplateTupleParameter,
-  TemplateParameters,
-  TemplateArguments,
-  EnumMember,
-}
+public import dil.ast.NodesEnum;
 
 /// This string is mixed into the constructor of a class that inherits from Node.
 const string set_kind = `this.kind = mixin("NodeKind." ~ typeof(this).stringof);`;
@@ -287,6 +78,13 @@
     children is null || addChildren(children);
   }
 
+  Class iS(Class)()
+  {
+    if (kind == mixin("NodeKind." ~ typeof(Class).stringof))
+      return cast(Class)cast(void*)this;
+    return null;
+  }
+
   static bool isDoxygenComment(Token* token)
   { // Doxygen: '/+!' '/*!' '//!'
     return token.type == TOK.Comment && token.start[2] == '!';
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/ast/NodesEnum.d	Sun Jan 13 21:53:01 2008 +0100
@@ -0,0 +1,232 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.ast.NodesEnum;
+
+enum NodeCategory
+{
+  Declaration,
+  Statement,
+  Expression,
+  Type,
+  Other
+}
+
+/// Array of class names that inherit from Node.
+static const char[][] classNames = [
+  // Declarations:
+  "Declarations",
+  "EmptyDeclaration",
+  "IllegalDeclaration",
+  "ModuleDeclaration",
+  "ImportDeclaration",
+  "AliasDeclaration",
+  "TypedefDeclaration",
+  "EnumDeclaration",
+  "ClassDeclaration",
+  "InterfaceDeclaration",
+  "StructDeclaration",
+  "UnionDeclaration",
+  "ConstructorDeclaration",
+  "StaticConstructorDeclaration",
+  "DestructorDeclaration",
+  "StaticDestructorDeclaration",
+  "FunctionDeclaration",
+  "VariableDeclaration",
+  "InvariantDeclaration",
+  "UnittestDeclaration",
+  "DebugDeclaration",
+  "VersionDeclaration",
+  "StaticIfDeclaration",
+  "StaticAssertDeclaration",
+  "TemplateDeclaration",
+  "NewDeclaration",
+  "DeleteDeclaration",
+  "AttributeDeclaration",
+  "ProtectionDeclaration",
+  "StorageClassDeclaration",
+  "LinkageDeclaration",
+  "AlignDeclaration",
+  "PragmaDeclaration",
+  "MixinDeclaration",
+
+  // Statements:
+  "Statements",
+  "IllegalStatement",
+  "EmptyStatement",
+  "ScopeStatement",
+  "LabeledStatement",
+  "ExpressionStatement",
+  "DeclarationStatement",
+  "IfStatement",
+//   "ConditionalStatement",
+  "WhileStatement",
+  "DoWhileStatement",
+  "ForStatement",
+  "ForeachStatement",
+  "ForeachRangeStatement", // D2.0
+  "SwitchStatement",
+  "CaseStatement",
+  "DefaultStatement",
+  "ContinueStatement",
+  "BreakStatement",
+  "ReturnStatement",
+  "GotoStatement",
+  "WithStatement",
+  "SynchronizedStatement",
+  "TryStatement",
+  "CatchBody",
+  "FinallyBody",
+  "ScopeGuardStatement",
+  "ThrowStatement",
+  "VolatileStatement",
+  "AsmStatement",
+  "AsmInstruction",
+  "AsmAlignStatement",
+  "IllegalAsmInstruction",
+  "PragmaStatement",
+  "MixinStatement",
+  "StaticIfStatement",
+  "StaticAssertStatement",
+  "DebugStatement",
+  "VersionStatement",
+
+  // Expressions:
+  "EmptyExpression",
+  "BinaryExpression",
+  "CondExpression",
+  "CommaExpression",
+  "OrOrExpression",
+  "AndAndExpression",
+  "OrExpression",
+  "XorExpression",
+  "AndExpression",
+  "CmpExpression",
+  "EqualExpression",
+  "IdentityExpression",
+  "RelExpression",
+  "InExpression",
+  "LShiftExpression",
+  "RShiftExpression",
+  "URShiftExpression",
+  "PlusExpression",
+  "MinusExpression",
+  "CatExpression",
+  "MulExpression",
+  "DivExpression",
+  "ModExpression",
+  "AssignExpression",
+  "LShiftAssignExpression",
+  "RShiftAssignExpression",
+  "URShiftAssignExpression",
+  "OrAssignExpression",
+  "AndAssignExpression",
+  "PlusAssignExpression",
+  "MinusAssignExpression",
+  "DivAssignExpression",
+  "MulAssignExpression",
+  "ModAssignExpression",
+  "XorAssignExpression",
+  "CatAssignExpression",
+  "UnaryExpression",
+  "AddressExpression",
+  "PreIncrExpression",
+  "PreDecrExpression",
+  "PostIncrExpression",
+  "PostDecrExpression",
+  "DerefExpression",
+  "SignExpression",
+  "NotExpression",
+  "CompExpression",
+  "CallExpression",
+  "NewExpression",
+  "NewAnonClassExpression",
+  "DeleteExpression",
+  "CastExpression",
+  "IndexExpression",
+  "SliceExpression",
+  "ModuleScopeExpression",
+  "IdentifierExpression",
+  "SpecialTokenExpression",
+  "DotExpression",
+  "TemplateInstanceExpression",
+  "ThisExpression",
+  "SuperExpression",
+  "NullExpression",
+  "DollarExpression",
+  "BoolExpression",
+  "IntExpression",
+  "RealExpression",
+  "ComplexExpression",
+  "CharExpression",
+  "StringExpression",
+  "ArrayLiteralExpression",
+  "AArrayLiteralExpression",
+  "AssertExpression",
+  "MixinExpression",
+  "ImportExpression",
+  "TypeofExpression",
+  "TypeDotIdExpression",
+  "TypeidExpression",
+  "IsExpression",
+  "FunctionLiteralExpression",
+  "TraitsExpression", // D2.0
+  "VoidInitializer",
+  "ArrayInitializer",
+  "StructInitializer",
+  "AsmTypeExpression",
+  "AsmOffsetExpression",
+  "AsmSegExpression",
+  "AsmPostBracketExpression",
+  "AsmBracketExpression",
+  "AsmLocalSizeExpression",
+  "AsmRegisterExpression",
+
+  // Types:
+  "UndefinedType",
+  "IntegralType",
+  "QualifiedType",
+  "ModuleScopeType",
+  "IdentifierType",
+  "TypeofType",
+  "TemplateInstanceType",
+  "PointerType",
+  "ArrayType",
+  "FunctionType",
+  "DelegateType",
+  "CFuncPointerType",
+  "ConstType", // D2.0
+  "InvariantType", // D2.0
+
+  // Other:
+  "FunctionBody",
+  "Parameter",
+  "Parameters",
+  "BaseClass",
+  "TemplateAliasParameter",
+  "TemplateTypeParameter",
+  "TemplateThisParameter", // D2.0
+  "TemplateValueParameter",
+  "TemplateTupleParameter",
+  "TemplateParameters",
+  "TemplateArguments",
+  "EnumMember",
+];
+
+char[] generateNodeKindMembers()
+{
+  char[] text;
+  foreach (className; classNames)
+    text ~= className ~ ",";
+  return text;
+}
+// pragma(msg, generateNodeKindMembers());
+
+// enum NodeKind;
+mixin(
+  "enum NodeKind"
+  "{"
+    ~ generateNodeKindMembers ~
+  "}"
+);
--- a/trunk/src/dil/ast/Parameters.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/dil/ast/Parameters.d	Sun Jan 13 21:53:01 2008 +0100
@@ -114,8 +114,8 @@
   }
 }
 
-version(D2)
-{
+// version(D2)
+// {
 class TemplateThisParameter : TemplateParameter
 {
   TypeNode specType, defType;
@@ -130,7 +130,7 @@
     this.defType = defType;
   }
 }
-}
+// }
 
 class TemplateValueParameter : TemplateParameter
 {
--- a/trunk/src/dil/ast/Statements.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/dil/ast/Statements.d	Sun Jan 13 21:53:01 2008 +0100
@@ -212,8 +212,8 @@
   }
 }
 
-version(D2)
-{
+// version(D2)
+// {
 class ForeachRangeStatement : Statement
 {
   TOK tok;
@@ -233,7 +233,7 @@
     this.forBody = forBody;
   }
 }
-}
+// }
 
 class SwitchStatement : Statement
 {
--- a/trunk/src/dil/ast/Types.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/dil/ast/Types.d	Sun Jan 13 21:53:01 2008 +0100
@@ -241,8 +241,8 @@
   }
 }
 
-version(D2)
-{
+// version(D2)
+// {
 class ConstType : TypeNode
 {
   this(TypeNode t)
@@ -262,4 +262,4 @@
     mixin(set_kind);
   }
 }
-} // version(D2)
+// } // version(D2)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/ast/Visitor.d	Sun Jan 13 21:53:01 2008 +0100
@@ -0,0 +1,128 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.ast.Visitor;
+
+import dil.ast.Node;
+import dil.ast.Declarations,
+       dil.ast.Expressions,
+       dil.ast.Statements,
+       dil.ast.Types,
+       dil.ast.BaseClass,
+       dil.ast.Parameters;
+
+/++
+  Generate abstract visit methods.
+  E.g.:
+    Declaration visit(ClassDeclaration);
+    Expression visit(CommaExpression);
++/
+char[] generateAbstractVisitMethods()
+{
+  char[] text;
+  foreach (className; classNames)
+  {
+    text ~= "returnType!(\""~className~"\")" ~ " visit(" ~ className ~ ");\n";
+  }
+  return text;
+}
+// pragma(msg, generateAbstractVisitMethods());
+
+/// Gets the appropriate return type for the provided class.
+template returnType(char[] className)
+{
+  static if (is(typeof(mixin(className)) : Declaration))
+    alias Declaration returnType;
+  else
+  static if (is(typeof(mixin(className)) : Statement))
+    alias Statement returnType;
+  else
+  static if (is(typeof(mixin(className)) : Expression))
+    alias Expression returnType;
+  else
+  static if (is(typeof(mixin(className)) : TypeNode))
+    alias TypeNode returnType;
+  else
+    alias Node returnType;
+}
+
+/++
+  Generate functions which do the second dispatch.
+  E.g.:
+    Expression visitCommaExpression(Visitor visitor, CommaExpression c)
+    { visitor.visit(c); }
+
+  The equivalent in the traditional Visitor pattern would be:
+    class CommaExpression : Expression
+    {
+      void accept(Visitor visitor)
+      { visitor.visit(this); }
+    }
++/
+char[] generateDispatchFunctions()
+{
+  char[] text;
+  foreach (className; classNames)
+    text ~= "returnType!(\""~className~"\") visit"~className~"(Visitor visitor, "~className~" c)\n"
+            "{ return visitor.visit(c); }\n";
+  return text;
+}
+// pragma(msg, generateDispatchFunctions());
+
+/++
+  The vtable holds a list of function pointers to the dispatch functions.
++/
+char[] generateVTable()
+{
+  char[] text = "[";
+  foreach (className; classNames)
+    text ~= "cast(void*)&visit"~className~",\n";
+  return text[0..$-2]~"]"; // slice away last ",\n"
+}
+// pragma(msg, generateVTable());
+
+abstract class Visitor
+{
+  abstract
+    mixin(generateAbstractVisitMethods());
+
+  static
+    mixin(generateDispatchFunctions());
+
+  /// The dispatch table.
+  static const void*[] dispatch_vtable = mixin(generateVTable());
+  static assert(dispatch_vtable.length == classNames.length, "vtable length doesn't match number of classes");
+
+  // Returns the dispatch function for n.
+  T function(Visitor,T) getDispatchFunction(T)(T n)
+  {
+    return cast(T function(Visitor,T))dispatch_vtable[n.kind];
+  }
+
+  Declaration visitD(Declaration n)
+  {
+    // Do first dispatch. Second dispatch is done in the called function.
+    return getDispatchFunction(n)(this, n);
+  }
+
+  Statement visitS(Statement n)
+  {
+    return getDispatchFunction(n)(this, n);
+  }
+
+  Expression visitE(Expression n)
+  {
+    return getDispatchFunction(n)(this, n);
+  }
+
+  TypeNode visitT(TypeNode n)
+  {
+    return getDispatchFunction(n)(this, n);
+  }
+
+  Node visitN(Node n)
+  {
+    return getDispatchFunction(n)(this, n);
+  }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/trunk/src/dil/semantic/Pass1.d	Sun Jan 13 21:53:01 2008 +0100
@@ -0,0 +1,92 @@
+/++
+  Author: Aziz Köksal
+  License: GPL3
++/
+module dil.semantic.Pass1;
+
+import dil.ast.Visitor;
+import dil.ast.Node,
+       dil.ast.Declarations,
+       dil.ast.Expressions,
+       dil.ast.Statements,
+       dil.ast.Types,
+       dil.ast.BaseClass,
+       dil.ast.Parameters;
+
+import dil.semantic.Symbol,
+       dil.semantic.Symbols,
+       dil.semantic.Scope;
+
+class SemanticPass1 : Visitor
+{
+  Scope scop;
+
+  /+Scope enterScope(Symbol s)
+  {
+    return null;
+  }+/
+
+override
+{
+  Declaration visit(ClassDeclaration c)
+  {
+    if (c.symbol)
+      return null;
+    c.symbol = new Class(c.name, c);
+    // Insert into current scope.
+    scop.insert(c.symbol, c.name);
+    // Enter a new scope.
+    this.scop = this.scop.enter(c.symbol);
+    // Continue semantic analysis.
+    c.decls && visitD(c.decls);
+    // Exit scope.
+    this.scop = scop.exit();
+    return c;
+  }
+
+  Expression visit(CommaExpression e)
+  {
+    if (!e.type)
+    {
+      e.left = visitE(e.left);
+      e.right = visitE(e.right);
+      e.type = e.right.type;
+    }
+    return e;
+  }
+
+  Expression visit(OrOrExpression)
+  { return null; }
+
+  Expression visit(AndAndExpression)
+  { return null; }
+
+  Expression visit(MixinExpression me)
+  {
+    /+
+    if (type)
+      return this.expr;
+    // TODO:
+    auto expr = this.expr.semantic(scop);
+    expr = expr.evaluate();
+    if (expr is null)
+      return this;
+    auto strExpr = TryCast!(StringExpression)(expr);
+    if (strExpr is null)
+     error(scop, MSG.MixinArgumentMustBeString);
+    else
+    {
+      auto loc = this.begin.getLocation();
+      auto filePath = loc.filePath;
+      auto parser = new_ExpressionParser(strExpr.getString(), filePath, scop.infoMan);
+      expr = parser.parse();
+      expr = expr.semantic(scop);
+    }
+    this.expr = expr;
+    this.type = expr.type;
+    return expr;
+    +/
+    return null;
+  }
+} // override
+}
--- a/trunk/src/main.d	Sun Jan 13 19:26:12 2008 +0100
+++ b/trunk/src/main.d	Sun Jan 13 21:53:01 2008 +0100
@@ -10,7 +10,9 @@
        dil.lexer.Token;
 import dil.ast.Declarations,
        dil.ast.Expressions,
-       dil.ast.Node;
+       dil.ast.Node,
+       dil.ast.Visitor;
+import dil.semantic.Pass1;
 import dil.Messages;
 import dil.Settings;
 import dil.SettingsLoader;