+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):
go-warn = $(STRICT_WARN)
GO_OBJS = \
+ go/ast-dump.o \
go/dataflow.o \
go/export.o \
go/expressions.o \
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) \
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) \
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) \
--- /dev/null
+// 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);
+ }
+}
--- /dev/null
+// 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
#include "runtime.h"
#include "backend.h"
#include "expressions.h"
+#include "ast-dump.h"
// Class Expression.
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
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)
{
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)
{
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*
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*
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type of this sink variable.
Type* type_;
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*
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*
}
}
+// 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*
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_;
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*
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
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The integer value.
mpz_t val_;
}
}
+// 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*
// 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
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The floating point value.
mpfr_t val_;
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*
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
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The real part.
mpfr_t real_;
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*
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_;
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*
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.
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
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type to convert to.
Type* type_;
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*
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type to convert to.
Type* type_;
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*
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The unary operator to apply.
Operator op_;
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*
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*
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*
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*
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The underlying call expression.
Expression* call_;
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.
}
}
+// 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*
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_;
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*
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_;
}
}
+// 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*
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*
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*
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*
this->location());
}
+ void
+ do_dump_expression(Ast_dump_context* ast_dump_context) const;
+
private:
Expression*
lower_method_expression(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*
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type we are allocating.
Type* type_;
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*
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type of the struct to construct.
Type* type_;
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*
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_;
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 :
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type of the map to construct.
Type* type_;
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.
this->location());
}
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
Expression*
lower_struct(Gogo*, Type*);
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*
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*
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_;
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*
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*
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*
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_;
}
}
+// 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*
tree
do_get_tree(Translate_context* context);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The type of the struct.
Struct_type* type_;
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*
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*
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_;
class Import;
class Temporary_statement;
class Label;
+class Ast_dump_context;
// The base class for all expressions.
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
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.
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The variable we are referencing.
Named_object* variable_;
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_;
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The string value. This is immutable.
const std::string val_;
void
do_export(Export*) const;
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The binary operator to apply.
Operator op_;
bool
determining_types();
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
bool
check_argument_type(int, const Type*, const Type*, source_location, bool);
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The function itself.
Named_object* function_;
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_;
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*);
this->location());
}
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The expression being indexed.
Expression* left_;
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The map we are looking into.
Expression* map_;
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.
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.
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.
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The expression to convert.
Expression* expr_;
tree
do_get_tree(Translate_context*);
+ void
+ do_dump_expression(Ast_dump_context*) const;
+
private:
// The channel from which we are receiving.
Expression* channel_;
// 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.
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();
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);
#include "runtime.h"
#include "backend.h"
#include "statements.h"
+#include "ast-dump.h"
// Class Statement.
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.
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*
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*
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*
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// Left hand side--the lvalue.
Expression* lhs_;
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*
do_get_backend(Translate_context*)
{ go_unreachable(); }
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// The operator (OPERATOR_PLUSEQ, etc.).
Operator op_;
}
}
+// 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*
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_;
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);
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*
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_;
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*
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_;
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*
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_;
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*
do_get_backend(Translate_context*)
{ go_unreachable(); }
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Call_expression*
lower_to_type(Runtime::Function);
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*
Bstatement*
do_get_backend(Translate_context* context);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Expression* expr_;
};
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*
Bstatement*
do_get_backend(Translate_context* context);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Block* block_;
};
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*
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_;
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*
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*
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*
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*
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_;
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*
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Label* label_;
};
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*
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*
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*
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*
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Expression* cond_;
Block* then_block_;
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*
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.
}
}
+// 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.
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// The value to switch on.
Expression* val_;
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.
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*
}
}
+// 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.
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.
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*
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*
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.
(*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
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*
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*
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*
class Bexpression;
class Bstatement;
class Bvariable;
+class Ast_dump_context;
// This class is used to traverse assignments made by a statement
// which makes assignments.
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
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**);
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// The type of the temporary variable.
Type* type_;
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
Named_object* var_;
};
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// Return values. This may be NULL.
Expression_list* vals_;
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_;
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
Bstatement*
get_statements_backend(Translate_context*);
+ // Dump AST representation.
+ void
+ dump_clause(Ast_dump_context*) const;
+
private:
// The channel.
Expression* channel_;
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// The select clauses.
Select_clauses* clauses_;
// Return the call expression.
Expression*
- call()
+ call() const
{ return this->call_; }
// Simplify a go or defer statement so that it only uses a single
protected:
Bstatement*
do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
};
// A defer statement.
protected:
Bstatement*
do_get_backend(Translate_context*);
+
+ void
+ do_dump_statement(Ast_dump_context*) const;
};
// A label statement.
Bstatement*
do_get_backend(Translate_context*);
+ void
+ do_dump_statement(Ast_dump_context*) const;
+
private:
// The label.
Label* label_;
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_;
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);
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.
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_;
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_;
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
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_;
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_;