gccgo: Added code to dump the AST tree.
authorRoberto Lublinerman <rluble@gmail.com>
Wed, 3 Aug 2011 00:37:26 +0000 (00:37 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Wed, 3 Aug 2011 00:37:26 +0000 (00:37 +0000)
gccgo: Added code to dump the AST tree. The AST dump is
activated with -fgo-dump-ast.
Initial version, it only dumps (most) constructs that
are expected after the lowering transformation.

* Make-lang.in (GO_OBJS): Add go/ast-dump.o.
(go/ast-dump.o): New target.
(go/expressions.o): Depend on go/gofrontend/ast-dump.h.
(go/statements.o): Likewise.

From-SVN: r177225

gcc/go/ChangeLog
gcc/go/Make-lang.in
gcc/go/gofrontend/ast-dump.cc [new file with mode: 0644]
gcc/go/gofrontend/ast-dump.h [new file with mode: 0644]
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/go.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/statements.cc
gcc/go/gofrontend/statements.h

index fb26cabfc319d25c53c2d09f59ec4653521097ef..dcf420e364cb281aa856a59e572168c606dc8a5e 100644 (file)
@@ -1,3 +1,10 @@
+2011-08-02  Roberto Lublinerman  <rluble@gmail.com>
+
+       * Make-lang.in (GO_OBJS): Add go/ast-dump.o.
+       (go/ast-dump.o): New target.
+       (go/expressions.o): Depend on go/gofrontend/ast-dump.h.
+       (go/statements.o): Likewise.
+
 2011-07-06  Richard Guenther  <rguenther@suse.de>
 
        * go-lang.c (go_langhook_init):
index 26c16194d7f9708d2eb79ecbd56c1d1f943be5f9..40fa30ceb9809a47a7f9031d0887b228493d4458 100644 (file)
@@ -45,6 +45,7 @@ gccgo$(exeext): $(GCCGO_OBJS) $(EXTRA_GCC_OBJS) libcommon-target.a $(LIBDEPS)
 go-warn = $(STRICT_WARN)
 
 GO_OBJS = \
+       go/ast-dump.o \
        go/dataflow.o \
        go/export.o \
        go/expressions.o \
@@ -247,6 +248,9 @@ go/go-gcc.o: go/go-gcc.cc $(GO_SYSTEM_H) $(TREE_H) tree-iterator.h \
 go/%.o: go/gofrontend/%.cc
        $(CXX) -c $(GOINCLUDES) $(ALL_CPPFLAGS) $(ALL_CXXFLAGS) $< $(OUTPUT_OPTION)
 
+go/ast-dump.o: go/gofrontend/ast-dump.cc $(GO_SYSTME_H) $(GO_GOGO_H) \
+       $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) $(GO_TYPES_H) \
+       go/gofrontend/ast-dump.h $(GO_C_H) go/gofrontend/go-dump.h
 go/dataflow.o: go/gofrontend/dataflow.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \
        $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) go/gofrontend/dataflow.h
 go/export.o: go/gofrontend/export.cc $(GO_SYSTEM_H) \
@@ -256,7 +260,8 @@ go/expressions.o: go/gofrontend/expressions.cc $(GO_SYSTEM_H) $(TOPLEV_H) \
        intl.h $(TREE_H) $(GIMPLE_H) tree-iterator.h convert.h $(REAL_H) \
        realmpfr.h $(GO_C_H) $(GO_GOGO_H) $(GO_TYPES_H) \
        go/gofrontend/export.h $(GO_IMPORT_H) $(GO_STATEMENTS_H) $(GO_LEX_H) \
-       $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H)
+       $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_EXPRESSIONS_H) \
+       go/gofrontend/ast-dump.h
 go/go.o: go/gofrontend/go.cc $(GO_SYSTEM_H) $(GO_C_H) $(GO_LEX_H) \
        $(GO_PARSE_H) go/gofrontend/backend.h $(GO_GOGO_H)
 go/go-dump.o: go/gofrontend/go-dump.cc $(GO_SYSTEM_H) $(GO_C_H) \
@@ -285,7 +290,8 @@ go/runtime.o: go/gofrontend/runtime.cc $(GO_SYSTEM_H) $(GO_GOGO_H) \
        go/gofrontend/runtime.def
 go/statements.o: go/gofrontend/statements.cc $(GO_SYSTEM_H) \
        $(GO_C_H) $(GO_TYPES_H) $(GO_EXPRESSIONS_H) $(GO_GOGO_H) \
-       $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H)
+       $(GO_RUNTIME_H) go/gofrontend/backend.h $(GO_STATEMENTS_H) \
+       go/gofrontend/ast-dump.h
 go/types.o: go/gofrontend/types.cc $(GO_SYSTEM_H) $(TOPLEV_H) intl.h $(TREE_H) \
        $(GIMPLE_H) $(REAL_H) convert.h $(GO_C_H) $(GO_GOGO_H) \
        go/gofrontend/operator.h $(GO_EXPRESSIONS_H) $(GO_STATEMENTS_H) \
diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc
new file mode 100644 (file)
index 0000000..d52d367
--- /dev/null
@@ -0,0 +1,423 @@
+// ast-dump.cc -- AST debug dump.    -*- C++ -*-
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "go-system.h"
+
+#include <iostream>
+#include <fstream>
+
+#include "gogo.h"
+#include "expressions.h"
+#include "statements.h"
+#include "types.h"
+#include "ast-dump.h"
+#include "go-c.h"
+#include "go-dump.h"
+
+// The -fgo-dump-ast flag to activate AST dumps.
+
+Go_dump ast_dump_context_flag("ast");
+
+// This class is used to traverse the tree to look for blocks and 
+// function headers.
+
+class Ast_dump_traverse_blocks_and_functions : public Traverse
+{
+ public:
+  Ast_dump_traverse_blocks_and_functions(Ast_dump_context* ast_dump_context)
+      : Traverse(traverse_blocks | traverse_functions),
+      ast_dump_context_(ast_dump_context)
+  { }
+
+ protected:
+  int 
+  block(Block*);
+  int
+  function(Named_object*);
+
+ private:
+  Ast_dump_context* ast_dump_context_;
+};
+
+// This class is used to traverse the tree to look for statements.
+
+class Ast_dump_traverse_statements : public Traverse
+{
+ public:
+  Ast_dump_traverse_statements(Ast_dump_context* ast_dump_context)
+      : Traverse(traverse_statements),
+      ast_dump_context_(ast_dump_context)
+  { }
+
+ protected:
+  int
+  statement(Block*, size_t* pindex, Statement*);
+
+ private:
+  Ast_dump_context* ast_dump_context_;
+};
+
+// For each block we enclose it in brackets.
+
+int Ast_dump_traverse_blocks_and_functions::block(Block * block)
+{
+  this->ast_dump_context_->print_indent();
+  this->ast_dump_context_->ostream() << "{" << std::endl;
+  this->ast_dump_context_->indent();
+
+  // Dump statememts.
+  Ast_dump_traverse_statements adts(this->ast_dump_context_);
+  block->traverse(&adts);
+
+  this->ast_dump_context_->unindent();
+  this->ast_dump_context_->print_indent();
+  this->ast_dump_context_->ostream() << "}" << std::endl;
+
+  return TRAVERSE_SKIP_COMPONENTS;
+}
+// Dump each traversed statement.
+
+int
+Ast_dump_traverse_statements::statement(Block* block, size_t* pindex,
+                                        Statement* statement)
+{
+  statement->dump_statement(this->ast_dump_context_);
+  if (statement->is_block_statement())
+    {
+      Ast_dump_traverse_blocks_and_functions adtbf(this->ast_dump_context_);
+      statement->traverse(block, pindex, &adtbf);
+    }
+
+  return TRAVERSE_SKIP_COMPONENTS;
+}
+
+// Dump the function header.
+
+int
+Ast_dump_traverse_blocks_and_functions::function(Named_object* no)
+{
+  this->ast_dump_context_->ostream() << no->name();
+  go_assert(no->is_function());
+  Function* func = no->func_value();
+  
+  this->ast_dump_context_->ostream() << "("; 
+  this->ast_dump_context_->dump_typed_identifier_list(
+                              func->type()->parameters());
+  
+  this->ast_dump_context_->ostream() << ")"; 
+  
+  Function::Results* res = func->result_variables();
+  if (res != NULL && !res->empty())
+    {  
+      this->ast_dump_context_->ostream() << " ("; 
+      
+      for (Function::Results::const_iterator it = res->begin(); 
+          it != res->end(); 
+          it++)
+        {
+          if (it != res->begin())
+            this->ast_dump_context_->ostream() << ",";
+          Named_object* no = (*it);
+          
+          this->ast_dump_context_->ostream() << no->name() << " ";
+          go_assert(no->is_result_variable());
+          Result_variable* resvar = no->result_var_value();
+          
+          this->ast_dump_context_->dump_type(resvar->type());
+        
+        }
+      this->ast_dump_context_->ostream() << ")";
+    }
+    
+  this->ast_dump_context_->ostream() << " : ";
+  this->ast_dump_context_->dump_type(func->type());
+  this->ast_dump_context_->ostream() << std::endl;
+  
+  return TRAVERSE_CONTINUE;
+}
+
+// Class Ast_dump_context.
+
+Ast_dump_context::Ast_dump_context() : ostream_(NULL)
+{
+}
+
+// Dump files will be named %basename%.dump.ast
+
+const char* kAstDumpFileExtension = ".dump.ast";
+
+// Dump the internal representation.
+
+void
+Ast_dump_context::dump(Gogo* gogo, const char* basename)
+{
+  std::ofstream* out = new std::ofstream();
+  std::string dumpname(basename);
+  dumpname += ".dump.ast";
+  out->open(dumpname.c_str());
+
+  if (out->fail())
+    {
+      error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname.c_str());
+      return;
+    }
+  
+  this->indent_ = 0;
+  this->gogo_ = gogo;
+  this->ostream_ = out;
+
+  Ast_dump_traverse_blocks_and_functions adtbf(this);
+  gogo->traverse(&adtbf);
+
+  out->close();
+}
+
+// Dump a textual representation of a type to the
+// the dump file.
+
+void
+Ast_dump_context::dump_type(const Type* t)
+{
+  if (t == NULL)
+    this->ostream() << "(nil type)";
+  else
+    // FIXME: write a type pretty printer instead of 
+    // using mangled names.
+    this->ostream() << "(" << t->mangled_name(this->gogo_) <<  ")"; 
+}
+
+// Dump a textual representation of a block to the
+// the dump file.
+
+void
+Ast_dump_context::dump_block(Block* b)
+{
+  Ast_dump_traverse_blocks_and_functions adtbf(this);
+  b->traverse(&adtbf);
+}
+
+// Dump a textual representation of an expression to the
+// the dump file.
+
+void
+Ast_dump_context::dump_expression(const Expression* e)
+{
+  e->dump_expression(this);
+}
+
+// Dump a textual representation of an expression list to the
+// the dump file.
+
+void
+Ast_dump_context::dump_expression_list(const Expression_list* el)
+{
+  if (el == NULL)
+    return;
+  
+  for (std::vector<Expression*>::const_iterator it = el->begin(); 
+       it != el->end();
+       it++)
+    {
+      if ( it != el->begin())
+        this->ostream() << ",";
+      (*it)->dump_expression(this);
+    }
+}
+
+// Dump a textual representation of a typed identifier to the
+// the dump file.
+
+void
+Ast_dump_context::dump_typed_identifier(const Typed_identifier* ti)
+{
+  this->ostream() << ti->name() << " ";
+  this->dump_type(ti->type());
+}
+
+// Dump a textual representation of a typed identifier list to the
+// the dump file.
+
+void
+Ast_dump_context::dump_typed_identifier_list(
+    const Typed_identifier_list* ti_list)         
+{
+  if (ti_list == NULL)
+    return;
+  
+  for (Typed_identifier_list::const_iterator it = ti_list->begin(); 
+       it != ti_list->end(); 
+       it++)
+    {
+      if (it != ti_list->begin())
+        this->ostream() << ",";
+      this->dump_typed_identifier(&(*it));
+    }
+}
+
+// Dump a textual representation of a temporary variable to the
+// the dump file.
+
+void
+Ast_dump_context::dump_temp_variable_name(const Statement* s)
+{
+  go_assert(s->classification() == Statement::STATEMENT_TEMPORARY);
+  // Use the statement address as part of the name for the temporary variable.
+  this->ostream() << "tmp." << (uintptr_t) s;
+}
+
+// Dump a textual representation of a label to the
+// the dump file.
+
+void
+Ast_dump_context::dump_label_name(const Unnamed_label* l)
+{
+  // Use the unnamed label address as part of the name for the temporary
+  // variable.
+  this->ostream() << "label." << (uintptr_t) l;
+}
+
+// Produce a textual representation of an operator symbol.
+
+static const char*
+op_string(Operator op)
+{
+// FIXME: This should be in line with symbols that are parsed,
+// exported and/or imported.
+  switch (op)
+    {
+    case OPERATOR_PLUS:
+      return "+";
+    case OPERATOR_MINUS:
+      return "-";
+    case OPERATOR_NOT:
+      return "!";
+    case OPERATOR_XOR:
+      return "^";
+    case OPERATOR_AND:
+      return "&";
+    case OPERATOR_MULT:
+      return "*";
+    case OPERATOR_OROR:
+      return "||";
+    case OPERATOR_ANDAND:
+      return "&&";
+    case OPERATOR_EQEQ:
+      return "==";
+    case OPERATOR_NOTEQ:
+      return "!=";
+    case OPERATOR_LT:
+      return "<";
+    case OPERATOR_LE:
+      return "<=";
+    case OPERATOR_GT:
+      return ">";
+    case OPERATOR_GE:
+      return ">=";
+    case OPERATOR_DIV:
+      return "/";
+    case OPERATOR_MOD:
+      return "%";
+    case OPERATOR_LSHIFT:
+      return "<<";
+    case OPERATOR_RSHIFT:
+      return "//";
+    case OPERATOR_BITCLEAR:
+      return "&^";
+    case OPERATOR_CHANOP:
+      return "<-";
+    case OPERATOR_PLUSEQ:
+      return "+=";
+    case OPERATOR_MINUSEQ:
+      return "-=";
+    case OPERATOR_OREQ:
+      return "|=";
+    case OPERATOR_XOREQ:
+      return "^=";
+    case OPERATOR_MULTEQ:
+      return "*=";
+    case OPERATOR_DIVEQ:
+      return "/=";
+    case OPERATOR_MODEQ:
+      return "%=";
+    case OPERATOR_LSHIFTEQ:
+      return "<<=";
+    case OPERATOR_RSHIFTEQ:
+      return ">>=";
+    case OPERATOR_ANDEQ:
+      return "&=";
+    case OPERATOR_BITCLEAREQ:
+      return "&^=";
+    case OPERATOR_PLUSPLUS:
+      return "++";
+    case OPERATOR_MINUSMINUS:
+      return "--";
+    case OPERATOR_COLON:
+      return ":";
+    case OPERATOR_COLONEQ:
+      return ":=";
+    case OPERATOR_SEMICOLON:
+      return ";";
+    case OPERATOR_DOT:
+      return ".";
+    case OPERATOR_ELLIPSIS:
+      return "...";
+    case OPERATOR_COMMA:
+      return ",";
+    case OPERATOR_LPAREN:
+      return "(";
+    case OPERATOR_RPAREN:
+      return ")";
+    case OPERATOR_LCURLY:
+      return "{";
+    case OPERATOR_RCURLY:
+      return "}";
+    case OPERATOR_LSQUARE:
+      return "[";
+    case OPERATOR_RSQUARE:
+      return "]";
+    default:
+      go_unreachable();
+    }
+  return NULL;
+}
+
+// Dump a textual representation of an operator to the
+// the dump file.
+
+void
+Ast_dump_context::dump_operator(Operator op)
+{
+  this->ostream() << op_string(op);
+}
+
+// Size of a single indent.
+
+const int Ast_dump_context::offset_ = 2;
+
+// Print indenting spaces to dump file.
+
+void
+Ast_dump_context::print_indent()
+{
+  for (int i = 0; i < this->indent_ * this->offset_; i++)
+    this->ostream() << " ";
+}
+
+// Dump a textual representation of the ast to the
+// the dump file.
+
+void Gogo::dump_ast(const char* basename)
+{
+  if (ast_dump_context_flag.is_enabled())
+    {
+      Ast_dump_context adc;
+      adc.dump(this, basename);
+    }
+}
diff --git a/gcc/go/gofrontend/ast-dump.h b/gcc/go/gofrontend/ast-dump.h
new file mode 100644 (file)
index 0000000..92a4915
--- /dev/null
@@ -0,0 +1,96 @@
+// ast-dump.h -- AST debug dump.    -*- C++ -*-
+
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#ifndef GO_AST_DUMP_H
+#define GO_AST_DUMP_H
+
+class Expression;
+class Expression_list;
+class Named_object;
+class Statement;
+class Gogo;
+
+// This class implements fgo-dump-ast. the
+// Abstract syntax tree dump of the Go program.
+
+class Ast_dump_context 
+{
+ public:
+  Ast_dump_context();
+
+  // Initialize the dump context.
+  void
+  dump(Gogo*, const char* basename);
+
+  // Dump spaces to dumpfile as indentation.
+  void
+  print_indent();
+  
+  // Increase current indentation for print_indent().
+  void
+  indent() 
+  { ++this->indent_;}
+
+  // Decrease current indentation for print_indent().
+  void
+  unindent() 
+  { --this->indent_;}
+
+  // Get dump output stream.
+  std::ostream& 
+  ostream() 
+  { return *this->ostream_;}
+
+  // Dump a Block to dump file.
+  void 
+  dump_block(Block*);
+  
+  // Dump a type to dump file.
+  void 
+  dump_type(const Type*);
+  
+  // Dump an expression to dump file.
+  void 
+  dump_expression(const Expression*);
+
+  // Dump an expression list to dump file.
+  void 
+  dump_expression_list(const Expression_list*);
+  
+  // Dump a typed identifier to dump file.
+  void
+  dump_typed_identifier(const  Typed_identifier*);
+
+  // Dump a typed identifier list to dump file.
+  void
+  dump_typed_identifier_list(const Typed_identifier_list*);
+  
+  // Dump temporary variable name to dump file.
+  void
+  dump_temp_variable_name(const Statement*);
+
+  // Dump unamed lable name to dump file.
+  void
+  dump_label_name(const Unnamed_label*);
+
+  // Dump operator symbol to dump file.
+  void
+  dump_operator(Operator);
+    
+ private:
+   // Current indent level.
+  int indent_;
+  
+  // Indentation offset.
+  static const int offset_;
+  
+  // Stream on output dump file.
+  std::ostream* ostream_;
+    
+  Gogo* gogo_;
+};
+
+#endif  // GO_AST_DUMP_H
index 433a6d7d431c87750205468eb7a6c8396f39f099..fbd716ab8e91fef1be60bde503de85e5ef5c716e 100644 (file)
@@ -36,6 +36,7 @@ extern "C"
 #include "runtime.h"
 #include "backend.h"
 #include "expressions.h"
