1 // ast-dump.cc -- AST debug dump. -*- C++ -*-
3 // Copyright 2011 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
13 #include "expressions.h"
14 #include "statements.h"
20 // The -fgo-dump-ast flag to activate AST dumps.
22 Go_dump
ast_dump_flag("ast");
24 // This class is used to traverse the tree to look for blocks and
27 class Ast_dump_traverse_blocks_and_functions
: public Traverse
30 Ast_dump_traverse_blocks_and_functions(Ast_dump_context
* ast_dump_context
)
31 : Traverse(traverse_blocks
| traverse_functions
),
32 ast_dump_context_(ast_dump_context
)
40 function(Named_object
*);
43 Ast_dump_context
* ast_dump_context_
;
46 // This class is used to traverse the tree to look for statements.
48 class Ast_dump_traverse_statements
: public Traverse
51 Ast_dump_traverse_statements(Ast_dump_context
* ast_dump_context
)
52 : Traverse(traverse_statements
),
53 ast_dump_context_(ast_dump_context
)
58 statement(Block
*, size_t* pindex
, Statement
*);
61 Ast_dump_context
* ast_dump_context_
;
64 // For each block we enclose it in brackets.
66 int Ast_dump_traverse_blocks_and_functions::block(Block
* block
)
68 this->ast_dump_context_
->print_indent();
69 this->ast_dump_context_
->ostream() << "{" << std::endl
;
70 this->ast_dump_context_
->indent();
73 Ast_dump_traverse_statements
adts(this->ast_dump_context_
);
74 block
->traverse(&adts
);
76 this->ast_dump_context_
->unindent();
77 this->ast_dump_context_
->print_indent();
78 this->ast_dump_context_
->ostream() << "}" << std::endl
;
80 return TRAVERSE_SKIP_COMPONENTS
;
83 // Dump each traversed statement.
86 Ast_dump_traverse_statements::statement(Block
* block
, size_t* pindex
,
89 statement
->dump_statement(this->ast_dump_context_
);
91 if (statement
->is_block_statement())
93 Ast_dump_traverse_blocks_and_functions
adtbf(this->ast_dump_context_
);
94 statement
->traverse(block
, pindex
, &adtbf
);
97 return TRAVERSE_SKIP_COMPONENTS
;
100 // Dump the function header.
103 Ast_dump_traverse_blocks_and_functions::function(Named_object
* no
)
105 this->ast_dump_context_
->ostream() << no
->name();
107 go_assert(no
->is_function());
108 Function
* func
= no
->func_value();
110 this->ast_dump_context_
->ostream() << "(";
111 this->ast_dump_context_
->dump_typed_identifier_list(
112 func
->type()->parameters());
114 this->ast_dump_context_
->ostream() << ")";
116 Function::Results
* res
= func
->result_variables();
117 if (res
!= NULL
&& !res
->empty())
119 this->ast_dump_context_
->ostream() << " (";
121 for (Function::Results::const_iterator it
= res
->begin();
125 if (it
!= res
->begin())
126 this->ast_dump_context_
->ostream() << ",";
127 Named_object
* no
= (*it
);
129 this->ast_dump_context_
->ostream() << no
->name() << " ";
130 go_assert(no
->is_result_variable());
131 Result_variable
* resvar
= no
->result_var_value();
133 this->ast_dump_context_
->dump_type(resvar
->type());
136 this->ast_dump_context_
->ostream() << ")";
139 this->ast_dump_context_
->ostream() << " : ";
140 this->ast_dump_context_
->dump_type(func
->type());
141 this->ast_dump_context_
->ostream() << std::endl
;
143 return TRAVERSE_CONTINUE
;
146 // Class Ast_dump_context.
148 Ast_dump_context::Ast_dump_context(std::ostream
* out
/* = NULL */,
149 bool dump_subblocks
/* = true */)
150 : indent_(0), dump_subblocks_(dump_subblocks
), ostream_(out
), gogo_(NULL
)
154 // Dump files will be named %basename%.dump.ast
156 const char* kAstDumpFileExtension
= ".dump.ast";
158 // Dump the internal representation.
161 Ast_dump_context::dump(Gogo
* gogo
, const char* basename
)
163 std::ofstream
* out
= new std::ofstream();
164 std::string
dumpname(basename
);
165 dumpname
+= ".dump.ast";
166 out
->open(dumpname
.c_str());
170 error("cannot open %s:%m, -fgo-dump-ast ignored", dumpname
.c_str());
175 this->ostream_
= out
;
177 Ast_dump_traverse_blocks_and_functions
adtbf(this);
178 gogo
->traverse(&adtbf
);
183 // Dump a textual representation of a type to the
187 Ast_dump_context::dump_type(const Type
* t
)
190 this->ostream() << "(nil type)";
192 // FIXME: write a type pretty printer instead of
193 // using mangled names.
194 if (this->gogo_
!= NULL
)
195 this->ostream() << "(" << t
->mangled_name(this->gogo_
) << ")";
198 // Dump a textual representation of a block to the
202 Ast_dump_context::dump_block(Block
* b
)
204 Ast_dump_traverse_blocks_and_functions
adtbf(this);
208 // Dump a textual representation of an expression to the
212 Ast_dump_context::dump_expression(const Expression
* e
)
214 e
->dump_expression(this);
217 // Dump a textual representation of an expression list to the
221 Ast_dump_context::dump_expression_list(const Expression_list
* el
,
222 bool as_pairs
/* = false */)
227 for (std::vector
<Expression
*>::const_iterator it
= el
->begin();
231 if ( it
!= el
->begin())
232 this->ostream() << ",";
234 (*it
)->dump_expression(this);
236 this->ostream() << "NULL";
239 this->ostream() << ":";
241 (*it
)->dump_expression(this);
246 // Dump a textual representation of a typed identifier to the
250 Ast_dump_context::dump_typed_identifier(const Typed_identifier
* ti
)
252 this->ostream() << ti
->name() << " ";
253 this->dump_type(ti
->type());
256 // Dump a textual representation of a typed identifier list to the
260 Ast_dump_context::dump_typed_identifier_list(
261 const Typed_identifier_list
* ti_list
)
266 for (Typed_identifier_list::const_iterator it
= ti_list
->begin();
267 it
!= ti_list
->end();
270 if (it
!= ti_list
->begin())
271 this->ostream() << ",";
272 this->dump_typed_identifier(&(*it
));
276 // Dump a textual representation of a temporary variable to the
280 Ast_dump_context::dump_temp_variable_name(const Statement
* s
)
282 go_assert(s
->classification() == Statement::STATEMENT_TEMPORARY
);
283 // Use the statement address as part of the name for the temporary variable.
284 this->ostream() << "tmp." << (uintptr_t) s
;
287 // Dump a textual representation of a label to the
291 Ast_dump_context::dump_label_name(const Unnamed_label
* l
)
293 // Use the unnamed label address as part of the name for the temporary
295 this->ostream() << "label." << (uintptr_t) l
;
298 // Produce a textual representation of an operator symbol.
301 op_string(Operator op
)
303 // FIXME: This should be in line with symbols that are parsed,
304 // exported and/or imported.
323 case OPERATOR_ANDAND
:
341 case OPERATOR_LSHIFT
:
343 case OPERATOR_RSHIFT
:
345 case OPERATOR_BITCLEAR
:
347 case OPERATOR_CHANOP
:
349 case OPERATOR_PLUSEQ
:
351 case OPERATOR_MINUSEQ
:
357 case OPERATOR_MULTEQ
:
363 case OPERATOR_LSHIFTEQ
:
365 case OPERATOR_RSHIFTEQ
:
369 case OPERATOR_BITCLEAREQ
:
371 case OPERATOR_PLUSPLUS
:
373 case OPERATOR_MINUSMINUS
:
377 case OPERATOR_COLONEQ
:
379 case OPERATOR_SEMICOLON
:
383 case OPERATOR_ELLIPSIS
:
387 case OPERATOR_LPAREN
:
389 case OPERATOR_RPAREN
:
391 case OPERATOR_LCURLY
:
393 case OPERATOR_RCURLY
:
395 case OPERATOR_LSQUARE
:
397 case OPERATOR_RSQUARE
:
405 // Dump a textual representation of an operator to the
409 Ast_dump_context::dump_operator(Operator op
)
411 this->ostream() << op_string(op
);
414 // Size of a single indent.
416 const int Ast_dump_context::offset_
= 2;
418 // Print indenting spaces to dump file.
421 Ast_dump_context::print_indent()
423 for (int i
= 0; i
< this->indent_
* this->offset_
; i
++)
424 this->ostream() << " ";
427 // Dump a textual representation of the ast to the
430 void Gogo::dump_ast(const char* basename
)
432 if (::ast_dump_flag
.is_enabled())
434 Ast_dump_context adc
;
435 adc
.dump(this, basename
);
439 // Implementation of String_dump interface.
442 Ast_dump_context::write_c_string(const char* s
)
444 this->ostream() << s
;
448 Ast_dump_context::write_string(const std::string
& s
)
450 this->ostream() << s
;
453 // Dump statment to stream.
456 Ast_dump_context::dump_to_stream(const Statement
* stm
, std::ostream
* out
)
458 Ast_dump_context
adc(out
, false);
459 stm
->dump_statement(&adc
);
462 // Dump expression to stream.
465 Ast_dump_context::dump_to_stream(const Expression
* expr
, std::ostream
* out
)
467 Ast_dump_context
adc(out
, false);
468 expr
->dump_expression(&adc
);