Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DumpId() methods to Check::Context, Parse::Tree, Lex::TokenizedBuffer #4620

Closed
wants to merge 17 commits into from
2 changes: 2 additions & 0 deletions toolchain/check/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ cc_library(
"convert.cpp",
"decl_name_stack.cpp",
"deduce.cpp",
"dump_id.cpp",
"eval.cpp",
"function.cpp",
"generic.cpp",
Expand All @@ -46,6 +47,7 @@ cc_library(
"decl_name_stack.h",
"deduce.h",
"diagnostic_helpers.h",
"dump_id.h",
"eval.h",
"function.h",
"generic.h",
Expand Down
15 changes: 12 additions & 3 deletions toolchain/check/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "toolchain/check/decl_introducer_state.h"
#include "toolchain/check/decl_name_stack.h"
#include "toolchain/check/diagnostic_helpers.h"
#include "toolchain/check/dump_id.h"
#include "toolchain/check/generic_region_stack.h"
#include "toolchain/check/global_init.h"
#include "toolchain/check/inst_block_stack.h"
Expand Down Expand Up @@ -58,7 +59,10 @@ struct AccessInfo {
};

// Context and shared functionality for semantics handlers.
class Context {
//
// The DumpIdMethods parent class provides a `DumpId(x)` method for many types
// across the toolchain.
class Context : public DumpIdMethods<Context> {
public:
using DiagnosticEmitter = Carbon::DiagnosticEmitter<SemIRLoc>;
using DiagnosticBuilder = DiagnosticEmitter::DiagnosticBuilder;
Expand Down Expand Up @@ -462,10 +466,15 @@ class Context {
}

auto sem_ir() -> SemIR::File& { return *sem_ir_; }
auto sem_ir() const -> const SemIR::File& { return *sem_ir_; }

auto parse_tree() -> const Parse::Tree& { return sem_ir_->parse_tree(); }
auto parse_tree() const -> const Parse::Tree& {
return sem_ir_->parse_tree();
}

auto tokens() -> const Lex::TokenizedBuffer& { return parse_tree().tokens(); }
auto tokens() const -> const Lex::TokenizedBuffer& {
return parse_tree().tokens();
}

auto node_stack() -> NodeStack& { return node_stack_; }

Expand Down
50 changes: 50 additions & 0 deletions toolchain/check/dump_id.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "toolchain/check/dump_id.h"

#include "common/check.h"
#include "llvm/Support/raw_ostream.h"
#include "toolchain/check/context.h"
#include "toolchain/lex/tokenized_buffer.h"
#include "toolchain/parse/tree.h"
#include "toolchain/sem_ir/file.h"

namespace Carbon::Check {

auto DumpIdImpl(SemIR::LocId loc_id, const Context& context) -> void {
if (!loc_id.is_valid()) {
llvm::errs() << "LocId(invalid)";
return;
}

if (loc_id.is_node_id()) {
auto token = context.parse_tree().node_token(loc_id.node_id());
auto line = context.tokens().GetLineNumber(token);
auto col = context.tokens().GetColumnNumber(token);
const char* implicit = loc_id.is_implicit() ? " implicit" : "";
llvm::errs() << "LocId(";
llvm::errs().write_escaped(context.sem_ir().filename());
llvm::errs() << ":" << line << ":" << col << implicit << ")";
} else {
CARBON_CHECK(loc_id.is_import_ir_inst_id());

auto import_ir_id = context.sem_ir()
.import_ir_insts()
.Get(loc_id.import_ir_inst_id())
.ir_id;
const auto* import_file =
context.sem_ir().import_irs().Get(import_ir_id).sem_ir;
llvm::errs() << "LocId(import from \"";
llvm::errs().write_escaped(import_file->filename());
llvm::errs() << "\")";
}
}

template <>
auto DumpIdMethods<Context>::WriteNewline() const -> void {
llvm::errs() << "\n";
}

} // namespace Carbon::Check
49 changes: 49 additions & 0 deletions toolchain/check/dump_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef CARBON_TOOLCHAIN_CHECK_DUMP_ID_H_
#define CARBON_TOOLCHAIN_CHECK_DUMP_ID_H_

#include "toolchain/lex/token_kind.h"
#include "toolchain/lex/tokenized_buffer.h"
#include "toolchain/parse/tree.h"
#include "toolchain/sem_ir/ids.h"

namespace Carbon::Check {

class Context;

auto DumpIdImpl(SemIR::LocId loc_id, const Context& context) -> void;

// A set of DumpId() overloads that dump an object to stderr, useful for calling
// inside a debugger. These are all exposed as part of the `Check::Context` API.
//
// This class is inherited by `Check::Context`, which provides itself as the
// template parameter. The methods are provided here instead of on `Context`
// directly to avoid cluttering the `Context` class with overloads for every
// dumpable id type.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is a good tradeoff. The clutter of making these methods of Context seems minimal compared to the complexity associated with the CRTP mixin (especially given how many methods Context already has).

template <class Context>
class DumpIdMethods {
static_assert(std::same_as<Context, ::Carbon::Check::Context>);

public:
LLVM_DUMP_METHOD auto DumpId(Lex::TokenIndex token) const -> void {
static_cast<const Context&>(*this).tokens().DumpId(token);
}
LLVM_DUMP_METHOD auto DumpId(Parse::NodeId node_id) const -> void {
static_cast<const Context&>(*this).parse_tree().DumpId(node_id);
}
LLVM_DUMP_METHOD auto DumpId(SemIR::LocId loc_id) const -> void {
DumpIdImpl(loc_id, static_cast<const Context&>(*this));
WriteNewline();
}

private:
// Helper to keep stream includes out of the header file.
auto WriteNewline() const -> void;
geoffromer marked this conversation as resolved.
Show resolved Hide resolved
};

} // namespace Carbon::Check

#endif // CARBON_TOOLCHAIN_CHECK_DUMP_ID_H_
10 changes: 8 additions & 2 deletions toolchain/lex/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -209,8 +209,14 @@ cc_library(

cc_library(
name = "tokenized_buffer",
srcs = ["tokenized_buffer.cpp"],
hdrs = ["tokenized_buffer.h"],
srcs = [
"dump_id.cpp",
"tokenized_buffer.cpp",
],
hdrs = [
"dump_id.h",
"tokenized_buffer.h",
],
deps = [
":character_set",
":helpers",
Expand Down
34 changes: 34 additions & 0 deletions toolchain/lex/dump_id.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "toolchain/lex/dump_id.h"

#include "llvm/Support/raw_ostream.h"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW, to the point about common/ostream.h -- please include it instead of llvm/Support/raw_ostream.h. As noted in common/ostream.h, I'm trying to avoid having people include raw_ostream.h directly, in order to get more consistent behavior.

#include "toolchain/lex/tokenized_buffer.h"

namespace Carbon::Lex {

auto DumpIdImpl(TokenIndex token, const TokenizedBuffer& buffer) -> void {
if (!token.is_valid()) {
llvm::errs() << "TokenIndex(invalid)";
return;
}

auto kind = buffer.GetKind(token);
auto line = buffer.GetLineNumber(token);
auto col = buffer.GetColumnNumber(token);

llvm::errs() << "TokenIndex(kind: ";
kind.Print(llvm::errs());
llvm::errs() << ", loc: ";
llvm::errs().write_escaped(buffer.source().filename());
llvm::errs() << ":" << line << ":" << col << ")";
}

template <>
auto DumpIdMethods<TokenizedBuffer>::WriteNewline() const -> void {
llvm::errs() << "\n";
}

} // namespace Carbon::Lex
41 changes: 41 additions & 0 deletions toolchain/lex/dump_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#ifndef CARBON_TOOLCHAIN_LEX_DUMP_ID_H_
#define CARBON_TOOLCHAIN_LEX_DUMP_ID_H_

#include "toolchain/lex/token_index.h"

namespace Carbon::Lex {

class TokenizedBuffer;

auto DumpIdImpl(TokenIndex token, const TokenizedBuffer& buffer) -> void;

// A set of DumpId() overloads that dump an object to stderr, useful for calling
// inside a debugger. These are all exposed as part of the
// `Lex::TokenizedBuffer` API.
//
// This class is inherited by `Lex::TokenizedBuffer`, which provides itself as
// the template parameter. The methods are provided here instead of on
// `TokenizedBuffer` directly to avoid cluttering the `TokenizedBuffer` class
// with overloads for every dumpable id type.
template <class TokenizedBuffer>
class DumpIdMethods {
static_assert(std::same_as<TokenizedBuffer, ::Carbon::Lex::TokenizedBuffer>);

public:
LLVM_DUMP_METHOD auto DumpId(TokenIndex token) const -> void {
DumpIdImpl(token, static_cast<const TokenizedBuffer&>(*this));
WriteNewline();
}

private:
// Helper to keep stream includes out of the header file.
auto WriteNewline() const -> void;
};

} // namespace Carbon::Lex

#endif // CARBON_TOOLCHAIN_LEX_DUMP_ID_H_
8 changes: 2 additions & 6 deletions toolchain/lex/tokenized_buffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ auto TokenizedBuffer::GetLine(TokenIndex token) const -> LineIndex {
}

auto TokenizedBuffer::GetLineNumber(TokenIndex token) const -> int {
return GetLineNumber(GetLine(token));
return GetLine(token).index + 1;
}

auto TokenizedBuffer::GetColumnNumber(TokenIndex token) const -> int {
Expand Down Expand Up @@ -162,10 +162,6 @@ auto TokenizedBuffer::IsRecoveryToken(TokenIndex token) const -> bool {
return recovery_tokens_[token.index];
}

auto TokenizedBuffer::GetLineNumber(LineIndex line) const -> int {
return line.index + 1;
}

auto TokenizedBuffer::GetNextLine(LineIndex line) const -> LineIndex {
LineIndex next(line.index + 1);
CARBON_DCHECK(static_cast<size_t>(next.index) < line_infos_.size());
Expand Down Expand Up @@ -262,7 +258,7 @@ auto TokenizedBuffer::PrintToken(llvm::raw_ostream& output_stream,
llvm::right_justify(
llvm::formatv("'{0}'", token_info.kind().name()).str(),
widths.kind + 2),
llvm::format_decimal(GetLineNumber(GetLine(token)), widths.line),
llvm::format_decimal(GetLineNumber(token), widths.line),
llvm::format_decimal(GetColumnNumber(token), widths.column),
llvm::format_decimal(GetIndentColumnNumber(line_index), widths.indent),
token_text);
Expand Down
10 changes: 6 additions & 4 deletions toolchain/lex/tokenized_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "toolchain/base/mem_usage.h"
#include "toolchain/base/shared_value_stores.h"
#include "toolchain/diagnostics/diagnostic_emitter.h"
#include "toolchain/lex/dump_id.h"
#include "toolchain/lex/token_index.h"
#include "toolchain/lex/token_kind.h"
#include "toolchain/source/source_buffer.h"
Expand Down Expand Up @@ -83,7 +84,11 @@ class TokenDiagnosticConverter : public DiagnosticConverter<TokenIndex> {
//
// Lexing errors result in a potentially incomplete sequence of tokens and
// `HasError` returning true.
class TokenizedBuffer : public Printable<TokenizedBuffer> {
//
// The DumpIdMethods parent class provides a `DumpId(x)` method for many types
// across the toolchain.
class TokenizedBuffer : public Printable<TokenizedBuffer>,
public DumpIdMethods<TokenizedBuffer> {
public:
// The maximum number of tokens that can be stored in the buffer, including
// the FileStart and FileEnd tokens.
Expand Down Expand Up @@ -156,9 +161,6 @@ class TokenizedBuffer : public Printable<TokenizedBuffer> {
// For example, a closing paren inserted to match an unmatched paren.
auto IsRecoveryToken(TokenIndex token) const -> bool;

// Returns the 1-based line number.
auto GetLineNumber(LineIndex line) const -> int;

// Returns the 1-based indentation column number.
auto GetIndentColumnNumber(LineIndex line) const -> int;

Expand Down
2 changes: 2 additions & 0 deletions toolchain/parse/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -113,11 +113,13 @@ cc_library(
cc_library(
name = "tree",
srcs = [
"dump_id.cpp",
"extract.cpp",
"tree.cpp",
"tree_and_subtrees.cpp",
],
hdrs = [
"dump_id.h",
"tree.h",
"tree_and_subtrees.h",
],
Expand Down
2 changes: 1 addition & 1 deletion toolchain/parse/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ auto Context::PrintForStackDump(llvm::raw_ostream& output) const -> void {

auto Context::PrintTokenForStackDump(llvm::raw_ostream& output,
Lex::TokenIndex token) const -> void {
output << " @ " << tokens_->GetLineNumber(tokens_->GetLine(token)) << ":"
output << " @ " << tokens_->GetLineNumber(token) << ":"
<< tokens_->GetColumnNumber(token) << ": token " << token << " : "
<< tokens_->GetKind(token) << "\n";
}
Expand Down
34 changes: 34 additions & 0 deletions toolchain/parse/dump_id.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include "toolchain/parse/dump_id.h"

#include "llvm/Support/raw_ostream.h"
#include "toolchain/lex/dump_id.h"
#include "toolchain/parse/tree.h"

namespace Carbon::Parse {

auto DumpIdImpl(NodeId node_id, const Tree& tree) -> void {
if (!node_id.is_valid()) {
llvm::errs() << "NodeId(invalid)";
return;
}

auto kind = tree.node_kind(node_id);
auto token = tree.node_token(node_id);

llvm::errs() << "NodeId(kind: ";
kind.Print(llvm::errs());
llvm::errs() << ", token: ";
Lex::DumpIdImpl(token, tree.tokens());
llvm::errs() << ")";
}

template <>
auto DumpIdMethods<Tree>::WriteNewline() const -> void {
llvm::errs() << "\n";
}

} // namespace Carbon::Parse
Loading
Loading