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"
19 #include "go-diagnostics.h"
21 // The -fgo-dump-ast flag to activate AST dumps.
23 Go_dump
ast_dump_flag("ast");
25 // This class is used to traverse the tree to look for blocks and
28 class Ast_dump_traverse_blocks_and_functions
: public Traverse
31 Ast_dump_traverse_blocks_and_functions(Ast_dump_context
* ast_dump_context
)
32 : Traverse(traverse_blocks
| traverse_functions
),
33 ast_dump_context_(ast_dump_context
)
41 function(Named_object
*);
44 Ast_dump_context
* ast_dump_context_
;
47 // This class is used to traverse the tree to look for statements.
49 class Ast_dump_traverse_statements
: public Traverse
52 Ast_dump_traverse_statements(Ast_dump_context
* ast_dump_context
)
53 : Traverse(traverse_statements
),
54 ast_dump_context_(ast_dump_context
)
59 statement(Block
*, size_t* pindex
, Statement
*);
62 Ast_dump_context
* ast_dump_context_
;
65 // For each block we enclose it in brackets.
67 int Ast_dump_traverse_blocks_and_functions::block(Block
* block
)
71 this->ast_dump_context_
->ostream() << std::endl
;
75 this->ast_dump_context_
->print_indent();
76 this->ast_dump_context_
->ostream() << "{" << std::endl
;
77 this->ast_dump_context_
->indent();
80 Ast_dump_traverse_statements
adts(this->ast_dump_context_
);
81 block
->traverse(&adts
);
83 this->ast_dump_context_
->unindent();
84 this->ast_dump_context_
->print_indent();
85 this->ast_dump_context_
->ostream() << "}" << std::endl
;
87 return TRAVERSE_SKIP_COMPONENTS
;
90 // Dump each traversed statement.
93 Ast_dump_traverse_statements::statement(Block
* block
, size_t* pindex
,
96 statement
->dump_statement(this->ast_dump_context_
);
98 if (statement
->is_block_statement())
100 Ast_dump_traverse_blocks_and_functions
adtbf(this->ast_dump_context_
);
101 statement
->traverse(block
, pindex
, &adtbf
);
104 return TRAVERSE_SKIP_COMPONENTS
;
107 // Dump the function header.
110 Ast_dump_traverse_blocks_and_functions::function(Named_object
* no
)
112 this->ast_dump_context_
->ostream() << no
->name();
114 go_assert(no
->is_function());
115 Function
* func
= no
->func_value();
117 this->ast_dump_context_
->ostream() << "(";
118 this->ast_dump_context_
->dump_typed_identifier_list(
119 func
->type()->parameters());
121 this->ast_dump_context_
->ostream() << ")";
123 Function::Results
* res
= func
->result_variables();
124 if (res
!= NULL
&& !res
->empty())
126 this->ast_dump_context_
->ostream() << " (";
128 for (Function::Results::const_iterator it
= res
->begin();
132 if (it
!= res
->begin())
133 this->ast_dump_context_
->ostream() << ",";
134 Named_object
* no
= (*it
);
136 this->ast_dump_context_
->ostream() << no
->name() << " ";
137 go_assert(no
->is_result_variable());
138 Result_variable
* resvar
= no
->result_var_value();
140 this->ast_dump_context_
->dump_type(resvar
->type());
143 this->ast_dump_context_
->ostream() << ")";
146 this->ast_dump_context_
->ostream() << " : ";
147 this->ast_dump_context_
->dump_type(func
->type());
148 this->ast_dump_context_
->ostream() << std::endl
;
150 return TRAVERSE_CONTINUE
;
153 // Class Ast_dump_context.
155 Ast_dump_context::Ast_dump_context(std::ostream
* out
/* = NULL */,
156 bool dump_subblocks
/* = true */)
157 : indent_(0), dump_subblocks_(dump_subblocks
), ostream_(out
), gogo_(NULL
)
161 // Dump files will be named %basename%.dump.ast
163 const char* kAstDumpFileExtension
= ".dump.ast";
165 // Dump the internal representation.
168 Ast_dump_context::dump(Gogo
* gogo
, const char* basename
)
171 std::string
dumpname(basename
);
172 dumpname
+= ".dump.ast";
173 out
.open(dumpname
.c_str());
177 go_error_at(Linemap::unknown_location(),
178 "cannot open %s:%m, -fgo-dump-ast ignored", dumpname
.c_str());
183 this->ostream_
= &out
;
185 Ast_dump_traverse_blocks_and_functions
adtbf(this);
186 gogo
->traverse(&adtbf
);
191 // Dump a textual representation of a type to the
195 Ast_dump_context::dump_type(const Type
* t
)
198 this->ostream() << "(nil type)";
200 // FIXME: write a type pretty printer instead of
201 // using mangled names.
202 if (this->gogo_
!= NULL
)
203 this->ostream() << "(" << t
->mangled_name(this->gogo_
) << ")";
206 // Dump a textual representation of a block to the
210 Ast_dump_context::dump_block(Block
* b
)
212 Ast_dump_traverse_blocks_and_functions
adtbf(this);
216 // Dump a textual representation of an expression to the
220 Ast_dump_context::dump_expression(const Expression
* e
)
222 e
->dump_expression(this);
225 // Dump a textual representation of an expression list to the
229 Ast_dump_context::dump_expression_list(const Expression_list
* el
,
230 bool as_pairs
/* = false */)
235 for (std::vector
<Expression
*>::const_iterator it
= el
->begin();
239 if ( it
!= el
->begin())
240 this->ostream() << ",";
242 (*it
)->dump_expression(this);
244 this->ostream() << "NULL";
247 this->ostream() << ":";
249 (*it
)->dump_expression(this);
254 // Dump a textual representation of a typed identifier to the
258 Ast_dump_context::dump_typed_identifier(const Typed_identifier
* ti
)
260 this->ostream() << ti
->name() << " ";
261 this->dump_type(ti
->type());
264 // Dump a textual representation of a typed identifier list to the
268 Ast_dump_context::dump_typed_identifier_list(
269 const Typed_identifier_list
* ti_list
)
274 for (Typed_identifier_list::const_iterator it
= ti_list
->begin();
275 it
!= ti_list
->end();
278 if (it
!= ti_list
->begin())
279 this->ostream() << ",";
280 this->dump_typed_identifier(&(*it
));
284 // Dump a textual representation of a temporary variable to the
288 Ast_dump_context::dump_temp_variable_name(const Statement
* s
)
290 go_assert(s
->classification() == Statement::STATEMENT_TEMPORARY
);
291 // Use the statement address as part of the name for the temporary variable.
292 this->ostream() << "tmp." << (uintptr_t) s
;
295 // Dump a textual representation of a label to the
299 Ast_dump_context::dump_label_name(const Unnamed_label
* l
)
301 // Use the unnamed label address as part of the name for the temporary
303 this->ostream() << "label." << (uintptr_t) l
;
306 // Produce a textual representation of an operator symbol.
309 op_string(Operator op
)
311 // FIXME: This should be in line with symbols that are parsed,
312 // exported and/or imported.
331 case OPERATOR_ANDAND
:
349 case OPERATOR_LSHIFT
:
351 case OPERATOR_RSHIFT
:
353 case OPERATOR_BITCLEAR
:
355 case OPERATOR_CHANOP
:
357 case OPERATOR_PLUSEQ
:
359 case OPERATOR_MINUSEQ
:
365 case OPERATOR_MULTEQ
:
371 case OPERATOR_LSHIFTEQ
:
373 case OPERATOR_RSHIFTEQ
:
377 case OPERATOR_BITCLEAREQ
:
379 case OPERATOR_PLUSPLUS
:
381 case OPERATOR_MINUSMINUS
:
385 case OPERATOR_COLONEQ
:
387 case OPERATOR_SEMICOLON
:
391 case OPERATOR_ELLIPSIS
:
395 case OPERATOR_LPAREN
:
397 case OPERATOR_RPAREN
:
399 case OPERATOR_LCURLY
:
401 case OPERATOR_RCURLY
:
403 case OPERATOR_LSQUARE
:
405 case OPERATOR_RSQUARE
:
413 // Dump a textual representation of an operator to the
417 Ast_dump_context::dump_operator(Operator op
)
419 this->ostream() << op_string(op
);
422 // Size of a single indent.
424 const int Ast_dump_context::offset_
= 2;
426 // Print indenting spaces to dump file.
429 Ast_dump_context::print_indent()
431 for (int i
= 0; i
< this->indent_
* this->offset_
; i
++)
432 this->ostream() << " ";
435 // Dump a textual representation of the ast to the
438 void Gogo::dump_ast(const char* basename
)
440 if (::ast_dump_flag
.is_enabled())
442 Ast_dump_context adc
;
443 adc
.dump(this, basename
);
447 // Implementation of String_dump interface.
450 Ast_dump_context::write_c_string(const char* s
)
452 this->ostream() << s
;
456 Ast_dump_context::write_string(const std::string
& s
)
458 this->ostream() << s
;
461 // Dump statment to stream.
464 Ast_dump_context::dump_to_stream(const Statement
* stm
, std::ostream
* out
)
466 Ast_dump_context
adc(out
, false);
467 stm
->dump_statement(&adc
);
470 // Dump expression to stream.
473 Ast_dump_context::dump_to_stream(const Expression
* expr
, std::ostream
* out
)
475 Ast_dump_context
adc(out
, false);
476 expr
->dump_expression(&adc
);