mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
Refactor output to be more streaming-focused. (#666)
- Switch code to llvm::raw_ostream as part of standardizing output forms.
- Preferring llvm::raw_ostream over std::ostream because other tooling code should be expected to rely on llvm more closely, and an overall preference towards library consistency.
- There are a couple spots in syntax/ that still use std streams, but I'd prefer to take a separate PR to see how best to address those.
- std::boolalpha doesn't work with llvm, so I've implemented equivalent in a couple places (not enough that it felt like worth making a helper function).
- Implement Print(ostream) as consistently as we can, as an instance member.
- This facilitates the use of the common/ostream.h template to provide operators.
- Preferring this approach so that Print is easily accessible via gdb, per suggestion on #executable-semantics.
- Switch code currently calling `type->Print(ostream)` to instead do `ostream << *type`.
- Remove the unused `PrintTypeEnv`, nothing used it and the declaration didn't match the definition.
This commit is contained in:
@@ -4,8 +4,6 @@
|
||||
|
||||
#include "executable_semantics/ast/expression.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
auto Expression::GetIdentifierExpression() const
|
||||
@@ -168,9 +166,8 @@ auto Expression::MakeTupleLiteral(int line_num,
|
||||
for (auto& arg : args) {
|
||||
if (arg.name == "") {
|
||||
if (seen_named_member) {
|
||||
std::cerr << line_num
|
||||
<< ": positional members must come before named members"
|
||||
<< std::endl;
|
||||
llvm::errs() << line_num
|
||||
<< ": positional members must come before named members\n";
|
||||
exit(-1);
|
||||
}
|
||||
arg.name = std::to_string(i);
|
||||
@@ -191,138 +188,122 @@ auto Expression::MakeIndexExpression(int line_num, const Expression* exp,
|
||||
return e;
|
||||
}
|
||||
|
||||
static void PrintOp(Operator op) {
|
||||
static void PrintOp(llvm::raw_ostream& out, Operator op) {
|
||||
switch (op) {
|
||||
case Operator::Add:
|
||||
std::cout << "+";
|
||||
out << "+";
|
||||
break;
|
||||
case Operator::Neg:
|
||||
case Operator::Sub:
|
||||
std::cout << "-";
|
||||
out << "-";
|
||||
break;
|
||||
case Operator::Mul:
|
||||
case Operator::Deref:
|
||||
case Operator::Ptr:
|
||||
std::cout << "*";
|
||||
out << "*";
|
||||
break;
|
||||
case Operator::Not:
|
||||
std::cout << "not";
|
||||
out << "not";
|
||||
break;
|
||||
case Operator::And:
|
||||
std::cout << "and";
|
||||
out << "and";
|
||||
break;
|
||||
case Operator::Or:
|
||||
std::cout << "or";
|
||||
out << "or";
|
||||
break;
|
||||
case Operator::Eq:
|
||||
std::cout << "==";
|
||||
out << "==";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintFields(const std::vector<FieldInitializer>& fields) {
|
||||
static void PrintFields(llvm::raw_ostream& out,
|
||||
const std::vector<FieldInitializer>& fields) {
|
||||
int i = 0;
|
||||
for (auto iter = fields.begin(); iter != fields.end(); ++iter, ++i) {
|
||||
if (i != 0) {
|
||||
std::cout << ", ";
|
||||
out << ", ";
|
||||
}
|
||||
std::cout << iter->name << " = ";
|
||||
PrintExp(iter->expression);
|
||||
out << iter->name << " = " << *iter->expression;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintExp(const Expression* e) {
|
||||
switch (e->tag()) {
|
||||
void Expression::Print(llvm::raw_ostream& out) const {
|
||||
switch (tag()) {
|
||||
case ExpressionKind::IndexExpression:
|
||||
PrintExp(e->GetIndexExpression().aggregate);
|
||||
std::cout << "[";
|
||||
PrintExp(e->GetIndexExpression().offset);
|
||||
std::cout << "]";
|
||||
out << *GetIndexExpression().aggregate << "["
|
||||
<< *GetIndexExpression().offset << "]";
|
||||
break;
|
||||
case ExpressionKind::FieldAccessExpression:
|
||||
PrintExp(e->GetFieldAccessExpression().aggregate);
|
||||
std::cout << ".";
|
||||
std::cout << e->GetFieldAccessExpression().field;
|
||||
out << *GetFieldAccessExpression().aggregate << "."
|
||||
<< GetFieldAccessExpression().field;
|
||||
break;
|
||||
case ExpressionKind::TupleLiteral:
|
||||
std::cout << "(";
|
||||
PrintFields(e->GetTupleLiteral().fields);
|
||||
std::cout << ")";
|
||||
out << "(";
|
||||
PrintFields(out, GetTupleLiteral().fields);
|
||||
out << ")";
|
||||
break;
|
||||
case ExpressionKind::IntLiteral:
|
||||
std::cout << e->GetIntLiteral();
|
||||
out << GetIntLiteral();
|
||||
break;
|
||||
case ExpressionKind::BoolLiteral:
|
||||
std::cout << std::boolalpha;
|
||||
std::cout << e->GetBoolLiteral();
|
||||
out << (GetBoolLiteral() ? "true" : "false");
|
||||
break;
|
||||
case ExpressionKind::PrimitiveOperatorExpression: {
|
||||
std::cout << "(";
|
||||
PrimitiveOperatorExpression op = e->GetPrimitiveOperatorExpression();
|
||||
out << "(";
|
||||
PrimitiveOperatorExpression op = GetPrimitiveOperatorExpression();
|
||||
if (op.arguments.size() == 0) {
|
||||
PrintOp(op.op);
|
||||
PrintOp(out, op.op);
|
||||
} else if (op.arguments.size() == 1) {
|
||||
PrintOp(op.op);
|
||||
std::cout << " ";
|
||||
auto iter = op.arguments.begin();
|
||||
PrintExp(*iter);
|
||||
PrintOp(out, op.op);
|
||||
out << " " << *op.arguments[0];
|
||||
} else if (op.arguments.size() == 2) {
|
||||
auto iter = op.arguments.begin();
|
||||
PrintExp(*iter);
|
||||
std::cout << " ";
|
||||
PrintOp(op.op);
|
||||
std::cout << " ";
|
||||
++iter;
|
||||
PrintExp(*iter);
|
||||
out << *op.arguments[0] << " ";
|
||||
PrintOp(out, op.op);
|
||||
out << " " << *op.arguments[1];
|
||||
}
|
||||
std::cout << ")";
|
||||
out << ")";
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::IdentifierExpression:
|
||||
std::cout << e->GetIdentifierExpression().name;
|
||||
out << GetIdentifierExpression().name;
|
||||
break;
|
||||
case ExpressionKind::BindingExpression: {
|
||||
const BindingExpression& binding = e->GetBindingExpression();
|
||||
const BindingExpression& binding = GetBindingExpression();
|
||||
if (binding.name.has_value()) {
|
||||
std::cout << *binding.name;
|
||||
out << *binding.name;
|
||||
} else {
|
||||
std::cout << "_";
|
||||
out << "_";
|
||||
}
|
||||
std::cout << ": ";
|
||||
PrintExp(e->GetBindingExpression().type);
|
||||
out << ": " << *binding.type;
|
||||
break;
|
||||
}
|
||||
case ExpressionKind::CallExpression:
|
||||
PrintExp(e->GetCallExpression().function);
|
||||
if (e->GetCallExpression().argument->tag() ==
|
||||
ExpressionKind::TupleLiteral) {
|
||||
PrintExp(e->GetCallExpression().argument);
|
||||
out << *GetCallExpression().function;
|
||||
if (GetCallExpression().argument->tag() == ExpressionKind::TupleLiteral) {
|
||||
out << *GetCallExpression().argument;
|
||||
} else {
|
||||
std::cout << "(";
|
||||
PrintExp(e->GetCallExpression().argument);
|
||||
std::cout << ")";
|
||||
out << "(" << *GetCallExpression().argument << ")";
|
||||
}
|
||||
break;
|
||||
case ExpressionKind::BoolTypeLiteral:
|
||||
std::cout << "Bool";
|
||||
out << "Bool";
|
||||
break;
|
||||
case ExpressionKind::IntTypeLiteral:
|
||||
std::cout << "Int";
|
||||
out << "Int";
|
||||
break;
|
||||
case ExpressionKind::TypeTypeLiteral:
|
||||
std::cout << "Type";
|
||||
out << "Type";
|
||||
break;
|
||||
case ExpressionKind::AutoTypeLiteral:
|
||||
std::cout << "auto";
|
||||
out << "auto";
|
||||
break;
|
||||
case ExpressionKind::ContinuationTypeLiteral:
|
||||
std::cout << "Continuation";
|
||||
out << "Continuation";
|
||||
break;
|
||||
case ExpressionKind::FunctionTypeLiteral:
|
||||
std::cout << "fn ";
|
||||
PrintExp(e->GetFunctionTypeLiteral().parameter);
|
||||
std::cout << " -> ";
|
||||
PrintExp(e->GetFunctionTypeLiteral().return_type);
|
||||
out << "fn " << *GetFunctionTypeLiteral().parameter << " -> "
|
||||
<< *GetFunctionTypeLiteral().return_type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user