Commit Graph
25 Commits
Author SHA1 Message Date
Jon Ross-Perkins 90b6f5a22c Refactor NodeCategory for X-macros (#5029)
Taking an approach similar to NameId in #5018
2025-02-27 01:00:10 +00:00
Jon Ross-Perkins 21252b5e94 Add missing trailing return types (#5006)
Noted CopyNameFromImportIR while glancing around (this one's interesting
because it's NameId, not void nor auto), did a scan just for a few other
cases. Not an exhaustive fix, and TBH assuming we'd prefer `auto ... ->
auto` since equivalent Carbon syntax would probably be `fn ... -> auto`
2025-02-24 22:41:59 +00:00
Richard Smith 1be726d3a2 Fix NodeCategory printing. (#4983)
Rearrange `NodeCategory` printing so we get a compile-time error for
missing switch cases if it's missing any categories. Add several missing
categories.

In passing, fix some minor things in the `NodeCategory` class
definition, and fix an overly-permissive typed node.
2025-02-20 01:50:42 +00:00
Richard SmithandJon Ross-Perkins 8eb4e24cb6 Implement #4864: Core is a keyword (#4909)
Change representation of package names from `IdentifierId` to
`PackageNameId`, and add a special value `PackageNameId::Core` for the
Core package. Add a `Core` expression to name the Core package, and
support for parsing the `Core` keyword in `package` and `import`
declarations.

For now, I've made no changes to instruction fingerprinting or name
mangling. This means that fingerprints and mangled names will collide
between names in the `Core` package and names in a `r#Core` package. See
#4908.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-02-11 21:33:57 +00:00
Jon Ross-Perkins 1670baf180 Make binary operators non-member (#4838)
Came up on #4831, style:

"For a type T whose values can be compared for equality, define a
non-member operator== and document when two values of type T are
considered equal."
https://google.github.io/styleguide/cppguide.html#Operator_Overloading

Note while we could put some of these out-of-line, it's helpful to keep
them inside the braces:
- For private member access
- For templated cases so that we aren't duplicating templates
- Very mild preference for keeping class's API documented within the
braces
2025-01-23 20:25:06 +00:00
Geoff RomerandJon Ross-Perkins 4f10735751 Track params in the parser (#4777)
This change splits `NodeKind::IdentifierName` into separate node kinds
depending on whether the identifier is followed by parameters, and
similarly splits `NameQualifier` based on whether the qualifier has
parameters. This enables us to only push a pattern block when it's
actually needed, rather than "defensively" pushing one when it might be
needed.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2025-01-10 22:11:07 +00:00
4845f40dff Switch CARBON_CHECK to a format string API (#4285)
This switches `DCHECK` and `FATAL` as well.

The goal is to reduce the code size impact of these assertions so that
we can keep more of them enabled. Currently, the largest cost I see from
`CHECK` is not the actual check or the cold code itself, but actually
the failure to inline trivial functions due to the presence of the cold
code. This means that our goal isn't to reduce apparent code size in the
final binary but the LLVM IR cost assessed for these routines in the
inliner, which closely correlates with code size but is a bit different.

As discussed in #4283, experimentation shows that a single function call
with a minimal number of arguments is the lowest cost model for these.
This is easily achieved with a format-string API that internally uses
`llvm::formatv`. This PR is essentially the `CHECK` version of #4283.

However, the check macros are substantially harder to make work with
both format strings and streaming because they also take a condition.
Also, unexpectedly, I was very successful at devising a regular
expression based automated rewrite from the streaming to the format
string form with only low 10s of manual fixes. This includes compacting
strings broken up across lines, etc. Given how well that went, I've
prepared this PR which just directly switches to the format string API
and migrate everything to use it.

One nice side-effect is that the format string approach ends up greatly
simplifying the implementation here as well.

This is ... *shockingly* effective. Parsing speeds up by more than 3%
with just this change. And checking speeds up by **8%** with this change
alone:
```
BM_CompileAPIFileDenseDecls<Phase::Parse>/256      86.3µs ± 1%  82.9µs ± 1%  -3.94%  (p=0.000 n=17+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/1024      431µs ± 1%   415µs ± 1%  -3.76%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/4096     1.77ms ± 1%  1.71ms ± 1%  -3.18%  (p=0.000 n=18+19)
BM_CompileAPIFileDenseDecls<Phase::Parse>/16384    7.44ms ± 1%  7.17ms ± 2%  -3.56%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/65536    30.7ms ± 1%  29.7ms ± 1%  -3.15%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Parse>/262144    131ms ± 1%   127ms ± 1%  -2.81%  (p=0.000 n=18+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/256       878µs ± 2%   800µs ± 1%  -8.91%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/1024     1.88ms ± 2%  1.72ms ± 1%  -8.56%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/4096     5.78ms ± 2%  5.28ms ± 1%  -8.70%  (p=0.000 n=20+18)
BM_CompileAPIFileDenseDecls<Phase::Check>/16384    21.9ms ± 1%  20.1ms ± 1%  -8.02%  (p=0.000 n=18+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/65536    90.4ms ± 2%  83.1ms ± 1%  -8.04%  (p=0.000 n=19+20)
BM_CompileAPIFileDenseDecls<Phase::Check>/262144    381ms ± 2%   352ms ± 1%  -7.79%  (p=0.000 n=19+19)
```

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
2024-09-12 16:42:08 +00:00
c33c9a02f6 Parse support for where operator (#4275)
Includes support for the `impls`, `=`, and `==` requirement operators to
the right of a `where`, but `and` to allow multiple requirements is
still a TODO.

---------

Co-authored-by: Josh L <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-09-11 03:17:07 +00:00
Brymer Meneses c353f6bd78 change tuple index (#4218)
This changes the tuple index from tuple[0] to tuple.0 in accordance with
the accepted propsal
https://github.com/carbon-language/carbon-lang/pull/3646

I messed up syncing to trunk on my original PR
https://github.com/carbon-language/carbon-lang/pull/4186, that's why I'm
starting on a blank state. Please let me know if I missed incorporating
a change from my prior PR.
2024-08-15 16:06:02 +00:00
Jon Ross-Perkins cda5f66d22 Refactor NodeCategory to provide a class API (#4004)
Mirroring #4003 for NodeCategory.

Note we template a lot more on NodeCategory's enum, so this is a
slightly more awkward delta.

Also, switch from Enum in KeywordModifierSet to RawEnumType for
consistency with EnumBase. The templating on NodeCategory had me
thinking about that more.
2024-05-29 22:47:50 +00:00
419d2e39d8 Move child count and bracketing information for parse nodes into the node kind definition. (#4000)
Instead of tracking the bracketing and child count information in the
kind macro in `node_kind.def`, provide it to `NodeKind::Define` in
`typed_nodes.h`. If a node is both bracketed and has a fixed child
count, track both facts and check them both in tree verification, since
it's easy to do so now.

The overall goal here is to reduce `node_kind.def` down to a simple list
of names. I have a slightly different approach in mind for the token
kinds.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
Co-authored-by: Carbon Infra Bot <carbon-external-infra@google.com>
2024-05-29 20:57:51 +00:00
Richard SmithandJon Ross-Perkins 28170c7867 Parse parameters in name qualifiers. (#3988)
Parse the name of a declaration as a sequence of `NameQualifier`s --
which have a name, possibly parameters, and a trailing period --
followed by a name and possibly parameters. This prepares us for parsing
declarations of members of generic classes and similar cases, but
actually supporting such member redeclarations is left to a future
change.

We previously required functions to have parameters, but no longer do,
following the direction of #3848. Cases like namespaces that can't
actually have parameters are now diagnosed in check instead of in parse.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-05-29 00:47:29 +00:00
Jon Ross-Perkins e66406ec93 Disable bugprone-macro-parentheses and let clang-format insert braces. (#3825)
-
[bugprone-macro-parentheses](https://clang.llvm.org/extra/clang-tidy/checks/bugprone/macro-parentheses.html)
-- this is just a false positive issue, I don't think it's helping us
catch bugs.
-
[InsertBraces](https://clang.llvm.org/docs/ClangFormatStyleOptions.html#insertbraces)
-- although there's a warning about this creating issues due to
incomplete semantic information, it seems to be happy with our code, and
allows clang-format to fix something that clang-tidy would otherwise
warn about.
2024-04-02 11:18:25 +00:00
Richard Smith 3884d3c27e Parse and check support for compound member access. (#3790)
On the parsing side, we treat `a.(b)` as a member access whose second
operand is a `ParenExpr` rather than a `MemberName`. A new node category
is added for the union of `MemberName` and `ParenExpr` to support this.

Checking is mostly reusing the same pieces we already have for simple
member access. Compound member access is in most ways a simplified form
of simple member access because it doesn't need to do any lookup.
2024-03-16 22:38:23 +00:00
Jon Ross-Perkins 86a7c9ff45 Rename parse_node -> node_id (#3760)
This was previously discussed at
https://discord.com/channels/655572317891461132/655578254970716160/1209975051588210729.
I'm initiating this mainly because we typically use "id" suffixes to
indicate an `IdBase` being passed around and the non-id suffix of
`parse_node` suggests at it carrying more data than it actually does.
There used to be more reason for avoiding `node_id` because
`SemIR::InstId` used to be named `NodeId`, but that's no longer
necessary. As a consequence, I'd like to rename `parse_node` to more
precisely reflect its type.

In full, this is doing:

```
parse_node_kind -> node_kind
parse_node -> node_id
ParseNodeCategory -> NodeCategory
ParseNodeKind -> NodeKind
ParseNode -> NodeId
```

This is primarily in check and sem_ir, but with some `parse_node_kind`
references in parse too.

Pluralization is consistent with name forms on both sides, so that
wasn't part of my replacements.
2024-03-09 00:21:29 +00:00
Jon Ross-Perkins 1974e44fd9 Rename factory functions from 'Create' to 'Make' (#3706)
Similar to #3705, we actually have a mix of `Make` and `Create` in
factory functions too, so this PR is normalizing on `Make`. It's
intended to be consistent with the naming choice for Carbon factory
functions.

Note, MakeSyntheticBlock is the only one I feel a little weird about
because llvm's own APIs use Create, and this is essentially wrapping
LLVM calls. But the flipside is it also feels like a vague line to draw,
when we also differ from LLVM coding style in other ways.
2024-02-14 18:26:56 +00:00
Richard SmithandJon Ross-Perkins 0e053703f8 Build Impl entity to represent an impl declaration. (#3683)
Collect the contents of an `impl` into a scope, and start doing very
basic checking for `impl` declarations and definitions.

This change adds two new `Id` types to the set of type that `NodeStack`
supports -- `ImplId` and `NameScopeId`.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2024-02-06 18:49:21 +00:00
josh11bandRichard Smith afd7115c0e Support determining IdKind from NodeCategory, in addition to NodeKind (#3648)
The categories `Expr`, `MemberName`, `Decl`, `Statement`, and `Modifier`
are usable since they are associated with a consistent `IdKind`. The
mapping to `IdKind` for NodeKinds that have those categories are no
longer listed explicitly, ensuring that the `NodeCategory` mapping is
the source of truth.

Also: fixes the category of the `FunctionDefinitionStart` and
`ArrayExprStart` node kinds.

Note: I've added [a section on defining constexpr constants to the
Toolchain architecture
doc](https://docs.google.com/document/d/1RRYMm42osyqhI2LyjrjockYCutQ5dOf8Abu50kTrkX0/edit?resourcekey=0-kHyqOESbOHmzZphUbtLrTw&tab=t.0#heading=h.f7682a2tpvxr).

FUTURE:

* We should switch `TuplePattern` to put an `InstId` on the `NodeStack`
instead of an `InstBlockId`, so we can handle the pattern category.
* We should make a category for names to replace uses of the `NameId`
`IdKind`.
* We should make use of these new APIs more, and propagate more-precise
types through the codebase.

QUESTION: Should I use a different approach for determining the number
of members of the `NodeKind` enum?

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2024-01-27 01:04:01 +00:00
josh11b a602be89e2 Add a MemberName parse node category for member access expressions (#3549)
Use this new category to replace the unconstrained `NodeId` child of
`MemberAccessExpr ` and `PointerMemberAccessExpr`. For now this new
category matches `IdentifierName` and `BaseName`, but later this will be
expanded to support `a.(b.c)` and `p->(b.c)` syntactic forms.

QUESTION: Is it time to make a `node_category.def` x-macro file?
ANSWER: Not yet.
2023-12-28 22:29:30 +00:00
josh11b 83b5db9c1e Make Parse::NodeCategory printable (#3548)
Completes TODO in `parse/extract.cpp`, moving the printing code for
`NodeCategory` out of the implementation of
`Extractable<NodeIdInCategory<T>>`.
2023-12-28 20:04:54 +00:00
2e97f27b8d Typed wrappers around parse tree nodes (#3534)
These are intended to allow the structure of a parse tree node to be
described more precisely in code, to support these use cases:

- Automated checking that the parse tree conforms to the expected
structure. (Added to `Tree::Verify`.)
- Easier reading and understanding of the structure of the parse tree by
toolchain developers. (See `parse/typed_nodes.h`.)
- Easier navigation of the parse tree, for example for tooling uses and
for use when forming diagnostics.

On this last point, an object representing the file may be inspecting
using `Tree::ExtractFile`, as in:
```
auto file = tree->ExtractFile();
for (AnyDeclId decl_id : file.decls) {
  // `decl_id` is convertible to a `NodeId`.
  if (std::optional<FunctionDecl> fn_decl =
      tree->ExtractAs<FunctionDecl>(decl_id)) {
    // fn_decl->params is a `TuplePatternId` (which extends `NodeId`)
    // that is guaranteed to reference a `TuplePattern`.
    std::optional<TuplePattern> params = tree->Extract(fn_decl->params);
    // `params` has a value unless there was an error in that node.
  } else if (auto class_def = tree->ExtractAs<ClassDefinition>(decl_id)) {
    // ...
  }
}
```

The `Extract...` functions collect the child nodes into the typed parse
node's fields (internally using a `Tree::SiblingIterator`) for easy
access. However, this is not as fast as directly observing the tree
structure using the postorder strategy being used by the check stage.

These functions rely on using struct reflection on the typed parse node
definitions from `parse/typed_nodes.h` to get the expected structure of
child nodes and then populate them.

Note that validating these in `Tree::Verify` adds significant cost to
it, and is currently included in the parsing stage. Without this change,
a 10 mloc test case of lex & parse takes 4.129 s ± 0.041 s. With this
change, it takes 5.768 s ± 0.036 s.

This builds upon and completes #3393.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-12-22 22:14:11 +00:00
Jon Ross-Perkins add31eb4e3 Refactor NodeKind to take advantage of a parse node only having one token kind. (#3486)
This builds on the series of changes to NodeKinds, aiming to simplify
the NodeKind implementation a little, also making it clearer that
there's a single associated token for each parse node (or, for
placeholders/invalid parses, not validated).

Note that prior to the relevant changes, there were nodes with multiple
tokens. This change is also locking in the approach of one token per
parse node, by refactoring macros to stop supporting multiple.
2023-12-13 21:03:44 +00:00
josh11b 5020fdb3be Use abbreviation "decl" instead of "declaration" (#3382)
Part of switching to the [abbreviations we've decided to
use](https://docs.google.com/document/d/1RRYMm42osyqhI2LyjrjockYCutQ5dOf8Abu50kTrkX0/edit?resourcekey=0-kHyqOESbOHmzZphUbtLrTw#heading=h.pph7i5m5un7q).

I will rename files in a follow-up PR.
2023-11-10 10:43:25 +00:00
josh11bandRichard Smith a112f2e802 Validate parse nodes correspond to expected tokens (#3295)
Can specify which tokens are allowed generally, and any additional
tokens that only occur when the parse node has an error.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-10-13 21:44:51 +00:00
Jon Ross-Perkins c555b39a2c Rename parser dir to parse (#3178)
Continuing with #3070. Just a dir and file rename (mostly removing
prefixes, although for parse_tree_fuzzer and parse_tree_file_test I'm
dropping "tree" instead of "parse"). Everything in the parse dir should
be marked as a move.
2023-09-01 01:35:45 +00:00