view src/dil/ast/DefaultVisitor.d @ 806:bcb74c9b895c

Moved out files in the trunk folder to the root.
author Aziz K?ksal <aziz.koeksal@gmail.com>
date Sun, 09 Mar 2008 00:12:19 +0100
parents trunk/src/dil/ast/DefaultVisitor.d@9e6c6bb73e5f
children
line wrap: on
line source

/++
  Author: Aziz Köksal
  License: GPL3
+/
module dil.ast.DefaultVisitor;

import dil.ast.Visitor;

import dil.ast.Node;
import dil.ast.Declarations,
       dil.ast.Expressions,
       dil.ast.Statements,
       dil.ast.Types,
       dil.ast.Parameters;
import common;

/// This huge template function, when instantiated for a certain node class,
/// generates a body of calls to visit() on the subnodes.
returnType!(T.stringof) visitDefault(T)(T t)
{
  assert(t !is null, "node passed to visitDefault() is null");
  //Stdout(t).newline;

  alias t d, s, e, n; // Variable aliases of t.

  static if (is(T : Declaration))
  {
    alias T D;
    static if (is(D == CompoundDeclaration))
      foreach (decl; d.decls)
        visitD(decl);
    //EmptyDeclaration,
    //IllegalDeclaration,
    //ModuleDeclaration have no subnodes.
    static if (is(D == AliasDeclaration) ||
               is(D == TypedefDeclaration))
      visitD(d.decl);
    static if (is(D == EnumDeclaration))
    {
      d.baseType && visitT(d.baseType);
      foreach (member; d.members)
        visitD(member);
    }
    static if (is(D == EnumMemberDeclaration))
      d.value && visitE(d.value);
    static if (is(D == ClassDeclaration) || is( D == InterfaceDeclaration))
    {
//       visitN(d.tparams);
      foreach (base; d.bases)
        visitT(base);
      d.decls && visitD(d.decls);
    }
    static if (is(D == StructDeclaration) || is(D == UnionDeclaration))
//       visitN(d.tparams),
      d.decls && visitD(d.decls);
    static if (is(D == ConstructorDeclaration))
      visitN(d.params), visitS(d.funcBody);
    static if (is(D == StaticConstructorDeclaration) ||
               is(D == DestructorDeclaration) ||
               is(D == StaticDestructorDeclaration) ||
               is(D == InvariantDeclaration) ||
               is(D == UnittestDeclaration))
      visitS(d.funcBody);
    static if (is(D == FunctionDeclaration))
      visitT(d.returnType),
//       visitN(d.tparams),
      visitN(d.params),
      visitS(d.funcBody);
    static if (is(D == VariablesDeclaration))
    {
      d.typeNode && visitT(d.typeNode);
      foreach(init; d.inits)
        init && visitE(init);
    }
    static if (is(D == DebugDeclaration) || is(D == VersionDeclaration))
      d.decls && visitD(d.decls),
      d.elseDecls && visitD(d.elseDecls);
    static if (is(D == StaticIfDeclaration))
      visitE(d.condition),
      visitD(d.ifDecls),
      d.elseDecls && visitD(d.elseDecls);
    static if (is(D == StaticAssertDeclaration))
      visitE(d.condition),
      d.message && visitE(d.message);
    static if (is(D == TemplateDeclaration))
      visitN(d.tparams),
      visitD(d.decls);
    static if (is(D == NewDeclaration) || is(D == DeleteDeclaration))
      visitN(d.params),
      visitS(d.funcBody);
    static if (is(D == ProtectionDeclaration) ||
               is(D == StorageClassDeclaration) ||
               is(D == LinkageDeclaration) ||
               is(D == AlignDeclaration))
      visitD(d.decls);
    static if (is(D == PragmaDeclaration))
    {
      foreach (arg; d.args)
        visitE(arg);
      visitD(d.decls);
    }
    static if (is(D == MixinDeclaration))
      d.templateExpr ? visitE(d.templateExpr) : visitE(d.argument);
  }
  else
  static if (is(T : Expression))
  {
    alias T E;
    static if (is(E == IllegalExpression))
    {}
    else
    static if (is(E == CondExpression))
      visitE(e.condition), visitE(e.lhs), visitE(e.rhs);
    else
    static if (is(E : BinaryExpression))
      visitE(e.lhs), visitE(e.rhs);
    else
    static if (is(E : UnaryExpression))
    {
      static if (is(E == CastExpression))
        visitT(e.type);
      visitE(e.e); // Visit member in base class UnaryExpression.
      static if (is(E == IndexExpression))
        foreach (arg; e.args)
          visitE(arg);
      static if (is(E == SliceExpression))
        e.left && (visitE(e.left), visitE(e.right));
      static if (is(E == AsmPostBracketExpression))
        visitE(e.e2);
    }
    else
    {
      static if (is(E == NewExpression))
      {
        foreach (arg; e.newArgs)
          visitE(arg);
        visitT(e.type);
        foreach (arg; e.ctorArgs)
          visitE(arg);
      }
      static if (is(E == NewAnonClassExpression))
      {
        foreach (arg; e.newArgs)
          visitE(arg);
        foreach (base; e.bases)
          visitT(base);
        foreach (arg; e.ctorArgs)
          visitE(arg);
        visitD(e.decls);
      }
      static if (is(E == AsmBracketExpression))
        visitE(e.e);
      static if (is(E == TemplateInstanceExpression))
        e.targs && visitN(e.targs);
      static if (is(E == ArrayLiteralExpression))
        foreach (value; e.values)
          visitE(value);
      static if (is(E == AArrayLiteralExpression))
        foreach (i, key; e.keys)
          visitE(key), visitE(e.values[i]);
      static if (is(E == AssertExpression))
        visitE(e.expr), e.msg && visitE(e.msg);
      static if (is(E == MixinExpression) ||
                 is(E == ImportExpression))
        visitE(e.expr);
      static if (is(E == TypeofExpression) ||
                 is(E == TypeDotIdExpression) ||
                 is(E == TypeidExpression))
        visitT(e.type);
      static if (is(E == IsExpression))
        visitT(e.type), e.specType && visitT(e.specType),
        e.tparams && visitN(e.tparams);
      static if (is(E == FunctionLiteralExpression))
        e.returnType && visitT(e.returnType),
        e.params && visitN(e.params),
        visitS(e.funcBody);
      static if (is(E == ParenExpression))
        visitE(e.next);
      static if (is(E == TraitsExpression))
        visitN(e.targs);
      // VoidInitializer has no subnodes.
      static if (is(E == ArrayInitExpression))
        foreach (i, key; e.keys)
          key && visitE(key), visitE(e.values[i]);
      static if (is(E == StructInitExpression))
        foreach (value; e.values)
          visitE(value);
    }
  }
  else
  static if (is(T : Statement))
  {
    alias T S;
    static if (is(S == CompoundStatement))
      foreach (stmnt; s.stmnts)
        visitS(stmnt);
    //IllegalStatement has no subnodes.
    static if (is(S == FuncBodyStatement))
      s.funcBody && visitS(s.funcBody),
      s.inBody && visitS(s.inBody),
      s.outBody && visitS(s.outBody);
    static if (is(S == ScopeStatement) || is(S == LabeledStatement))
      visitS(s.s);
    static if (is(S == ExpressionStatement))
      visitE(s.e);
    static if (is(S == DeclarationStatement))
      visitD(s.decl);
    static if (is(S == IfStatement))
    {
      s.variable ? cast(Node)visitS(s.variable) : visitE(s.condition);
      visitS(s.ifBody), s.elseBody && visitS(s.elseBody);
    }
    static if (is(S == WhileStatement))
      visitE(s.condition), visitS(s.whileBody);
    static if (is(S == DoWhileStatement))
      visitS(s.doBody), visitE(s.condition);
    static if (is(S == ForStatement))
      s.init && visitS(s.init),
      s.condition && visitE(s.condition),
      s.increment && visitE(s.increment),
      visitS(s.forBody);
    static if (is(S == ForeachStatement))
      visitN(s.params), visitE(s.aggregate), visitS(s.forBody);
    static if (is(S == ForeachRangeStatement))
      visitN(s.params), visitE(s.lower), visitE(s.upper), visitS(s.forBody);
    static if (is(S == SwitchStatement))
      visitE(s.condition), visitS(s.switchBody);
    static if (is(S == CaseStatement))
    {
      foreach (value; s.values)
        visitE(value);
      visitS(s.caseBody);
    }
    static if (is(S == DefaultStatement))
      visitS(s.defaultBody);
    //ContinueStatement,
    //BreakStatement have no subnodes.
    static if (is(S == ReturnStatement))
      s.e && visitE(s.e);
    static if (is(S == GotoStatement))
      s.caseExpr && visitE(s.caseExpr);
    static if (is(S == WithStatement))
      visitE(s.e), visitS(s.withBody);
    static if (is(S == SynchronizedStatement))
      s.e && visitE(s.e), visitS(s.syncBody);
    static if (is(S == TryStatement))
    {
      visitS(s.tryBody);
      foreach (catchBody; s.catchBodies)
        visitS(catchBody);
      s.finallyBody && visitS(s.finallyBody);
    }
    static if (is(S == CatchStatement))
      s.param && visitN(s.param), visitS(s.catchBody);
    static if (is(S == FinallyStatement))
      visitS(s.finallyBody);
    static if (is(S == ScopeGuardStatement))
      visitS(s.scopeBody);
    static if (is(S == ThrowStatement))
      visitE(s.e);
    static if (is(S == VolatileStatement))
      s.volatileBody && visitS(s.volatileBody);
    static if (is(S == AsmBlockStatement))
      visitS(s.statements);
    static if (is(S == AsmStatement))
      foreach (op; s.operands)
        visitE(op);
    //AsmAlignStatement,
    //IllegalAsmStatement have no subnodes.
    static if (is(S == PragmaStatement))
    {
      foreach (arg; s.args)
        visitE(arg);
      visitS(s.pragmaBody);
    }
    static if (is(S == MixinStatement))
      visitE(s.templateExpr);
    static if (is(S == StaticIfStatement))
      visitE(s.condition), visitS(s.ifBody), s.elseBody && visitS(s.elseBody);
    static if (is(S == StaticAssertStatement))
      visitE(s.condition), s.message && visitE(s.message);
    static if (is(S == DebugStatement) || is(S == VersionStatement))
      visitS(s.mainBody), s.elseBody && visitS(s.elseBody);
  }
  else
  static if (is(T : TypeNode))
  {
    //IllegalType,
    //IntegralType,
    //ModuleScopeType,
    //IdentifierType have no subnodes.
    static if (is(T == QualifiedType))
      visitT(t.lhs), visitT(t.rhs);
    static if (is(T == TypeofType))
      visitE(t.e);
    static if (is(T == TemplateInstanceType))
      t.targs && visitN(t.targs);
    static if (is(T == PointerType))
      visitT(t.next);
    static if (is(T == ArrayType))
    {
      visitT(t.next);
      if (t.assocType)
        visitT(t.assocType);
      else if (t.e1)
        visitE(t.e1), t.e2 && visitE(t.e2);
    }
    static if (is(T == FunctionType) || is(T == DelegateType))
      visitT(t.returnType), visitN(t.params);
    static if (is(T == CFuncPointerType))
      visitT(t.next), t.params && visitN(t.params);
    static if (is(T == BaseClassType) ||
               is(T == ConstType) ||
               is(T == InvariantType))
      visitT(t.next);
  }
  else
  static if (is(T == Parameter))
  {
    n.type && visitT(n.type);
    n.defValue && visitE(n.defValue);
  }
  else
  static if (is(T == Parameters) ||
             is(T == TemplateParameters) ||
             is(T == TemplateArguments))
  {
    foreach (node; n.children)
      visitN(node);
  }
  else
  static if (is(T : TemplateParameter))
  {
    static if (is(N == TemplateAliasParameter) ||
               is(N == TemplateTypeParameter) ||
               is(N == TemplateThisParameter))
      n.specType && visitN(n.specType),
      n.defType && visitN(n.defType);
    static if (is(N == TemplateValueParameter))
      visitT(n.valueType),
      n.specValue && visitN(n.specValue),
      n.defValue && visitN(n.defValue);
    //TemplateTupleParameter has no subnodes.
  }
  else
    static assert(0, "Missing default visit method for: "~typeof(t).stringof);
  return t;
}

/// Generates the default visit methods.
///
/// E.g:
/// ---
/// private mixin .visitDefault!(ClassDeclaration) _ClassDeclaration;
/// override returnType!("ClassDeclaration") visit(ClassDeclaration node)
/// { return _ClassDeclaration.visitDefault(node); }
/// ---
char[] generateDefaultVisitMethods()
{
  char[] text;
  foreach (className; g_classNames)
    text ~= "private mixin .visitDefault!("~className~") _"~className~";\n"
            "override returnType!(\""~className~"\") visit("~className~" node)"
            "{return _"~className~".visitDefault(node);}\n";
  return text;
}
// pragma(msg, generateDefaultVisitMethods());

/// This class provides default methods for
/// traversing nodes and their sub-nodes.
class DefaultVisitor : Visitor
{
  // Comment out if too many errors are shown.
  mixin(generateDefaultVisitMethods());
}