-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Adding some shape to toolchain semantic analysis #1092
Changes from 22 commits
7522567
ab58121
2b261ae
4353804
6428560
fd1af93
f70e5bc
79edb3f
9dbca5c
b35bab6
5474a8c
ceddf6e
0b178ac
965020d
3483dc1
3e4f031
de41ac9
2053bf0
9375743
0400253
0eccb82
ec1ab6d
e413510
01a7fc7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// 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 TOOLCHAIN_SEMANTICS_FUNCTION_H_ | ||
#define TOOLCHAIN_SEMANTICS_FUNCTION_H_ | ||
|
||
#include "toolchain/parser/parse_tree.h" | ||
|
||
namespace Carbon::Semantics { | ||
|
||
// Semantic information for a function. | ||
class Function { | ||
public: | ||
Function(ParseTree::Node decl_node, ParseTree::Node name_node) | ||
: decl_node_(decl_node), name_node_(name_node) {} | ||
|
||
auto decl_node() const -> ParseTree::Node { return decl_node_; } | ||
auto name_node() const -> ParseTree::Node { return name_node_; } | ||
|
||
private: | ||
// The FunctionDeclaration node. | ||
ParseTree::Node decl_node_; | ||
|
||
// The function's DeclaredName node. | ||
ParseTree::Node name_node_; | ||
}; | ||
|
||
} // namespace Carbon::Semantics | ||
|
||
#endif // TOOLCHAIN_SEMANTICS_FUNCTION_H_ |
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// 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/semantics/semantics_ir.h" | ||
|
||
#include "common/check.h" | ||
#include "llvm/Support/FormatVariadic.h" | ||
#include "toolchain/lexer/tokenized_buffer.h" | ||
|
||
namespace Carbon { | ||
|
||
void SemanticsIR::Block::Add(llvm::StringRef name, Token named_entity) { | ||
ordering_.push_back(named_entity); | ||
name_lookup_.insert({name, named_entity}); | ||
} | ||
|
||
auto SemanticsIR::AddFunction(Block& block, ParseTree::Node decl_node, | ||
ParseTree::Node name_node) | ||
-> Semantics::Function& { | ||
int32_t index = functions_.size(); | ||
functions_.push_back(Semantics::Function(decl_node, name_node)); | ||
block.Add(parse_tree_->GetNodeText(name_node), | ||
Token(Token::Kind::Function, index)); | ||
return functions_[index]; | ||
} | ||
|
||
} // namespace Carbon |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
// 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 TOOLCHAIN_SEMANTICS_SEMANTICS_IR_H_ | ||
#define TOOLCHAIN_SEMANTICS_SEMANTICS_IR_H_ | ||
|
||
#include "llvm/ADT/SmallVector.h" | ||
#include "llvm/ADT/StringMap.h" | ||
#include "toolchain/parser/parse_tree.h" | ||
#include "toolchain/semantics/function.h" | ||
|
||
namespace Carbon { | ||
|
||
// Provides semantic analysis on a ParseTree. | ||
class SemanticsIR { | ||
public: | ||
chandlerc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Provides a link back to an entity in a name scope. | ||
class Token { | ||
public: | ||
Token() : Token(Kind::Invalid, -1) {} | ||
chandlerc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private: | ||
friend class SemanticsIR; | ||
|
||
// The kind of token. These correspond to the lists on SemanticsIR which | ||
// will be indexed into. | ||
enum class Kind { | ||
Invalid, | ||
Function, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Whether here or in a future step, I might call this a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll figure out separately if this needs to be separated out -- I was still considering how to determine the body (tempting is having them be the same, with a separation only on the body, particularly if that's how they work syntactically) |
||
}; | ||
|
||
Token(Kind kind, int32_t index) : kind_(kind), index_(index) { | ||
// TODO: kind_ and index_ are currently unused, this suppresses the | ||
// warning. | ||
kind_ = kind; | ||
index_ = index; | ||
} | ||
|
||
Kind kind_; | ||
|
||
// The index of the named entity within its list. | ||
int32_t index_; | ||
}; | ||
|
||
struct Block { | ||
public: | ||
void Add(llvm::StringRef name, Token named_entity); | ||
|
||
private: | ||
llvm::SmallVector<Token> ordering_; | ||
llvm::StringMap<Token> name_lookup_; | ||
}; | ||
chandlerc marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
private: | ||
friend class SemanticsIRFactory; | ||
|
||
explicit SemanticsIR(const ParseTree& parse_tree) | ||
: parse_tree_(&parse_tree) {} | ||
|
||
// Creates a function, adds it to the enclosing scope, and returns a reference | ||
// for further mutations. On a name collision, it will not be added to the | ||
// scope, but will still be returned. | ||
auto AddFunction(Block& block, ParseTree::Node decl_node, | ||
ParseTree::Node name_node) -> Semantics::Function&; | ||
|
||
// Indexed by Token::Function. | ||
llvm::SmallVector<Semantics::Function, 0> functions_; | ||
|
||
// The file-level block. | ||
Block root_block_; | ||
|
||
const ParseTree* parse_tree_; | ||
}; | ||
|
||
} // namespace Carbon | ||
|
||
#endif // TOOLCHAIN_SEMANTICS_SEMANTICS_IR_H_ |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// 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/semantics/semantics_ir_factory.h" | ||
|
||
#include "common/check.h" | ||
#include "llvm/Support/FormatVariadic.h" | ||
#include "toolchain/lexer/tokenized_buffer.h" | ||
#include "toolchain/parser/parse_node_kind.h" | ||
|
||
namespace Carbon { | ||
|
||
auto SemanticsIRFactory::Build(const ParseTree& parse_tree) -> SemanticsIR { | ||
SemanticsIRFactory builder(parse_tree); | ||
builder.ProcessRoots(); | ||
return builder.semantics_; | ||
} | ||
|
||
void SemanticsIRFactory::ProcessRoots() { | ||
for (ParseTree::Node node : semantics_.parse_tree_->roots()) { | ||
switch (semantics_.parse_tree_->node_kind(node)) { | ||
case ParseNodeKind::FunctionDeclaration(): | ||
ProcessFunctionNode(semantics_.root_block_, node); | ||
break; | ||
case ParseNodeKind::FileEnd(): | ||
// No action needed. | ||
break; | ||
default: | ||
FATAL() << "Unhandled node kind: " | ||
<< semantics_.parse_tree_->node_kind(node).name(); | ||
} | ||
} | ||
} | ||
|
||
void SemanticsIRFactory::ProcessFunctionNode(SemanticsIR::Block& block, | ||
ParseTree::Node decl_node) { | ||
llvm::Optional<Semantics::Function> fn; | ||
for (ParseTree::Node node : semantics_.parse_tree_->children(decl_node)) { | ||
switch (semantics_.parse_tree_->node_kind(node)) { | ||
case ParseNodeKind::DeclaredName(): | ||
fn = semantics_.AddFunction(block, decl_node, node); | ||
break; | ||
case ParseNodeKind::ParameterList(): | ||
// TODO: Maybe something like Semantics::AddVariable passed to | ||
// Function::AddParameter. | ||
break; | ||
case ParseNodeKind::CodeBlock(): | ||
// TODO: Should accumulate the definition into the code block. | ||
break; | ||
default: | ||
FATAL() << "Unhandled node kind: " | ||
<< semantics_.parse_tree_->node_kind(node).name(); | ||
} | ||
} | ||
} | ||
|
||
} // namespace Carbon |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it worth separating the validity changes into a separate PR? Not a big deal, looks trivial either way, but would be good to add a unittest to
parse_tree
that covers this?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Split to #1139