+#include "ast-dump.h"
 
 // Class Expression.
 
@@ -790,6 +791,12 @@ Expression::check_bounds(tree val, tree bound_type, tree sofar,
                           sofar, ret);
 }
 
+void
+Expression::dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  this->do_dump_expression(ast_dump_context);
+}
+
 // Error expressions.  This are used to avoid cascading errors.
 
 class Error_expression : public Expression
@@ -849,8 +856,19 @@ class Error_expression : public Expression
   tree
   do_get_tree(Translate_context*)
   { return error_mark_node; }
+
+  void
+  do_dump_expression(Ast_dump_context*) const;
 };
 
+// Dump the ast representation for an error expression to a dump context.
+
+void
+Error_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "_Error_" ;
+}
+
 Expression*
 Expression::make_error(source_location location)
 {
@@ -894,11 +912,19 @@ Type_expression : public Expression
   do_get_tree(Translate_context*)
   { go_unreachable(); }
 
+  void do_dump_expression(Ast_dump_context*) const;
  private:
   // The type which we are representing as an expression.
   Type* type_;
 };
 
+void
+Type_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_type(this->type_);
+}
+
 Expression*
 Expression::make_type(Type* type, source_location location)
 {
@@ -1018,6 +1044,14 @@ Var_expression::do_get_tree(Translate_context* context)
   return ret;
 }
 
+// Ast dump for variable expression.
+
+void
+Var_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << this->variable_->name() ;
+}
+
 // Make a reference to a variable in an expression.
 
 Expression*
@@ -1076,6 +1110,15 @@ Temporary_reference_expression::do_get_tree(Translate_context* context)
   return ret;
 }
 
+// Ast dump for temporary reference.
+
+void
+Temporary_reference_expression::do_dump_expression(
+                                Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_temp_variable_name(this->statement_);
+}
+
 // Make a reference to a temporary variable.
 
 Temporary_reference_expression*
@@ -1113,6 +1156,9 @@ class Sink_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type of this sink variable.
   Type* type_;
@@ -1154,6 +1200,14 @@ Sink_expression::do_get_tree(Translate_context* context)
   return this->var_;
 }
 
+// Ast dump for sink expression.
+
+void
+Sink_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "_" ;
+}
+
 // Make a sink expression.
 
 Expression*
@@ -1286,6 +1340,14 @@ Func_expression::do_get_tree(Translate_context* context)
   return gogo->make_trampoline(fnaddr, closure_tree, this->location());
 }
 
+// Ast dump for function.
+
+void
+Func_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << this->function_->name() ;
+}
+
 // Make a reference to a function in an expression.
 
 Expression*
@@ -1354,6 +1416,16 @@ Unknown_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
     }
 }
 
+// Dump the ast representation for an unknown expression to a dump context.
+
+void
+Unknown_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "_Unknown_(" << this->named_object_->name()
+                             << ")";
+   
+}
+
 // Make a reference to an unknown name.
 
 Expression*
@@ -1399,6 +1471,10 @@ class Boolean_expression : public Expression
   do_export(Export* exp) const
   { exp->write_c_string(this->val_ ? "true" : "false"); }
 
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const
+  { ast_dump_context->ostream() << (this->val_ ? "true" : "false"); }
+  
  private:
   // The constant.
   bool val_;
@@ -1566,6 +1642,15 @@ String_expression::do_import(Import* imp)
   return Expression::make_string(val, imp->location());
 }
 
+// Ast dump for string expression.
+
+void
+String_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  // FIXME: Do proper backshlash quoting for this->val_
+  ast_dump_context->ostream() << "\"" << this->val_ << "\"";
+}
+
 // Make a string expression.
 
 Expression*
@@ -1595,6 +1680,10 @@ class Integer_expression : public Expression
   static void
   export_integer(Export* exp, const mpz_t val);
 
+  // Write VAL to dump context.
+  static void
+  dump_integer(Ast_dump_context* ast_dump_context, const mpz_t val);
+
  protected:
   bool
   do_is_constant() const
@@ -1623,6 +1712,9 @@ class Integer_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The integer value.
   mpz_t val_;
@@ -1871,6 +1963,28 @@ Integer_expression::do_import(Import* imp)
     }
 }
 
+// Write integer to dump context.
+
+void
+Integer_expression::dump_integer(Ast_dump_context* ast_dump_context, 
+                                 const mpz_t val)
+{
+  // FIXME: refactor this code so that is used both by dump and export. Extract
+  // a common interface for Ast_dump_context and Export.
+  char* s = mpz_get_str(NULL, 10, val);
+  ast_dump_context->ostream() << s ;
+  free(s);
+}
+
+
+// Ast dump for integer expression.
+
+void
+Integer_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  Integer_expression::dump_integer(ast_dump_context, this->val_);
+}
+
 // Build a new integer value.
 
 Expression*
@@ -1903,6 +2017,10 @@ class Float_expression : public Expression
   // Write VAL to export data.
   static void
   export_float(Export* exp, const mpfr_t val);
+  
+  // Write VAL to dump file.
+  static void
+  dump_float(Ast_dump_context* ast_dump_context, const mpfr_t val);
 
  protected:
   bool
@@ -1932,6 +2050,9 @@ class Float_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The floating point value.
   mpfr_t val_;
@@ -2109,6 +2230,35 @@ Float_expression::do_export(Export* exp) const
   exp->write_c_string(" ");
 }
 
+// Write  a floating point number to a dump context.
+
+void
+Float_expression::dump_float(Ast_dump_context* ast_dump_context, 
+                                  const mpfr_t val)
+{
+  // FIXME: this code should be refactored so that the same code is used here
+  // and in export_float.
+
+  mp_exp_t exponent;
+  char* s = mpfr_get_str(NULL, &exponent, 10, 0, val, GMP_RNDN);
+  if (*s == '-')
+    ast_dump_context->ostream() << "-";
+  ast_dump_context->ostream() << "0.";
+  ast_dump_context->ostream() << (*s == '-' ? s + 1 : s);
+  mpfr_free_str(s);
+  char buf[30];
+  snprintf(buf, sizeof buf, "E%ld", exponent);
+  ast_dump_context->ostream()  << buf;
+}
+
+// Dump a floating point number to the dump file.
+
+void
+Float_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  Float_expression::dump_float(ast_dump_context, this->val_);
+}
+
 // Make a float expression.
 
 Expression*
@@ -2143,6 +2293,11 @@ class Complex_expression : public Expression
   static void
   export_complex(Export* exp, const mpfr_t real, const mpfr_t val);
 
+  // Write REAL/IMAG to dump context.
+  static void
+  dump_complex(Ast_dump_context* ast_dump_context, 
+              const mpfr_t real, const mpfr_t val);
+  
  protected:
   bool
   do_is_constant() const
@@ -2173,6 +2328,9 @@ class Complex_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The real part.
   mpfr_t real_;
@@ -2342,6 +2500,34 @@ Complex_expression::do_export(Export* exp) const
   exp->write_c_string(" ");
 }
 
+// Write a complex number to a dump context.
+
+void
+Complex_expression::dump_complex(Ast_dump_context* ast_dump_context,
+                                    const mpfr_t real, const mpfr_t imag) 
+{
+  // FIXME: this code should be refactored so that it is used both here
+  // and by export _complex
+  if (!mpfr_zero_p(real))
+    {
+      Float_expression::dump_float(ast_dump_context, real);
+      if (mpfr_sgn(imag) > 0)
+        ast_dump_context->ostream() << "+";
+    }
+  Float_expression::dump_float(ast_dump_context, imag);
+  ast_dump_context->ostream() << "i";
+}
+
+// Dump a complex expression to the dump file.
+
+void
+Complex_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  Complex_expression::dump_complex(ast_dump_context, 
+                                      this->real_,
+                                      this->imag_);
+}
+
 // Make a complex expression.
 
 Expression*
@@ -2443,6 +2629,9 @@ class Const_expression : public Expression
   do_export(Export* exp) const
   { this->constant_->const_value()->expr()->export_expression(exp); }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The constant.
   Named_object* constant_;
@@ -2824,6 +3013,14 @@ Const_expression::do_get_tree(Translate_context* context)
   return ret;
 }
 
+// Dump ast representation for constant expression.
+
+void
+Const_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << this->constant_->name();
+}
+
 // Make a reference to a constant in an expression.
 
 Expression*
@@ -2905,6 +3102,10 @@ class Nil_expression : public Expression
   void
   do_export(Export* exp) const
   { exp->write_c_string("nil"); }
+
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const
+  { ast_dump_context->ostream() << "nil"; }
 };
 
 // Import a nil expression.
@@ -2945,6 +3146,10 @@ class Iota_expression : public Parser_expression
   Expression*
   do_copy()
   { go_unreachable(); }
+  
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const
+  { ast_dump_context->ostream() << "iota"; } 
 };
 
 // Make an iota expression.  This is only called for one case: the
