Commit Graph
40 Commits
Author SHA1 Message Date
Richard SmithandChandler Carruth 1013d1773c Model function calls as initializing expressions (#3089)
Start treating function calls as initializing expressions instead of as
value expressions.

This required adding support for expression categories. Value bindings
and temporary materialization conversions are created where necessary to
transition between expression categories. For a function call with a
return slot, we speculatively create a materialized temporary before the
call and either commit to it or replace it with something else later,
once we see how the function call expression is actually used.

This change follows the direction suggested in #3133 for initializing
expressions: depending on the return type of a function, the return
value will either be initialized in-place or returned directly. This is
visible in the semantics IR, which is a little unfortunate but is
probably necessary as this is part of the semantics of the program.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-08-24 19:35:07 +00:00
Jon Ross-Perkins 2425e28e3a Collapse names into VarStorage (#3116)
This removes BindName, putting name information directly on VarStorage.
As a side-effect of updating semantics_ir_test for this change, I also
noted that function bodies were being generated as invalid YAML so am
fixing that (just `{}` to `[]` bracketing, otherwise the test wouldn't
work anymore).

Because names are now available, I've updated lowering to use them for
vars.

In the SemIR formatter, the name is now repeated because it's a
parameter to VarStorage. I believe this is just default behavior, and
we'd have to special-case VarStorage to remove it because it's automatic
argument printing in action. On the balance, it felt like letting it
print was reasonable.

I've noted in places that the name on VarStorage is expected to be
optional, but am not adding support because I'd have no way of testing
it at present.
2023-08-22 18:55:31 +00:00
Richard Smith d74b8f0497 Fix diagnostic messages that don't end in a period. (#3127) 2023-08-21 23:59:18 +00:00
Richard Smith 6e01b90394 Rename some semantics nodes and some IR names to make them match better. (#3085) 2023-08-10 21:48:50 +00:00
Richard SmithandChandler Carruth 6cbf280a68 Add formatted textual IR output (#3056)
Add a textual IR format to the toolchain.

The exact details of the format are somewhat arbitrary right now, and I
expect them to change as we refine the semantics IR model, but at the
moment they're somewhat directly following the current structure of the
IR.

Semantics tests currently test both the "raw" format, which shows the
details of the representation, and the textual format, which is somewhat
higher level. We may want to revisit that decision once the textual
format is a bit more stable, and test only the textual format in most of
these tests, but for now it seems prudent to keep both sets of tests.

---------

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-08-10 19:41:39 +00:00
Richard Smith 212188a922 Prefer to put STDOUT CHECK at the end of the file. (#3073)
Allow interleaving of STDOUT and STDERR check lines. Put STDOUT lines
after the line they're attached to, and STDERR lines before. If no
STDOUT check line is attached to any line, then put them all at the end
of the file instead.

This is intended to better handle the case where stdout contains
unreplaced mentions of line numbers, and also reflects that stdout is
typically a consequence of the test rather than commentary on it, so
placing it after the test seems likely to read better.
2023-08-08 19:51:52 +00:00
Richard Smith 90d2d7ef65 Fix some minor errors in diagnostic text. (#3047) 2023-08-02 18:17:16 +00:00
Richard SmithandJon Ross-Perkins 0c33dead70 Remove the type field from semantics nodes that don't produce values of that type. (#3049)
For `Assign` and `ReturnExpression`, this field wasn't used for
anything. For `StructTypeField`, we stored the type of the field here,
and now store it as an argument of the node instead.

---------

Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-08-02 17:30:27 +00:00
db5e269097 Removed builtin empty tuple type (#3021)
Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
Co-authored-by: Jon Ross-Perkins <jperkins@google.com>
2023-07-27 21:17:29 +00:00
Richard Smith 35ccac5125 Semantics and lowering for type keyword and type values. (#3022)
Also switch from modeling type values as `i1` to modeling them as an
empty struct. We don't need any runtime representation for types, as
there are no runtime operations on them, so an empty struct seems like a
good representation.
2023-07-25 21:49:45 +00:00
Jon Ross-Perkins 65a4e006a2 Add line output to diagnostics to help identify error locations. (#3010)
This also makes the filename a reference to the buffer since the line
seems better to have as a reference (versus copying a string per error).
Most tests now have different line deltas due to the extra output, but
the actual errors should overall stay the same.

Some of the error locations look like they could be improved, but this
change is only making it clear where they were before.
2023-07-21 23:53:36 +00:00
Farzana Ahmed SiddiqueandFarzana Ahmed Siddique 6a81a3396e Updated tests for tool chain to incorporate type blocks (#3008)
Co-authored-by: Farzana Ahmed Siddique <fasiddique@google.com>
2023-07-21 17:36:24 +00:00
Jon Ross-Perkins bc84f109fe Rename semantics InvalidType to Error (#2975)
Following up on zygoloid's request [on
#2940](https://github.com/carbon-language/carbon-lang/pull/2940#discussion_r1253522564)
2023-07-06 22:30:56 +00:00
Jon Ross-Perkins 918c089e03 Add namespace support. (#2940)
This handles namespacing of functions. Parsing and semantics are changed
significantly, while lowering works without changes. Variables can't be
namespaced yet because they're dealing with patterns, and I didn't dig
through that code.

Most of the logic is done through the new name declaration stack, which
is necessary because semantics isn't quite sure where the declaration
name ends. It'd be complex for parsing to send a signal about this,
probably involving node variants and rewrites of the tree, and this
solution seems to work well. Unfortunately this means a new stack, but
that may be inevitable due to the extra information needing to be
tracked.

Note this doesn't deal with scoped lookups of non-namespace things,
which we'll need for generics. That'll probably involve pushing resolved
scopes onto a stack (or maybe just setting a singleton value?) to affect
contextual name lookup. But, I think the basics are there to make it
work when we can test the behavior.

This renames "designator expression" to "qualified expression" and adds
"qualified declaration" in order to use terminology more consistent with
C++.

Namespaces will probably need to be considered for name mangling down
the line, but this still uses the basic name.
2023-07-06 20:43:40 +00:00
Richard Smith 4b69264cb1 Add implied return; at end of non-value-returning functions. (#2942)
Add validation that every code block in a function is terminated by a sequence of terminating instructions, and that terminators don't appear anywhere else in code blocks.

This required tracking whether we're in a reachable code block. That's done on the fly when we create a new code block; the new `SemanticsNodeBlockId::Unreachable` is used to represent the case where we're not actually creating a code block because we're in unreachable code.
2023-06-26 15:17:47 -07:00
Richard Smith b908c6e274 Track the list of blocks that form the body of a function. (#2941)
Use that list for lowering in lexical order, instead of rediscovering
the list based on which blocks are referenced as branch targets.
2023-06-23 08:36:13 -07:00
Jon Ross-Perkins 39f7aae98d Sorting out how bindings are added to name lookup. (#2869)
This shifts logic so that bindings are added to name lookup only after the scope is complete, removing logic around adding/removing/re-adding names in certain scopes.

This does mean that things like a function's forward declaration will need to go through an extra hoop for name conflict checks, because under this approach a function definition does conflict checking when it adds names for the body's use. But, that seems easy to address, and better than the current hoops.
2023-06-01 16:50:34 -07:00
Jon Ross-Perkins 1497e1333d Switch types to a SemanticsTypeId. (#2854)
This switches types to using SemanticsTypeId instead of SemanticsNodeId, and lowering pre-builds its list of types. The empty tuple type is special-cased because we don't want to emit it unless it's in-use, but as the implicit return for functions, it's frequently used. Callables use invalid to indicate the implicit return, and that seems undesirable to change due to the size increase.
2023-05-26 11:19:49 -07:00
Jon Ross-Perkins 1d56e165ef Start refactoring type handling to track which types are in-use. (#2848)
This is the first step to refactoring types into a SemanticsTypeId. This only tracks what's in-use, but as a consequence starts funneling type information through in ways similar to how I'd want it to do SemanticsTypeId.
2023-05-26 10:16:38 -07:00
Jon Ross-Perkins e73207429f Adjust handling of values in calls and structs (#2824)
Previously, IR for arguments in calls and struct values was separated out. This merges it back in. Additionally, parameters for functions and struct types had their own IR; the block is still there, but there's a TODO to decide what to do with it.

In the LLVM IR, this has the consequence of emitting expressions that are inputs to a call or struct value within the scope of the function, which is pretty much where it should be. Importantly it happens before the call is encountered.

This change also tinkers with the int and real literal lowering. I'm pretty sure both are still wrong, but was having trouble figuring out a "better" way to do it, and this seems like it'll work for now.
2023-05-18 11:42:03 -07:00
Jon Ross-Perkins 6b7a522b3f Provide local paths for file tests. (#2830)
The intent of this change is that instead of paths looking like `explorer/testdata/foo/bar.carbon` (repo-relative), they're now just `bar.carbon` (local). The consequence is that paths should be a bit more durable in various environments, and just paths should be shorter and easier to read.

The explorer's prelude is an exception to this since it comes from data, rather than being the test target. Due to the change in approaches, it needs the regex again.

Uses #2829
2023-05-18 10:20:51 -07:00
Jon Ross-PerkinsandChandler Carruth e4a04c2936 Use new test framework in toolchain to reduce per-test overhead (#2821)
This builds on #2814 by adding the test framework to the toolchain. On Linux, this is 7s -> 4s for me. #2811 has more detailed timing for the explorer, which also had more dramatic changes because it's about 3x more tests run in 2x as many ways (6x total).

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2023-05-12 10:40:22 -07:00
Jon Ross-Perkins 7824e9618c Consolidate towards ImplicitAs handling. (#2719)
This eliminates the older TryTypeConversion approach in favor of the ImplicitAs logic. This makes `return {}` work correctly.
2023-03-31 08:11:17 -07:00
Jon Ross-Perkins 2eef8c751b Add semantics for struct type and value literals. (#2709)
This handles the basics of type and value for structs. Structurally, these look like parameters and arguments (respectively) because expressions/generics may result in multiple IR nodes being generated.

Because `{}` needs to be cast to a type for storage, I'm also adding some validation that's not specific to `{}`, e.g. that `1` shouldn't be valid as a type for storage (previously, nothing errored for that).

This adds more stringification of types, particularly literals, because they come up in value errors now.

ImplicitAs is the result of me mulling whether I'm taking the right approach on type conversions. I think it needs to return a value so that if the implicit cast rewrites the value, the result is accessible to the caller. I may reorient the current TryTypeConversion logic to be more based on the ImplicitAs logic.
2023-03-30 10:15:11 -07:00
Jon Ross-Perkins c615d76196 Add stringification for nodes. (#2704)
This is used to make error messages more readable. It'll be particularly important as more complex types are added.
2023-03-22 14:55:53 -07:00
Jon Ross-Perkins 4ca2e81877 Modify SemanticsIR printing to produce stable output on builtin changes. (#2702)
These changes should make output more stable when builtins are added to semantics. By omitting them from nodes and printing nodes as "relative to the last builtin", I should be able to add and remove builtins without automatically affecting every test. Also by printing builtin nodes as `nodeNameOfBuiltin`, it's a little easier to understand what's going on (for me, at least).
2023-03-22 10:24:03 -07:00
Jon Ross-Perkins 32e8fee4ad Add initial lowering of a trivial function (#2640)
This is starting to build out actual lowering logic, for a really simple `fn Main() -> i32 { return 0; }`

Notes for achieving this:

- In semantics, currently function names are bound separate from the signature. When emitting IR, this turns out to be inconvenient because we want to know the name when we process the declaration and the definition. This change addresses that by merging the name into the FunctionDeclaration node, which is also accessible from the definition. It removes the separate BindName. This should be the cause of all the test changes in semantics, because the IR generated changes.

- Add a "Lowering" class which I'm using to hold the llvm builder state. This class now has minimal support for the SemanticsIR generated by the above example.

- In the "Lowering", values from expressions are stored in a DenseMap. I'll keep thinking about whether there's a cleaner way to achieve this, and I'd call it a temporary solution for now. However, this is how the `0` in `return 0` gets properly associated across SemanticsIR instructions, and it'll frequently be an issue in less trivial cases.
2023-02-28 11:30:20 -08:00
Jon Ross-PerkinsandRichard Smith f7924aa93f Implement calls in the toolchain. (#2582)
This adds tracking of call information plus basic type checking. It adds a builtin for the empty tuple, mainly so that I have the basis for a default function return type.

As an aside, it also unifies printing within SemanticsIR, fixing a missing comma after callables.

Co-authored-by: Richard Smith <richard@metafoo.co.uk>
2023-02-13 16:15:04 -08:00
Jon Ross-Perkins 22d7cd19ed Polish out support for reals and strings. (#2593)
Reals were mostly handled, but this PR adds storage of them. It also switches a little towards the FloatingPointType semantic from TokenizedBuffer.

While real literals like `1.0` were handled, the type literals were not. This just adds `f64`, similar to how I also only support `i32`.

The String type literal wasn't used, so I've added support in lexer and parser. Per discussion with @zygoloid String might be renamed based on the newer type literal plan, but it's still String in explorer and the design, so this is just consistent.

The builtin_types.carbon tests the three basic types that are there right now. The test is added to both parser and semantics so that it's clear what the state is in both stages.
2023-02-13 08:04:49 -08:00
Jon Ross-Perkins aa307b1144 Fix CrossReference to use NodeId instead of NodeBlockId. (#2597)
Probably a mistake from when this was referencing a node within a block instead of a node directly.
2023-02-10 11:59:19 -08:00
Jon Ross-Perkins 94cbb9d917 Make function definitions allocate the body more lazily. (#2557)
Lazy allocation means that we can use a single node block for _all_ empty node blocks. The change in timing for when the definition node is emitted shouldn't affect semantic correctness; the signature is already present for recursive calls.
2023-01-27 11:46:12 -08:00
Jon Ross-Perkins 6feed2ae33 Add tracking of function parameters (#2552)
For parameters (and in the future, arguments too; generally comma-separated lists) track two node blocks:

1. param_ir: The complete IR.
2. param_refs: Nodes within the IR that are the "root" parameter.

param_refs should allow quick counting of the # of parameters, and more efficient comparison of call args with function parameters. param_ir should be necessary to generate the actual signature.

In order to construct this, this refactors the node_block_stack into its own class, which is reused in params_stack. These carry references to the underlying SmallVector for lazy modification in order to avoid a dependency cycle with SemanticsIR (also see notes on empty node blocks below).

When finalized, the block pair is pushed onto finished_params_stack. That's because node_stack only has space for one thing, and this is two things -- so I'm essentially choosing a trade-off of adding another stack in order to avoid consuming more space in the expectation that most parse nodes have 0 or 1 things to return, and 2 will be very rare.

As factored, this currently consolidates most empty node blocks into a single canonical empty node block. This is because I think empty blocks, i.e. `()`, will be very common. In order to achieve this, SemanticsNodeBlockStack does lazy creation.

An alternative approach would have been to use 1 node block per parameter. We decided against this in order to reduce the number of vectors being created.
2023-01-26 14:30:38 -08:00
Jon Ross-Perkins a1f2d6341f Switch SemanticsIR dumps to produce YAML (#2517)
The parser and lexer already produce YAML, so this is fundamentally a consistency issue. I've been thinking about this, and was looking again because I'm working on adding callables, and figured I'd just fix it now.
2023-01-18 17:43:17 -08:00
Jon Ross-Perkins 11deb14dc6 Handle var init-with-self situations. (#2488)
The problem I'm trying to solve is: `var x: i32 = x;`. This change makes it so that name lookup fails, by removing `x` from name lookup between the `=` and `;`.

`var x: i32` still adds to name lookup to handle future situations like `var (x: i32, x: i32);` which is still a redefinition of `x`; if we don't add `x` to name lookup, it gets harder to catch that example.

The VariableDeclaration/VariableInitializer refactor in ParseTree supports this by given a bracketing-like structure for semantics to cue that it's entering an initialization expression. With this, VariableInitializer can remove the name lookup and queue it to be restored. VariableDeclaration doesn't need to change too much since it's still bracketed by VariableIntroducer, and so we just traverse slightly differently.

Note this also incidentally changes a little about NameReference, that it's returning the storage consistently instead of the name. You can see this e.g. in global_lookup.carbon, `Assign(node8, node4): node2;` using node4 (VarStorage) instead of Node5 (BindName). Really either _could_ work, since from a BindName we can get to the VarStorage, and that may be reason to switch later if we find it preferable to have the BindName for whatever reason.

But the *actual* value in NameLookup is a BindName so that errors can associate with the _name_ instead of the "storage" parse node, which is currently the `:`. This is mainly for fail_duplicate_decl.carbon, which has a "Previous definition" note that points at the storage's parse node.
2022-12-28 12:55:40 -08:00
Jon Ross-PerkinsandChandler Carruth 6c9b7cba55 Add a DiagnosticBuilder to support context on diagnostics. (#2490)
This is currently used once for PreviousDefinition in semantics.

This PR doesn't just add a builder, it also adds support to the emitter itself to collect notes attached to a diagnostic, and to the consumers and emitters to print all of them.

Co-authored-by: Chandler Carruth <chandlerc@gmail.com>
2022-12-28 10:24:19 -08:00
Jon Ross-Perkins e5d49f5989 Store SemanticsNode in a single list instead of per-block (#2475)
This switches to single list storage of SemanticsNode. The driving motivation behind this is to simplify cross-references within a given IR. Types of nodes will frequently refer to other blocks. This causes a significant increase in the number of cross-references, which can become difficult to manage (and reason about). By reducing to a single list of nodes, cross-references are only needed when crossing IR boundaries.

Because cross-references now only have 2 things to track (IR and index), they can be a regular SemanticsNode and don't need further indirection. This wasn't motivating, but feels like it reinforces the simplification.

Note this isn't being used to deduplicate nodes, at least right now. That could lead to difficult-to-update situations, but also most nodes are associated with the underlying ParseTree::Node in order to track sources for diagnostics; as a consequence, nodes representing equal text in different source locations wouldn't be the same node. There may be future opportunities here, discussed with @zygoloid, but no action is taken at present.

We may eventually want to switch the storage of NodeBlocks to have `[start, end)` ranges instead of individual numbers, but I'm leaving that alone for now.

As an aside, I noticed I was accidentally overloading the copy constructor on SemanticsIR. I've added some disambiguation on that, but am not deleting the copy constructor per style advice (even though the type should never be copied due to storage size).

codespell tries to change `CrossReference -> cross-reference` so disabling it there.
2022-12-21 13:13:13 -08:00
Jon Ross-Perkins 9d234aa7e7 Start doing name lookup for references (#2472)
When binding a name, add it to name lookup. On NameReference nodes, use name lookup.

- Switches from "identifiers" to the more generic "strings". Not strictly necessary here, but it's the overall direction I think we've agreed upon and wanted to do it while building more support out.
- Starts doing deduplication of strings.
- On BindName, registers names with name lookup.
- Does name lookup based on the deduplicated string.
  - Per discussion with zygoloid, design is intended to be constant-time lookup regardless of the number of parent scopes.
- Adds scopes so that we can track names which will be deregistered from lookup.
2022-12-20 10:10:23 -08:00
Jon Ross-Perkins 8e6d48004b Have the driver return errors on SemanticsIR errors. (#2471)
This does a high level check on diagnostics in order to be minimally invasive on the semantics code.
2022-12-16 15:51:00 -08:00
Jon Ross-Perkins 6c248ea38f Add support for VariableDeclaration and VariableInitialization (#2466)
This starts dealing with assignment for the initializer, please let me know if you have thoughts there (including for naming).
2022-12-14 13:42:53 -08:00
Jon Ross-Perkins 30960d11a9 Start adding var decls to semantics. (#2447)
This is just the declaration, without initialization. Partly breaking it out because I'm changing the placeholder builtin types.

Might also need to separate out storage of the var from the name bind.
2022-12-07 15:10:42 -08:00