Commit Graph
95 Commits
Author SHA1 Message Date
Jon Ross-Perkins c8b30d3eec Split Parse out to its own target. (#3556)
This is mirroring the structure of codegen/codegen.h, lower/lower.h, and
check/check.h. I recently did lex/lex.h, so parse/parse.h is the last.
Now, the directory's main API file is eponymous with the directory.

I could've used a friend function to avoid making the Tree constructor
public, but in other places we make less use of `friend`, just leaving
things public. This felt more consistent, and simple because it only
affects the constructor.
2024-01-03 19:44:05 +00:00
josh11bandChandler Carruth 48c986f52d Start using typed parse node ids in the check stage (#3547)
Goal is to increase type safety, though more work needs to be done (see
added TODOs).

Note that, after this change, check handlers corresponding to deleted
parse node kinds will no longer compile.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-12-29 01:28:09 +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
josh11b 73cf277bdf Test trace output of Tree::VerifyExtractAs, fix found bugs (#3545)
Tests previously uncovered code. Fix uncovered problems:
* formatting of trace output
* package & import directives need to be classified as declarations
* the problem that meant the previous problem wasn't caught by existing
tests (since `Tree::Verify` didn't check that top-level declarations
match `AnyDeclId`, as required by `Tree::ExtractFile()`).
2023-12-28 00:27:53 +00:00
josh11b 29104e212a Do TODO to rename QualifiedDecl -> QualifiedName (#3543)
Renaming since the parse node does not represent a declaration.
2023-12-26 23:12:28 +00:00
josh11b 55d853e17f Fix crash on incomplete constraint (#3542)
Previously would fail with:

```
CHECK failure at toolchain/parse/node_kind.cpp:74: Lex::TokenKind::Error == expected_token_kind || token_kind == expected_token_kind: Created parse node with NodeKind NamedConstraintDecl and has_error 1 for lexical token kind Constraint, but expected token kind Semi
```

Issue found by fuzzing.
2023-12-26 21:48:16 +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
Richard Smith 0a06fceb5f Improve diagnosis of mismatched brackets. (#3282)
Move handling of mismatched brackets out of the main lexing loop into a
separate pass that is only run if there are mismatched brackets This is
done in preparation for using both lookahead and lookbehind to work out
how to match brackets, and to get this code far away from the hot lexing
loop.

Fix bracket insertion location to be immediately after the token that
we're inserting the bracket after, rather than potentially at the end of
a comment. When there are open brackets at the end of the file, say that
there are open brackets, not that there's a closing bracket without a
matching opening bracket.
2023-12-21 08:49:37 +00:00
Richard Smith d87fe8b532 Rename Carbon::StringLiteralId -> Carbon::StringLiteralValueId. (#3522)
We have `StringLiteral`s in multiple other `Carbon` sub-namespaces.
Rename to a more specific name to avoid collisions.

We should likely also rename `Carbon::IntId` -> `Carbon::IntValueId` and
`Carbon::RealId` -> `Carbon::RealValueId`, but this collision is
prioritized because it was blocking work on typed parse nodes which
introduces a `Carbon::Parse::StringLiteralId`.
2023-12-18 23:27:33 +00:00
Jon Ross-Perkins e343ea593c Add macro for postfix operators. (#3504)
Per request on #3481, for consistency with prefix/infix.
2023-12-13 23:54:27 +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
Jon Ross-Perkins 550559e30e On invalid parse nodes, if the token may vary, allow any token. (#3484)
Note #3486 rewrites the macro behavior, and is already approved: so this
PR is only for the changed enforcement during error. Also, #3493 already
changed several things to allow any token while this PR was awaiting
review, but this still changes enforcement for `For` and `If`.

This was brought up on
[#toolchain](https://discord.com/channels/655572317891461132/655578254970716160/1182066616456970251),
and I think this any-on-error approach gets at least some support. We
could try setting it to the introducer, but it's quite possible we want
it to be something like the token which led to the parse error, rather
than a static token. That leads to a conclusion that, most typically,
we'll expect arbitrary tokens when error conditions may lead to tokens
which aren't the expected token.

A couple related, recent `CARBON_IF_ERROR` crash fixes can be found in
#3404 and #3424. Something like #3404 would've been needed regardless
because `namespace` didn't have `CARBON_IF_ERROR` before, although I
might've missed the underlying issue with declarations because only
`namespace` had a relevant test (that is, if #3404 had added
`CARBON_ANY_TOKEN_ON_ERROR`, I wouldn't have had a crash in #3462).
#3424 would've been avoided with this change because there was a
`CARBON_IF_ERROR`, and it was just too restrictive.
2023-12-13 20:28:48 +00:00
Jon Ross-Perkins 7c7afc9e32 Split out infix and prefix operators to separate node kinds. (#3481)
This leaves a single state for each in the expr loop. I was trying to
think through ways to have per-token states, but they felt sort of
bulky.

Note this is more verbose: but I think the long-term is going to be that
when we start wanting to add handlers, we're going to need to switch to
different names based on the token found. As a consequence, the parse
state logic will end up diverging a little, and we'll just want to align
towards boilerplate handlers.

Short-term, this opens up a path for saying that each parse node
corresponds to precisely one token in success states, and separates out
what were becoming big handler functions in check.
2023-12-13 19:52:20 +00:00
Jacob Schneider 6419568142 Fully underline parse nodes in diagnostics. (#3442)
Another incremental change to diagnostic formatting. I simply recurse
over all the tokens in the subtree of a parse node and construct a
`DiagnosticLocation` that covers all of the tokens.

I believe it's nicer for the user to be directed at the entire chunk of
source where the error is occurring rather then just pointing at the
bracketing/terminator tokens, but let me know if you all agree.
2023-12-13 18:43:19 +00:00
Jon Ross-Perkins 6cc5dc7736 Replace the NodeKind StructFieldUnknown with InvalidParse. (#3482)
StructFieldUnknown was used previously for invalid parses. But we have
added other, more common ways of talking about those; so this is
removing the special-case.
2023-12-12 00:43:04 +00:00
Chandler Carruthandjosh11b 6037b11e90 Teach the parser to not crash on the spaceship <=> operator. (#3494)
This remains structurally valid although we don't use this operator or
have a design for it, this at least fixes a fuzzer-found crash.

---------

Co-authored-by: josh11b <josh11b@users.noreply.github.com>
2023-12-11 22:53:07 +00:00
josh11bandJon Ross-Perkins 6067ca3f49 Change return of SkipPastLikelyEnd to be last consumed token (#3493)
This approach means the parse subtree includes the full token range
consumed.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-12-11 22:11:09 +00:00
josh11b 1addf10054 Move add invalid node. Follow up to #3473. (#3491)
I think this matches expectations about how the parse code should be
structured better.
2023-12-11 17:22:17 +00:00
josh11bandJon Ross-Perkins 5f439b842b Parsing impl...as (#3473)
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-12-09 04:04:00 +00:00
Jon Ross-Perkins c4864aa2ff Split out and/or operator handling from infix. (#3480)
This is also doing the parse node split, allowing lower reliance in
formatter on the tokenized buffer (something that I may be touching more
due to import handling).
2023-12-09 01:03:32 +00:00
josh11b b7d129b88c Add PushState overload to combine Parse::State change with StateStackEntry (#3485)
Shortens a common `PushState` pattern
2023-12-08 23:58:30 +00:00
Geoff RomerandRichard Smith 6e65a30b5d Rename ParamList to TuplePattern (#3479)
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-12-08 23:35:47 +00:00
Geoff Romer 5897e57c21 Clarify naming around paren expressions (#3444)
(Split out of #3410)

Consistently use `ParenExpr` solely for parenthesized single
expressions, and use more syntax-oriented terminology for states and
nodes that might represent either a `ParenExpr` or a tuple literal.
2023-12-08 21:46:28 +00:00
Jon Ross-Perkins 50071532fe Refactor state construction and change how the decl loop makes state. (#3467)
Building on #3463. The PushState+PopState to construct a state feels
worth cleanup. The rest is just kind of making it easier to do without
adding another PushState overload.
2023-12-08 17:29:23 +00:00
josh11b 3b0923c81d Add interface support to check (#3474)
Largely copied from the `class` code
2023-12-08 17:13:49 +00:00
2705a32b92 Refactor the decl scope loop to consolidate modifier handling. (#3463)
Building on #3462, trying to make the flow easier to see, also making a
little more use of macros for boilerplate modifier handling.

---------

Co-authored-by: josh11b <josh11b@users.noreply.github.com>
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-12-08 17:04:05 +00:00
Geoff RomerandRichard Smith 39750b9925 Parse support for tuple patterns in var and let (#3448)
Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-12-08 01:16:03 +00:00
Jon Ross-Perkins ef0fa81a58 Upgrade clang-format version (#3471)
This apparently includes a fix for
https://github.com/llvm/llvm-project/issues/47664 (previously
https://bugs.llvm.org/show_bug.cgi?id=48320)

Note this continues with a clang-format version that's different from
the compiler versions we're often using, but the differences in
formatting seem worthwhile.
2023-12-07 19:09:36 +00:00
josh11b 2e29b48d26 Drop GetDeclContext from parse, errors will be diagnosed in check (#3468)
The criteria being enforced is not correct since `final` and `default`
functions in interfaces have definitions.
2023-12-07 16:35:57 +00:00
Richard Smith fe6f7b4330 Rename Name -> IdentifierName given that we have several other kinds of parse nodes that represent names. (#3453)
Factor out common checking handling for the different kinds of
unqualified names
2023-12-07 01:48:14 +00:00
josh11b fa07b52b8b Precedence terminology (#3465) 2023-12-06 23:10:33 +00:00
Jon Ross-Perkins 9b194a31c9 Support modifiers on namespace, in theory. (#3462)
In theory because none are allowed. This is to improve consistency in
handle_decl_name_scope's modifier handling, removing the namespace
special-case.

I noticed there's a crash bug on `impl <declaration>` which I'll address
separately.

This builds on #3461.
2023-12-06 22:45:19 +00:00
Jon Ross-Perkins d73729179a Switch modifiers to use distinct parse nodes. (#3461)
This is supporting a direction that all parse nodes should correspond to
a single token, allowing for reduced tokenized buffer access during
checking (it's still necessary for diagnostics, and some literals).

One of the justifications for a unified parse node was implementation
LOC: note this is slightly smaller, using macros to reduce some
duplication. While this does add more switching in HandleDeclScopeLoop,
that's offset by less explicit switching in the check handlers. Also, I
think the duplication in HandleDeclScopeLoop can be reduced by shifting
the flow there, which I'll do in a separate PR.
2023-12-06 22:14:53 +00:00
josh11b a970b1e587 Require extend before base: BaseType; (#3459) 2023-12-06 20:14:16 +00:00
josh11bandJon Ross-Perkins fada410559 Support declaration modifier keywords (#3412)
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-12-05 22:45:57 +00:00
Richard Smith 7dffa0c7ec Support for base: T;, .base, x.base. (#3450)
No support for `extend base` yet, in an effort to minimize collisions
with #3412.
2023-12-04 22:45:59 +00:00
Jon Ross-Perkins 30155dbb72 Add support for 'package' in expressions. (#3445)
This creates a namespace for `package` scope.

It looks like names of class_decls in namespaces lead to an unexpected
instref. This is already true, as best as I can tell. I'm not sure if
there's a preferred approach to address that, so I've left a TODO for
now.
2023-12-04 21:05:41 +00:00
Geoff Romer b8d4e2f41b Binding pattern naming cleanup (#3410)
- Rename `PatternBinding` to `BindingPattern`.
- Use `BindingPattern` rather than `Pattern` in the names of
binding-pattern-specific parse states.
2023-12-01 21:36:51 +00:00
Richard Smith c6bc2cbb3d Rename IndexBase -> IdBase, ComparableIndexBase -> IndexBase. (#3436)
This reflects how we're naming classes that derive from these classes,
and matches usage for each existing `Id` and `Index` type, except:

- `Parse::NodeId` previously inherited from `ComparableIndexBase`, and
is no longer comparable.
- `SemIR::MemberIndex` previously inherited from `IndexBase`, and is now
comparable.

Making `Parse::NodeId` non-comparable reflects that it's intended to be
an opaque identifier for a node and that the ordering is an
implementation detail rather than part of the intended public interface.
`PostorderIterator` and `SiblingIterator` still rely on the numerical
meaning of `NodeId`s, but that's OK since they're part of the node
implementation.
2023-11-30 18:50:59 +00:00
Jon Ross-Perkins 05723095bc Switch formatv adapters to format_provider (#3434)
The main difference I'm aiming for is that clangd doesn't complain about
the struct being unused, but it does miss the function's use. But really
these are specific to formatv for diagnostics, so this is more clearly
marking such, and probably makes for a better pattern for the future.
2023-11-30 18:33:03 +00:00
Jon Ross-Perkins 0db63ff17a Abbreviate Integer and FloatingPoint (#3435)
I was suggesting this because `FloatingPoint` is pretty long. `int` and
`float` should be familiar abbreviations. `unsigned` should be familiar
to developers too, but `UnsignedInt` still feels usefully clearer for
the additional chars.
2023-11-29 23:29:48 +00:00
Jon Ross-PerkinsandRichard Smith 0d618b1278 Tidy up lint issues. (#3429)
These are manual fixes; mostly from clang-tidy, some from clangd (which
notes unused includes).

In typed_insts, adding inlline due to misc-definitions-in-headers. Per
discussion, clang-tidy is wrong, but inline silences it.

For parameter name skew in definition versus declaration, I'm just using
the name from the definition.

---------

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-11-29 20:41:53 +00:00
Richard Smith eae630a3db Rename Lex::{Token,Line} -> Lex::{Token,Line}Index. (#3433)
As discussed [on
discord](https://discord.com/channels/655572317891461132/655578254970716160/1178878128714678282)
and today's toolchain discussion.
2023-11-29 20:33:58 +00:00
Richard Smith 332a368cee Rename Parse::Node -> Parse::NodeId. (#3432)
As discussed [on
discord](https://discord.com/channels/655572317891461132/655578254970716160/1178878128714678282)
and today's toolchain discussion.
2023-11-29 18:53:12 +00:00
Jon Ross-PerkinsandChandler Carruth 0c0998d7cd Error when passing StringRef to CARBON_DIAGNOSTIC. (#3431)
This gets to a lifetime subtlety, particularly with things like the
sorting diagnostic consumer that delay output. In order to reduce the
chance of accidental references, disallow StringRef in the diagnostics.

For example:

```
./toolchain/diagnostics/diagnostic_emitter.h:162:5: error: static_assert failed due to requirement '!std::is_same_v<llvm::StringRef, llvm::StringRef>' "Use std::string or llvm::StringLiteral for diagnostic lifetimes."
    static_assert(
    ^
toolchain/check/convert.cpp:477:11: note: in instantiation of member function 'Carbon::Internal::DiagnosticBase<std::string, std::string, llvm::StringRef>::DiagnosticBase' requested here
          CARBON_DIAGNOSTIC(StructInitMissingFieldInConversion, Error,
          ^
./toolchain/diagnostics/diagnostic_emitter.h:47:7: note: expanded from macro 'CARBON_DIAGNOSTIC'
      ::Carbon::Internal::DiagnosticBase<__VA_ARGS__>(        \
      ^
```

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-11-29 17:04:11 +00:00
Jon Ross-Perkins 161f46ed37 FloatingPointLiteral to RealLiteral fixup (#3430) 2023-11-29 17:00:03 +00:00
Jon Ross-Perkins 3f208e27f9 Align on FileStart/FileEnd for naming. (#3428)
The lexer has been using EndOfFile form (stemming from EOF), parser went
to FileEnd form. This consolidates on FileEnd form.
2023-11-29 16:36:57 +00:00
Jon Ross-Perkins 35d15a390c Remove nodiscard uses. (#3418)
Per [#toolchain
discussion](https://discord.com/channels/655572317891461132/655578254970716160/1176632520834560211)

We'd at one point been trying to put `[[nodiscard]]` everywhere, but
then we stopped because it had felt verbose without finding many issues
(plus, people plain forgot to add it). Some history in #888.

Since newer code gets added without it, we now have code like:

```
  auto GetLineInfo(Line line) -> LineInfo&;
  [[nodiscard]] auto GetLineInfo(Line line) const -> const LineInfo&;
  auto AddLine(LineInfo info) -> Line;
  auto GetTokenInfo(Token token) -> TokenInfo&;
  [[nodiscard]] auto GetTokenInfo(Token token) const -> const TokenInfo&;
  auto AddToken(TokenInfo info) -> Token;
  [[nodiscard]] auto GetTokenPrintWidths(Token token) const -> PrintWidths;
```

Here, the lack of `[[nodiscard]]` doesn't mean anything: for example,
`GetLineInfo` should not have its result discarded if it's called. But
the mix could be confusing for readers.

As a resolution, remove the attribute. `[[nodiscard]]` should be treated
like other attributes going forward, which essentially means "avoid in
general, add a comment to explain why the attribute is needed" rather
than use-as-default.
2023-11-28 18:46:19 +00:00
josh11b a307e7a72a Rename files to use "expr" and "deref" (#3426)
Follows #3425 and #3375 .
2023-11-28 17:11:35 +00:00