@@ -3040,6 +3245,9 @@ class Type_conversion_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type to convert to.
   Type* type_;
@@ -3570,6 +3778,18 @@ Type_conversion_expression::do_import(Import* imp)
   return Expression::make_cast(type, val, imp->location());
 }
 
+// Dump ast representation for a type conversion expression.
+
+void
+Type_conversion_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << "(";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << ") ";
+}
+
 // Make a type cast expression.
 
 Expression*
@@ -3614,6 +3834,9 @@ class Unsafe_type_conversion_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type to convert to.
   Type* type_;
@@ -3698,6 +3921,18 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context)
     return fold_convert_loc(loc, type_tree, expr_tree);
 }
 
+// Dump ast representation for an unsafe type conversion expression.
+
+void
+Unsafe_type_conversion_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << "(";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << ") ";
+}
+
 // Make an unsafe type conversion expression.
 
 Expression*
@@ -3801,6 +4036,9 @@ class Unary_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The unary operator to apply.
   Operator op_;
@@ -4412,6 +4650,17 @@ Unary_expression::do_import(Import* imp)
   return Expression::make_unary(op, expr, imp->location());
 }
 
+// Dump ast representation of an unary expression.
+
+void
+Unary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_operator(this->op_);
+  ast_dump_context->ostream() << "(";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << ") ";
+}
+
 // Make a unary expression.
 
 Expression*
@@ -6311,6 +6560,20 @@ Binary_expression::do_import(Import* imp)
   return Expression::make_binary(op, left, right, imp->location());
 }
 
+// Dump ast representation of a binary expression.
+
+void
+Binary_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "(";
+  ast_dump_context->dump_expression(this->left_);
+  ast_dump_context->ostream() << " ";
+  ast_dump_context->dump_operator(this->op_);
+  ast_dump_context->ostream() << " ";
+  ast_dump_context->dump_expression(this->right_);
+  ast_dump_context->ostream() << ") ";
+}
+
 // Make a binary expression.
 
 Expression*
@@ -6643,6 +6906,26 @@ Bound_method_expression::do_get_tree(Translate_context*)
   return error_mark_node;
 }
 
+// Dump ast representation of a bound method expression.
+
+void
+Bound_method_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+    const
+{
+  if (this->expr_type_ != NULL)
+    ast_dump_context->ostream() << "(";
+  ast_dump_context->dump_expression(this->expr_); 
+  if (this->expr_type_ != NULL) 
+    {
+      ast_dump_context->ostream() << ":";
+      ast_dump_context->dump_type(this->expr_type_);
+      ast_dump_context->ostream() << ")";
+    }
+    
+  ast_dump_context->ostream() << ".";
+  ast_dump_context->dump_expression(method_);
+}
+
 // Make a method expression.
 
 Bound_method_expression*
@@ -9298,6 +9581,19 @@ Call_expression::set_results(Translate_context* context, tree call_tree)
   return save_expr(stmt_list);
 }
 
+// Dump ast representation for a call expressin.
+
+void
+Call_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  this->fn_->dump_expression(ast_dump_context);
+  ast_dump_context->ostream() << "(";
+  if (args_ != NULL)
+    ast_dump_context->dump_expression_list(this->args_);
+
+  ast_dump_context->ostream() << ") ";
+}
+
 // Make a call expression.
 
 Call_expression*
@@ -9344,6 +9640,9 @@ class Call_result_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The underlying call expression.
   Expression* call_;
@@ -9443,6 +9742,19 @@ Call_result_expression::do_get_tree(Translate_context* context)
   return ref->get_tree(context);
 }
 
+// Dump ast representation for a call result expression.
+
+void
+Call_result_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+    const
+{
+  // FIXME: Wouldn't it be better if the call is assigned to a temporary 
+  // (struct) and the fields are referenced instead.
+  ast_dump_context->ostream() << this->index_ << "@(";
+  ast_dump_context->dump_expression(this->call_);
+  ast_dump_context->ostream() << ")";
+}
+
 // Make a reference to a single result of a call which returns
 // multiple results.
 
@@ -9519,6 +9831,36 @@ Index_expression::do_lower(Gogo*, Named_object*, Statement_inserter*, int)
     }
 }
 
+// Write an indexed expression (expr[expr:expr] or expr[expr]) to a
+// dump context
+
+void
+Index_expression::dump_index_expression(Ast_dump_context* ast_dump_context, 
+                                       const Expression* expr, 
+                                       const Expression* start,
+                                       const Expression* end)
+{
+  expr->dump_expression(ast_dump_context);
+  ast_dump_context->ostream() << "[";
+  start->dump_expression(ast_dump_context);
+  if (end != NULL)
+    {
+      ast_dump_context->ostream() << ":";
+      end->dump_expression(ast_dump_context);
+    }
+  ast_dump_context->ostream() << "]";
+}
+
+// Dump ast representation for an index expression.
+
+void
+Index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  Index_expression::dump_index_expression(ast_dump_context, this->left_, 
+                                          this->start_, this->end_);
+}
+
 // Make an index expression.
 
 Expression*
@@ -9573,6 +9915,9 @@ class Array_index_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The array we are getting a value from.
   Expression* array_;
@@ -9922,6 +10267,16 @@ Array_index_expression::do_get_tree(Translate_context* context)
                         constructor);
 }
 
+// Dump ast representation for an array index expression.
+
+void
+Array_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  Index_expression::dump_index_expression(ast_dump_context, this->array_, 
+                                          this->start_, this->end_);
+}
+
 // Make an array index expression.  END may be NULL.
 
 Expression*
@@ -9976,6 +10331,9 @@ class String_index_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The string we are getting a value from.
   Expression* string_;
@@ -10176,6 +10534,16 @@ String_index_expression::do_get_tree(Translate_context* context)
     }
 }
 
+// Dump ast representation for a string index expression.
+
+void
+String_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context)
+    const
+{
+  Index_expression::dump_index_expression(ast_dump_context, this->string_, 
+                                         this->start_, this->end_);
+}
+
 // Make a string index expression.  END may be NULL.
 
 Expression*
@@ -10390,6 +10758,16 @@ Map_index_expression::get_value_pointer(Translate_context* context,
   return ret;
 }
 
+// Dump ast representation for a map index expression
+
+void
+Map_index_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  Index_expression::dump_index_expression(ast_dump_context, 
+                                          this->map_, this->index_, NULL);
+}
+
 // Make a map index expression.
 
 Map_index_expression*
@@ -10456,6 +10834,16 @@ Field_reference_expression::do_get_tree(Translate_context* context)
                NULL_TREE);
 }
 
+// Dump ast representation for a field reference expression.
+
+void
+Field_reference_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  this->expr_->dump_expression(ast_dump_context);
+  ast_dump_context->ostream() << "." <<  this->field_index_;
+}
+
 // Make a reference to a qualified identifier in an expression.
 
 Field_reference_expression*
@@ -10602,6 +10990,16 @@ Interface_field_reference_expression::do_get_tree(Translate_context*)
   go_unreachable();
 }
 
+// Dump ast representation for an interface field reference.
+
+void
+Interface_field_reference_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  this->expr_->dump_expression(ast_dump_context);
+  ast_dump_context->ostream() << "." << this->name_;
+}
+
 // Make a reference to a field in an interface.
 
 Expression*
@@ -10639,6 +11037,9 @@ class Selector_expression : public Parser_expression
                                   this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const;
+
  private:
   Expression*
   lower_method_expression(Gogo*);
@@ -10859,6 +11260,17 @@ Selector_expression::lower_method_expression(Gogo* gogo)
   return Expression::make_func_reference(no, NULL, location);
 }
 
+// Dump the ast for a selector expression.
+
+void
+Selector_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  ast_dump_context->dump_expression(this->left_);
+  ast_dump_context->ostream() << ".";
+  ast_dump_context->ostream() << this->name_;
+}
+                      
 // Make a selector expression.
 
 Expression*
@@ -10898,6 +11310,9 @@ class Allocation_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The type we are allocating.
   Type* type_;
@@ -10919,6 +11334,17 @@ Allocation_expression::do_get_tree(Translate_context* context)
   return fold_convert(build_pointer_type(type_tree), space);
 }
 
+// Dump ast representation for an allocation expression.
+
+void
+Allocation_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  ast_dump_context->ostream() << "new(";
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << ")";
+}
+
 // Make an allocation expression.
 
 Expression*
@@ -10973,6 +11399,9 @@ class Struct_construction_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type of the struct to construct.
   Type* type_;
@@ -11185,6 +11614,19 @@ Struct_construction_expression::do_export(Export* exp) const
   exp->write_c_string(")");
 }
 
+// Dump ast representation of a struct construction expression.
+
+void
+Struct_construction_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << "{";
+  ast_dump_context->dump_expression_list(this->vals_);
+  ast_dump_context->ostream() << "}";
+}
+
 // Make a struct composite literal.  This used by the thunk code.
 
 Expression*
@@ -11249,6 +11691,9 @@ protected:
   tree
   get_constructor_tree(Translate_context* context, tree type_tree);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type of the array to construct.
   Type* type_;
@@ -11422,6 +11867,19 @@ Array_construction_expression::do_export(Export* exp) const
   exp->write_c_string(")");
 }
 
+// Dump ast representation of an array construction expressin.
+
+void
+Array_construction_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << "{" ;
+  ast_dump_context->dump_expression_list(this->vals_);
+  ast_dump_context->ostream() << "}" ;
+
+}
+
 // Construct a fixed array.
 
 class Fixed_array_construction_expression :
@@ -11688,6 +12146,9 @@ class Map_construction_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The type of the map to construct.
   Type* type_;
@@ -11941,6 +12402,18 @@ Map_construction_expression::do_export(Export* exp) const
   exp->write_c_string(")");
 }
 
+// Dump ast representation for a map construction expression.
+
+void
+Map_construction_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  // FIXME: We should print key:value pairs here.
+  ast_dump_context->ostream() << "{" ;
+  ast_dump_context->dump_expression_list(this->vals_);
+  ast_dump_context->ostream() << "}";
+}
+
 // A general composite literal.  This is lowered to a type specific
 // version.
 
@@ -11971,6 +12444,9 @@ class Composite_literal_expression : public Parser_expression
                                            this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   Expression*
   lower_struct(Gogo*, Type*);
@@ -12382,6 +12858,20 @@ Composite_literal_expression::lower_map(Gogo* gogo, Named_object* function,
   return new Map_construction_expression(type, this->vals_, location);
 }
 
+// Dump ast representation for a composite literal expression.
+
+void
+Composite_literal_expression::do_dump_expression(
+                               Ast_dump_context* ast_dump_context) const
+{
+  // FIXME: We should print colons if this->has_keys_ is true
+  ast_dump_context->ostream() << "composite_literal(" ;
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << ", {";
+  ast_dump_context->dump_expression_list(this->vals_);
+  ast_dump_context->ostream() << "})";
+}
+
 // Make a composite literal expression.
 
 Expression*
@@ -12556,6 +13046,17 @@ Type_guard_expression::do_get_tree(Translate_context* context)
                                              this->location());
 }
 
+// Dump ast representation for a type guard expression.
+
+void
+Type_guard_expression::do_dump_expression(Ast_dump_context* ast_dump_context) 
+    const
+{
+  this->expr_->dump_expression(ast_dump_context);
+  ast_dump_context->ostream() <<  ".";
+  ast_dump_context->dump_type(this->type_);
+}
+
 // Make a type guard expression.
 
 Expression*
@@ -12607,6 +13108,9 @@ class Heap_composite_expression : public Expression
   do_export(Export*) const
   { go_unreachable(); }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The composite literal which is being put on the heap.
   Expression* expr_;
@@ -12635,6 +13139,17 @@ Heap_composite_expression::do_get_tree(Translate_context* context)
   return ret;
 }
 
+// Dump ast representation for a heap composite expression.
+
+void
+Heap_composite_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "&(";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << ")";
+}
+
 // Allocate a composite literal on the heap.
 
 Expression*
@@ -12702,6 +13217,15 @@ Receive_expression::do_get_tree(Translate_context* context)
                                    this->for_select_, this->location());
 }
 
+// Dump ast representation for a receive expression.
+
+void
+Receive_expression::do_dump_expression(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << " <- " ;
+  ast_dump_context->dump_expression(channel_);
+}
+
 // Make a receive expression.
 
 Receive_expression*
@@ -12741,11 +13265,23 @@ class Type_descriptor_expression : public Expression
                                                this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type for which this is the descriptor.
   Type* type_;
 };
 
+// Dump ast representation for a type descriptor expression.
+
+void
+Type_descriptor_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->dump_type(this->type_);
+}
+
 // Make a type descriptor expression.
 
 Expression*
@@ -12783,6 +13319,9 @@ class Type_info_expression : public Expression
   tree
   do_get_tree(Translate_context* context);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The type for which we are getting information.
   Type* type_;
@@ -12834,6 +13373,23 @@ Type_info_expression::do_get_tree(Translate_context* context)
     }
 }
 
+// Dump ast representation for a type info expression.
+
+void
+Type_info_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "typeinfo(";
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << ",";
+  ast_dump_context->ostream() << 
+    (this->type_info_ == TYPE_INFO_ALIGNMENT ? "alignment" 
+    : this->type_info_ == TYPE_INFO_FIELD_ALIGNMENT ? "field alignment"
+    : this->type_info_ == TYPE_INFO_SIZE ? "size "
+    : "unknown");
+  ast_dump_context->ostream() << ")";
+}
+
 // Make a type info expression.
 
 Expression*
@@ -12870,6 +13426,9 @@ class Struct_field_offset_expression : public Expression
   tree
   do_get_tree(Translate_context* context);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The type of the struct.
   Struct_type* type_;
@@ -12906,6 +13465,17 @@ Struct_field_offset_expression::do_get_tree(Translate_context* context)
                          byte_position(struct_field_tree));
 }
 
+// Dump ast representation for a struct field offset expression.
+
+void
+Struct_field_offset_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() <<  "unsafe.Offsetof(";
+  ast_dump_context->ostream() << this->field_->field_name();
+  ast_dump_context->ostream() << ")";
+}
+
 // Make an expression for a struct field offset.
 
 Expression*
@@ -12946,11 +13516,25 @@ class Map_descriptor_expression : public Expression
                                               this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
  private:
   // The type for which this is the descriptor.
   Map_type* type_;
 };
 
+// Dump ast representation for a map descriptor expression.
+
+void
+Map_descriptor_expression::do_dump_expression(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->ostream() << "map_descriptor(";
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream() << ")";
+}
+
 // Make a map descriptor expression.
 
 Expression*
@@ -12988,6 +13572,10 @@ class Label_addr_expression : public Expression
     return expr_to_tree(this->label_->get_addr(context, this->location()));
   }
 
+  void
+  do_dump_expression(Ast_dump_context* ast_dump_context) const
+  { ast_dump_context->ostream() << this->label_->name(); }
+  
  private:
   // The label whose address we are taking.
   Label* label_;
index da31f149ae085c3018efa700cb5b5565dcfb2cb6..6f74f73eb1ac2355896209194919730bfbc3a81e 100644 (file)
@@ -42,6 +42,7 @@ class Export;
 class Import;
 class Temporary_statement;
 class Label;
+class Ast_dump_context;
 
 // The base class for all expressions.
 
@@ -635,6 +636,10 @@ class Expression
   static tree
   check_bounds(tree val, tree bound_type, tree sofar, source_location);
 
+  // Dump an expression to a dump constext.
+  void
+  dump_expression(Ast_dump_context*) const;
+
  protected:
   // May be implemented by child class: traverse the expressions.
   virtual int
@@ -731,6 +736,10 @@ class Expression
   void
   report_error(const char*);
 
+  // Child class implements dumping to a dump context.
+  virtual void
+  do_dump_expression(Ast_dump_context*) const = 0;
+
  private:
   // Convert to the desired statement classification, or return NULL.
   // This is a controlled dynamic cast.
@@ -934,6 +943,9 @@ class Var_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The variable we are referencing.
   Named_object* variable_;
@@ -978,6 +990,9 @@ class Temporary_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The statement where the temporary variable is defined.
   Temporary_statement* statement_;
@@ -1031,6 +1046,9 @@ class String_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The string value.  This is immutable.
   const std::string val_;
@@ -1154,6 +1172,9 @@ class Binary_expression : public Expression
   void
   do_export(Export*) const;
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The binary operator to apply.
   Operator op_;
@@ -1290,6 +1311,9 @@ class Call_expression : public Expression
   bool
   determining_types();
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   bool
   check_argument_type(int, const Type*, const Type*, source_location, bool);
@@ -1384,6 +1408,9 @@ class Func_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The function itself.
   Named_object* function_;
@@ -1432,6 +1459,9 @@ class Unknown_expression : public Parser_expression
   do_copy()
   { return new Unknown_expression(this->named_object_, this->location()); }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+  
  private:
   // The unknown name.
   Named_object* named_object_;
@@ -1456,6 +1486,12 @@ class Index_expression : public Parser_expression
   set_is_lvalue()
   { this->is_lvalue_ = true; }
 
+  // Dump an index expression, i.e. an expression of the form
+  // expr[expr] or expr[expr:expr], to a dump context.
+  static void
+  dump_index_expression(Ast_dump_context*, const Expression* expr, 
+                        const Expression* start, const Expression* end);
+
  protected:
   int
   do_traverse(Traverse*);
@@ -1473,6 +1509,9 @@ class Index_expression : public Parser_expression
                                this->location());
   }
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression being indexed.
   Expression* left_;
@@ -1572,6 +1611,9 @@ class Map_index_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The map we are looking into.
   Expression* map_;
@@ -1641,6 +1683,9 @@ class Bound_method_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The object used to find the method.  This is passed to the method
   // as the first argument.
@@ -1712,6 +1757,9 @@ class Field_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression we are looking into.  This should have a type of
   // struct.
@@ -1777,6 +1825,9 @@ class Interface_field_reference_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression for the interface object.  This should have a type
   // of interface or pointer to interface.
@@ -1830,6 +1881,9 @@ class Type_guard_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The expression to convert.
   Expression* expr_;
@@ -1889,6 +1943,9 @@ class Receive_expression : public Expression
   tree
   do_get_tree(Translate_context*);
 
+  void
+  do_dump_expression(Ast_dump_context*) const;
+
  private:
   // The channel from which we are receiving.
   Expression* channel_;
index 3dc344027657c8dfc3182c413bead3d5e4d7ee96..4ab0f8ee7cf8b5fecb5324cdc102c04c91f2f828 100644 (file)
@@ -133,6 +133,9 @@ go_parse_input_files(const char** filenames, unsigned int filename_count,
 
   // Convert complicated go and defer statements into simpler ones.
   ::gogo->simplify_thunk_statements();
+  
+  // Dump ast, use filename[0] as the base name
+  ::gogo->dump_ast(filenames[0]);
 }
 
 // Write out globals.
index c9d2971daf58a7750129527165050458aa654c14..dae22f51c05d55388f6a7f554ca35ac014aa681d 100644 (file)
@@ -422,6 +422,10 @@ class Gogo
   void
   simplify_thunk_statements();
 
+  // Dump AST if -fgo-dump-ast is set 
+  void
+  dump_ast(const char* basename);
+
   // Convert named types to the backend representation.
   void
   convert_named_types();
@@ -512,7 +516,6 @@ class Gogo
   receive_as_64bit_integer(tree type, tree channel, bool blocking,
                           bool for_select);
 
-
   // Make a trampoline which calls FNADDR passing CLOSURE.
   tree
   make_trampoline(tree fnaddr, tree closure, source_location);
index dd2aef6f10a04b8c01111a9065c14f9aeb59a917..c6d2ace91f841ce5983254c75bc5f534c198c480 100644 (file)
@@ -15,6 +15,7 @@
 #include "runtime.h"
 #include "backend.h"
 #include "statements.h"
+#include "ast-dump.h"
 
 // Class Statement.
 
@@ -142,6 +143,14 @@ Statement::get_backend(Translate_context* context)
   return this->do_get_backend(context);
 }
 
+// Dump AST representation for a statement to a dump context.
+
+void
+Statement::dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  this->do_dump_statement(ast_dump_context);
+}
+
 // Note that this statement is erroneous.  This is called by children
 // when they discover an error.
 
@@ -178,8 +187,20 @@ class Error_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*)
   { go_unreachable(); }
+
+  void
+  do_dump_statement(Ast_dump_context*) const;
 };
 
+// Dump the AST representation for an error statement.
+
+void
+Error_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "Error statement" << std::endl;
+}
+
 // Make an error statement.
 
 Statement*
@@ -280,6 +301,30 @@ Variable_declaration_statement::do_get_backend(Translate_context* context)
   return context->backend()->statement_list(stats);
 }
 
+// Dump the AST representation for a variable declaration.
+
+void
+Variable_declaration_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  
+  go_assert(var_->is_variable());
+  ast_dump_context->ostream() << "var " << this->var_->name() <<  " ";
+  Variable* var = this->var_->var_value();
+  if (var->has_type()) 
+    {
+      ast_dump_context->dump_type(var->type());
+      ast_dump_context->ostream() << " ";
+    }
+  if (var->init() != NULL)
+    {
+      ast_dump_context->ostream() <<  "= ";
+      ast_dump_context->dump_expression(var->init());
+    }
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a variable declaration.
 
 Statement*
@@ -422,6 +467,27 @@ Temporary_statement::get_backend_variable(Translate_context* context) const
   return this->bvariable_;
 }
 
+// Dump the AST represemtation for a temporary statement
+
+void
+Temporary_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_temp_variable_name(this);
+  if (this->type_ != NULL)
+    {
+      ast_dump_context->ostream() << " ";
+      ast_dump_context->dump_type(this->type_);
+      
+    }
+  if (this->init_ != NULL)
+    {
+      ast_dump_context->ostream() << " = ";
+      ast_dump_context->dump_expression(this->init_);
+    }
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make and initialize a temporary variable in BLOCK.
 
 Temporary_statement*
@@ -458,6 +524,9 @@ class Assignment_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // Left hand side--the lvalue.
   Expression* lhs_;
@@ -542,6 +611,19 @@ Assignment_statement::do_get_backend(Translate_context* context)
                                                  this->location());
 }
 
+// Dump the AST representation for an assignment statement.
+
+void
+Assignment_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
+    const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->lhs_);
+  ast_dump_context->ostream() << " = " ;
+  ast_dump_context->dump_expression(this->rhs_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make an assignment statement.
 
 Statement*
@@ -614,6 +696,9 @@ class Assignment_operation_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The operator (OPERATOR_PLUSEQ, etc.).
   Operator op_;
@@ -704,6 +789,19 @@ Assignment_operation_statement::do_lower(Gogo*, Named_object*,
     }
 }
 
+// Dump the AST representation for an assignment operation statement
+
+void
+Assignment_operation_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->lhs_);
+  ast_dump_context->dump_operator(this->op_); 
+  ast_dump_context->dump_expression(this->rhs_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make an assignment operation statement.
 
 Statement*
@@ -741,6 +839,9 @@ class Tuple_assignment_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // Left hand side--a list of lvalues.
   Expression_list* lhs_;
@@ -768,7 +869,7 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
   source_location loc = this->location();
 
   Block* b = new Block(enclosing, loc);
-  
+
   // First move out any subexpressions on the left hand side.  The
   // right hand side will be evaluated in the required order anyhow.
   Move_ordered_evals moe(b);
@@ -832,6 +933,19 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
   return Statement::make_block_statement(b, loc);
 }
 
+// Dump the AST representation for a tuple assignment statement.
+
+void
+Tuple_assignment_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression_list(this->lhs_);
+  ast_dump_context->ostream() << " = ";
+  ast_dump_context->dump_expression_list(this->rhs_);
+  ast_dump_context->ostream()  << std::endl;
+}
+
 // Make a tuple assignment statement.
 
 Statement*
@@ -869,6 +983,9 @@ public:
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // Lvalue which receives the value from the map.
   Expression* val_;
@@ -960,6 +1077,21 @@ Tuple_map_assignment_statement::do_lower(Gogo*, Named_object*,
   return Statement::make_block_statement(b, loc);
 }
 
+// Dump the AST representation for a tuple map assignment statement.
+
+void
+Tuple_map_assignment_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << ", ";
+  ast_dump_context->dump_expression(this->present_);
+  ast_dump_context->ostream() << " = ";
+  ast_dump_context->dump_expression(this->map_index_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a map assignment statement which returns a pair of values.
 
 Statement*
@@ -998,6 +1130,9 @@ class Map_assignment_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // A reference to the map index which should be set or deleted.
   Expression* map_index_;
@@ -1076,6 +1211,21 @@ Map_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing,
   return Statement::make_block_statement(b, loc);
 }
 
+// Dump the AST representation for a map assignment statement.
+
+void
+Map_assignment_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->map_index_);
+  ast_dump_context->ostream() << " = ";
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << ", ";
+  ast_dump_context->dump_expression(this->should_set_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a statement which assigns a pair of entries to a map.
 
 Statement*
@@ -1113,6 +1263,9 @@ class Tuple_receive_assignment_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // Lvalue which receives the value from the channel.
   Expression* val_;
@@ -1200,6 +1353,21 @@ Tuple_receive_assignment_statement::do_lower(Gogo*, Named_object*,
   return Statement::make_block_statement(b, loc);
 }
 
+// Dump the AST representation for a tuple receive statement.
+
+void
+Tuple_receive_assignment_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << ", ";
+  ast_dump_context->dump_expression(this->closed_);
+  ast_dump_context->ostream() << " <- ";
+  ast_dump_context->dump_expression(this->channel_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a nonblocking receive statement.
 
 Statement*
@@ -1240,6 +1408,9 @@ class Tuple_type_guard_assignment_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Call_expression*
   lower_to_type(Runtime::Function);
@@ -1375,6 +1546,23 @@ Tuple_type_guard_assignment_statement::lower_to_object_type(
   b->add_statement(s);
 }
 
+// Dump the AST representation for a tuple type guard statement.
+
+void 
+Tuple_type_guard_assignment_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << ", ";
+  ast_dump_context->dump_expression(this->ok_);
+  ast_dump_context->ostream() << " = ";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << " . ";
+  ast_dump_context->dump_type(this->type_);
+  ast_dump_context->ostream()  << std::endl;
+}
+
 // Make an assignment from a type guard to a pair of variables.
 
 Statement*
@@ -1415,6 +1603,9 @@ class Expression_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context* context);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Expression* expr_;
 };
@@ -1459,6 +1650,17 @@ Expression_statement::do_get_backend(Translate_context* context)
   return context->backend()->expression_statement(tree_to_expr(expr_tree));
 }
 
+// Dump the AST representation for an expression statement
+
+void 
+Expression_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
+    const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(expr_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make an expression statement from an Expression.
 
 Statement*
@@ -1494,6 +1696,9 @@ class Block_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context* context);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Block* block_;
 };
@@ -1507,6 +1712,14 @@ Block_statement::do_get_backend(Translate_context* context)
   return context->backend()->block_statement(bblock);
 }
 
+// Dump the AST for a block statement
+
+void
+Block_statement::do_dump_statement(Ast_dump_context*) const
+{
+  // block statement braces are dumped when traversing.
+}
+
 // Make a block statement.
 
 Statement*
@@ -1541,6 +1754,9 @@ class Inc_dec_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The l-value to increment or decrement.
   Expression* expr_;
@@ -1564,6 +1780,16 @@ Inc_dec_statement::do_lower(Gogo*, Named_object*, Block*, Statement_inserter*)
   return Statement::make_assignment_operation(op, this->expr_, oexpr, loc);
 }
 
+// Dump the AST representation for a inc/dec statement.
+
+void
+Inc_dec_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(expr_);
+  ast_dump_context->ostream() << (is_inc_? "++": "--") << std::endl;
+}
+
 // Make an increment statement.
 
 Statement*
@@ -2233,6 +2459,17 @@ Go_statement::do_get_backend(Translate_context* context)
   return context->backend()->expression_statement(call_bexpr);
 }
 
+// Dump the AST representation for go statement.
+
+void
+Go_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "go ";
+  ast_dump_context->dump_expression(this->call());
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a go statement.
 
 Statement*
@@ -2261,6 +2498,17 @@ Defer_statement::do_get_backend(Translate_context* context)
   return context->backend()->expression_statement(call_bexpr);
 }
 
+// Dump the AST representation for defer statement.
+
+void
+Defer_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "defer ";
+  ast_dump_context->dump_expression(this->call());
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a defer statement.
 
 Statement*
@@ -2445,6 +2693,17 @@ Return_statement::do_get_backend(Translate_context* context)
                                              retvals, loc);
 }
 
+// Dump the AST representation for a return statement.
+
+void
+Return_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "return " ;
+  ast_dump_context->dump_expression_list(this->vals_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a return statement.
 
 Statement*
@@ -2481,6 +2740,9 @@ class Bc_statement : public Statement
   do_get_backend(Translate_context* context)
   { return this->label_->get_goto(context, this->location()); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The label that this branches to.
   Unnamed_label* label_;
@@ -2488,6 +2750,21 @@ class Bc_statement : public Statement
   bool is_break_;
 };
 
+// Dump the AST representation for a break/continue statement
+
+void
+Bc_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << (this->is_break_ ? "break" : "continue");
+  if (this->label_ != NULL) 
+    {
+      ast_dump_context->ostream() << " "; 
+      ast_dump_context->dump_label_name(this->label_);
+    }
+  ast_dump_context->ostream() << std::endl; 
+}
+
 // Make a break statement.
 
 Statement*
@@ -2530,6 +2807,9 @@ class Goto_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Label* label_;
 };
@@ -2557,6 +2837,15 @@ Goto_statement::do_get_backend(Translate_context* context)
   return context->backend()->goto_statement(blabel, this->location());
 }
 
+// Dump the AST representation for a goto statement.
+
+void
+Goto_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "goto " << this->label_->name() << std::endl;
+}
+
 // Make a goto statement.
 
 Statement*
@@ -2588,10 +2877,25 @@ class Goto_unnamed_statement : public Statement
   do_get_backend(Translate_context* context)
   { return this->label_->get_goto(context, this->location()); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Unnamed_label* label_;
 };
 
+// Dump the AST representation for an unnamed goto statement
+
+void
+Goto_unnamed_statement::do_dump_statement(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "goto ";
+  ast_dump_context->dump_label_name(this->label_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a goto statement to an unnamed label.
 
 Statement*
@@ -2621,6 +2925,15 @@ Label_statement::do_get_backend(Translate_context* context)
   return context->backend()->label_definition_statement(blabel);
 }
 
+// Dump the AST for a label definition statement.
+
+void
+Label_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << this->label_->name() << ":" << std::endl;
+}
+
 // Make a label statement.
 
 Statement*
@@ -2648,11 +2961,25 @@ class Unnamed_label_statement : public Statement
   do_get_backend(Translate_context* context)
   { return this->label_->get_definition(context); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The label.
   Unnamed_label* label_;
 };
 
+// Dump the AST representation for an unnamed label definition statement.
+
+void
+Unnamed_label_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
+    const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_label_name(this->label_);
+  ast_dump_context->ostream() << ":" << std::endl;
+}
+
 // Make an unnamed label statement.
 
 Statement*
@@ -2688,6 +3015,9 @@ class If_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Expression* cond_;
   Block* then_block_;
@@ -2759,6 +3089,24 @@ If_statement::do_get_backend(Translate_context* context)
                                          else_block, this->location());
 }
 
+// Dump the AST representation for an if statement
+
+void
+If_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "if ";
+  ast_dump_context->dump_expression(this->cond_);
+  ast_dump_context->ostream() << std::endl;
+  ast_dump_context->dump_block(this->then_block_);
+  if (this->else_block_ != NULL) 
+    {
+      ast_dump_context->print_indent();
+      ast_dump_context->ostream() << "else" << std::endl;
+      ast_dump_context->dump_block(this->else_block_);
+    }
+}
+
 // Make an if statement.
 
 Statement*
@@ -3050,6 +3398,31 @@ Case_clauses::Case_clause::get_backend(Translate_context* context,
     return context->backend()->compound_statement(statements, break_stat);
 }
 
+// Dump the AST representation for a case clause
+
+void
+Case_clauses::Case_clause::dump_clause(Ast_dump_context* ast_dump_context) 
+    const
+{
+  ast_dump_context->print_indent();
+  if (this->is_default_)
+    {
+      ast_dump_context->ostream() << "default:";
+    }
+  else
+    {
+      ast_dump_context->ostream() << "case ";
+      ast_dump_context->dump_expression_list(this->cases_);
+      ast_dump_context->ostream() << ":" ;
+    }
+  ast_dump_context->dump_block(this->statements_);
+  if (this->is_fallthrough_)
+    {
+      ast_dump_context->print_indent();
+      ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
+    }
+}
+
 // Class Case_clauses.
 
 // Traversal.
@@ -3212,6 +3585,17 @@ Case_clauses::get_backend(Translate_context* context,
     }
 }
 
+// Dump the AST representation for case clauses (from a switch statement)
+
+void
+Case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
+{
+  for (Clauses::const_iterator p = this->clauses_.begin();
+       p != this->clauses_.end();
+       ++p)    
+    p->dump_clause(ast_dump_context);
+}
+
 // A constant switch statement.  A Switch_statement is lowered to this
 // when all the cases are constants.
 
@@ -3241,6 +3625,9 @@ class Constant_switch_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The value to switch on.
   Expression* val_;
@@ -3320,6 +3707,20 @@ Constant_switch_statement::do_get_backend(Translate_context* context)
   return context->backend()->compound_statement(switch_statement, ldef);
 }
 
+// Dump the AST representation for a constant switch statement.
+
+void
+Constant_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context)
+    const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "switch ";
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << " {" << std::endl;
+  this->clauses_->dump_clauses(ast_dump_context);
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Class Switch_statement.
 
 // Traversal.
@@ -3395,6 +3796,24 @@ Switch_statement::break_label()
   return this->break_label_;
 }
 
+// Dump the AST representation for a switch statement.
+
+void
+Switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "switch ";
+  if (this->val_ != NULL)
+    {
+      ast_dump_context->dump_expression(this->val_);
+      ast_dump_context->ostream() << " ";
+    }
+  ast_dump_context->ostream() << "{" << std::endl;
+  this->clauses_->dump_clauses(ast_dump_context);
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Make a switch statement.
 
 Switch_statement*
@@ -3519,6 +3938,31 @@ Type_case_clauses::Type_case_clause::lower(Block* b,
     }
 }
 
+// Dump the AST representation for a type case clause
+
+void
+Type_case_clauses::Type_case_clause::dump_clause(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  if (this->is_default_)
+    {
+      ast_dump_context->ostream() << "default:";
+    }
+  else
+    {
+      ast_dump_context->ostream() << "case "; 
+      ast_dump_context->dump_type(this->type_);
+      ast_dump_context->ostream() << ":" ;
+    }
+  ast_dump_context->dump_block(this->statements_);
+  if (this->is_fallthrough_)
+    {
+      ast_dump_context->print_indent();
+      ast_dump_context->ostream() <<  " (fallthrough)" << std::endl;
+    }
+}
+
 // Class Type_case_clauses.
 
 // Traversal.
@@ -3589,6 +4033,17 @@ Type_case_clauses::lower(Block* b, Temporary_statement* descriptor_temp,
     default_case->lower(b, descriptor_temp, break_label, NULL);
 }
 
+// Dump the AST representation for case clauses (from a switch statement)
+
+void
+Type_case_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
+{
+  for (Type_clauses::const_iterator p = this->clauses_.begin();
+       p != this->clauses_.end();
+       ++p)    
+    p->dump_clause(ast_dump_context);
+}
+
 // Class Type_switch_statement.
 
 // Traversal.
@@ -3692,6 +4147,20 @@ Type_switch_statement::break_label()
   return this->break_label_;
 }
 
+// Dump the AST representation for a type switch statement
+
+void
+Type_switch_statement::do_dump_statement(Ast_dump_context* ast_dump_context) 
+    const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "switch " << this->var_->name() << " = ";
+  ast_dump_context->dump_expression(this->expr_);
+  ast_dump_context->ostream() << " .(type) {" << std::endl;
+  this->clauses_->dump_clauses(ast_dump_context);
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Make a type switch statement.
 
 Type_switch_statement*
@@ -3862,6 +4331,18 @@ Send_statement::do_get_backend(Translate_context* context)
     return context->backend()->compound_statement(btemp, s);
 }
 
+// Dump the AST representation for a send statement
+
+void
+Send_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->dump_expression(this->channel_);
+  ast_dump_context->ostream() << " <- ";
+  ast_dump_context->dump_expression(this->val_);
+  ast_dump_context->ostream() << std::endl;
+}
+
 // Make a send statement.
 
 Send_statement*
@@ -4053,6 +4534,48 @@ Select_clauses::Select_clause::get_statements_backend(
   return context->backend()->block_statement(bblock);
 }
 
+// Dump the AST representation for a select case clause
+
+void
+Select_clauses::Select_clause::dump_clause(
+    Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  if (this->is_default_)
+    {
+      ast_dump_context->ostream() << "default:";
+    }
+  else
+    {
+      ast_dump_context->ostream() << "case "  ;
+      if (this->is_send_)
+        {
+          ast_dump_context->dump_expression(this->channel_);
+          ast_dump_context->ostream() << " <- " ;
+          ast_dump_context->dump_expression(this->val_);
+        }
+      else 
+        {
+         if (this->val_ != NULL)
+           ast_dump_context->dump_expression(this->val_);
+          if (this->closed_ != NULL)
+            {
+             // FIXME: can val_ == NULL and closed_ ! = NULL?
+              ast_dump_context->ostream() << " , " ;
+              ast_dump_context->dump_expression(this->closed_);
+            }
+          if (this->closedvar_ != NULL ||
+              this->var_ != NULL)
+            ast_dump_context->ostream() << " := " ;
+            
+          ast_dump_context->ostream() << " <- " ;
+          ast_dump_context->dump_expression(this->channel_);
+        }
+      ast_dump_context->ostream() << ":" ;
+    }
+  ast_dump_context->dump_block(this->statements_);
+}
+
 // Class Select_clauses.
 
 // Traversal.
@@ -4326,6 +4849,17 @@ Select_clauses::add_clause_backend(
     (*clauses)[index] = context->backend()->compound_statement(s, g);
 }
 
+// Dump the AST representation for select clauses.
+
+void
+Select_clauses::dump_clauses(Ast_dump_context* ast_dump_context) const
+{
+  for (Clauses::const_iterator p = this->clauses_.begin();
+       p != this->clauses_.end();
+       ++p)    
+    p->dump_clause(ast_dump_context);
+}
+
 // Class Select_statement.
 
 // Return the break label for this switch statement, creating it if
@@ -4366,6 +4900,17 @@ Select_statement::do_get_backend(Translate_context* context)
                                     this->location());
 }
 
+// Dump the AST representation for a select statement.
+
+void 
+Select_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "select {" << std::endl;
+  this->clauses_->dump_clauses(ast_dump_context);
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Make a select statement.
 
 Select_statement*
@@ -4501,6 +5046,38 @@ For_statement::set_break_continue_labels(Unnamed_label* break_label,
   this->continue_label_ = continue_label;
 }
 
+// Dump the AST representation for a for statement.
+
+void
+For_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  if (this->init_ != NULL)
+    {
+      ast_dump_context->print_indent();
+      ast_dump_context->indent();
+      ast_dump_context->ostream() << "// INIT  " << std::endl;
+      ast_dump_context->dump_block(this->init_);
+      ast_dump_context->unindent();
+    }
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "for ";
+  if (this->cond_ != NULL)
+    ast_dump_context->dump_expression(this->cond_);
+  ast_dump_context->ostream() << " {" << std::endl;
+  ast_dump_context->indent();
+
+  ast_dump_context->dump_block(this->statements_);
+  if (this->init_ != NULL)
+    {
+      ast_dump_context->print_indent();
+      ast_dump_context->ostream() << "// POST " << std::endl;
+      ast_dump_context->dump_block(this->post_);
+    }
+  ast_dump_context->unindent();
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Make a for statement.
 
 For_statement*
@@ -5119,6 +5696,33 @@ For_range_statement::continue_label()
   return this->continue_label_;
 }
 
+// Dump the AST representation for a for range statement.
+
+void
+For_range_statement::do_dump_statement(Ast_dump_context* ast_dump_context) const
+{
+  
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "for ";
+  ast_dump_context->dump_expression(this->index_var_);
+  if (this->value_var_ != NULL)
+    {
+      ast_dump_context->ostream() << ", ";
+      ast_dump_context->dump_expression(this->value_var_);
+    }
+    
+  ast_dump_context->ostream() << " = range ";      
+  ast_dump_context->dump_expression(this->range_);
+  ast_dump_context->ostream() << " {" << std::endl;
+  ast_dump_context->indent();
+
+  ast_dump_context->dump_block(this->statements_);
+
+  ast_dump_context->unindent();
+  ast_dump_context->print_indent();
+  ast_dump_context->ostream() << "}" << std::endl;
+}
+
 // Make a for statement with a range clause.
 
 For_range_statement*
index 44241ab115270a4ad047bba525668a2121ea201c..8b5263bb820042868d46bad2959eb82e3c0c7868 100644 (file)
@@ -43,6 +43,7 @@ class Typed_identifier_list;
 class Bexpression;
 class Bstatement;
 class Bvariable;
+class Ast_dump_context;
 
 // This class is used to traverse assignments made by a statement
 // which makes assignments.
@@ -374,6 +375,10 @@ class Statement
   Bstatement*
   get_backend(Translate_context*);
 
+  // Dump AST representation of a statement to a dump context.
+  void
+  dump_statement(Ast_dump_context*) const;
+
  protected:
   // Implemented by child class: traverse the tree.
   virtual int
@@ -414,6 +419,10 @@ class Statement
   virtual Bstatement*
   do_get_backend(Translate_context*) = 0;
 
+  // Implemented by child class: dump ast representation.
+  virtual void
+  do_dump_statement(Ast_dump_context*) const = 0;
+
   // Traverse an expression in a statement.
   int
   traverse_expression(Traverse*, Expression**);
@@ -507,6 +516,9 @@ class Temporary_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The type of the temporary variable.
   Type* type_;
@@ -544,6 +556,9 @@ class Variable_declaration_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Named_object* var_;
 };
@@ -581,6 +596,9 @@ class Return_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // Return values.  This may be NULL.
   Expression_list* vals_;
@@ -617,6 +635,9 @@ class Send_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The channel on which to send the value.
   Expression* channel_;
@@ -678,6 +699,10 @@ class Select_clauses
   Bstatement*
   get_backend(Translate_context*, Unnamed_label* break_label, source_location);
 
+  // Dump AST representation.
+  void
+  dump_clauses(Ast_dump_context*) const;
+
  private:
   // A single clause.
   class Select_clause
@@ -748,6 +773,10 @@ class Select_clauses
     Bstatement*
     get_statements_backend(Translate_context*);
 
+    // Dump AST representation.
+    void
+    dump_clause(Ast_dump_context*) const;
+
    private:
     // The channel.
     Expression* channel_;
@@ -825,6 +854,9 @@ class Select_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The select clauses.
   Select_clauses* clauses_;
@@ -844,7 +876,7 @@ class Thunk_statement : public Statement
 
   // Return the call expression.
   Expression*
-  call()
+  call() const
   { return this->call_; }
 
   // Simplify a go or defer statement so that it only uses a single
@@ -914,6 +946,9 @@ class Go_statement : public Thunk_statement
  protected:
   Bstatement*
   do_get_backend(Translate_context*);
+
+  void
+  do_dump_statement(Ast_dump_context*) const;
 };
 
 // A defer statement.
@@ -928,6 +963,9 @@ class Defer_statement : public Thunk_statement
  protected:
   Bstatement*
   do_get_backend(Translate_context*);
+
+  void
+  do_dump_statement(Ast_dump_context*) const;
 };
 
 // A label statement.
@@ -952,6 +990,9 @@ class Label_statement : public Statement
   Bstatement*
   do_get_backend(Translate_context*);
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The label.
   Label* label_;
@@ -1005,6 +1046,9 @@ class For_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The initialization statements.  This may be NULL.
   Block* init_;
@@ -1063,6 +1107,9 @@ class For_range_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   Expression*
   make_range_ref(Named_object*, Temporary_statement*, source_location);
@@ -1167,6 +1214,10 @@ class Case_clauses
              std::vector<std::vector<Bexpression*> >* all_cases,
              std::vector<Bstatement*>* all_statements) const;
 
+  // Dump the AST representation to a dump context.
+  void
+  dump_clauses(Ast_dump_context*) const;
+  
  private:
   // For a constant switch we need to keep a record of constants we
   // have already seen.
@@ -1237,6 +1288,10 @@ class Case_clauses
     get_backend(Translate_context*, Unnamed_label* break_label,
                Case_constants*, std::vector<Bexpression*>* cases) const;
 
+    // Dump the AST representation to a dump context.
+    void
+    dump_clause(Ast_dump_context*) const;
+  
    private:
     // The list of case expressions.
     Expression_list* cases_;
@@ -1292,6 +1347,9 @@ class Switch_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The value to switch on.  This may be NULL.
   Expression* val_;
@@ -1342,6 +1400,10 @@ class Type_case_clauses
   lower(Block*, Temporary_statement* descriptor_temp,
        Unnamed_label* break_label) const;
 
+  // Dump the AST representation to a dump context.
+  void
+  dump_clauses(Ast_dump_context*) const;
+
  private:
   // One type case clause.
   class Type_case_clause
@@ -1382,6 +1444,10 @@ class Type_case_clauses
     lower(Block*, Temporary_statement* descriptor_temp,
          Unnamed_label* break_label, Unnamed_label** stmts_label) const;
 
+    // Dump the AST representation to a dump context.
+    void
+    dump_clause(Ast_dump_context*) const;
+
    private:
     // The type for this type clause.
     Type* type_;
@@ -1438,6 +1504,9 @@ class Type_switch_statement : public Statement
   do_get_backend(Translate_context*)
   { go_unreachable(); }
 
+  void
+  do_dump_statement(Ast_dump_context*) const;
+
  private:
   // The variable holding the value we are switching on.
   Named_object* var_;