Skip to content

Commit

Permalink
Adding some shape to toolchain semantic analysis (#1092)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonmeow authored Mar 16, 2022
1 parent 50d9fc5 commit bf7159f
Show file tree
Hide file tree
Showing 10 changed files with 325 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
# - performance-unnecessary-value-param is disabled because it duplicate
# modernize-pass-by-value.
Checks:
-*, bugprone-*, -bugprone-easily-swappable-parameters,
-*, bugprone-*, -bugprone-branch-clone, -bugprone-easily-swappable-parameters,
-bugprone-narrowing-conversions, google-*, -google-readability-todo,
misc-definitions-in-headers, misc-misplaced-const, misc-redundant-expression,
misc-static-assert, misc-unconventional-assign-operator,
Expand Down
40 changes: 33 additions & 7 deletions toolchain/semantics/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,45 @@
package(default_visibility = ["//visibility:public"])

cc_library(
name = "semantics",
srcs = ["semantics.cpp"],
hdrs = ["semantics.h"],
name = "function",
hdrs = ["function.h"],
deps = ["//toolchain/parser:parse_tree"],
)

cc_library(
name = "semantics_ir",
srcs = ["semantics_ir.cpp"],
hdrs = ["semantics_ir.h"],
deps = [
":function",
"//common:check",
"//toolchain/lexer:tokenized_buffer",
"//toolchain/parser:parse_tree",
"@llvm-project//llvm:Support",
],
)

cc_library(
name = "semantics_ir_factory",
srcs = ["semantics_ir_factory.cpp"],
hdrs = ["semantics_ir_factory.h"],
deps = [
":semantics_ir",
"//common:check",
"//toolchain/lexer:tokenized_buffer",
"//toolchain/parser:parse_node_kind",
"//toolchain/parser:parse_tree",
"@llvm-project//llvm:Support",
],
)

cc_test(
name = "semantics_test",
name = "semantics_ir_factory_test",
size = "small",
srcs = ["semantics_test.cpp"],
srcs = ["semantics_ir_factory_test.cpp"],
deps = [
":semantics",
"//toolchain/diagnostics:diagnostic_emitter",
":semantics_ir_factory",
"//toolchain/diagnostics:mocks",
"//toolchain/lexer:tokenized_buffer",
"//toolchain/parser:parse_tree",
"//toolchain/source:source_buffer",
Expand Down
31 changes: 31 additions & 0 deletions toolchain/semantics/function.h
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_
15 changes: 0 additions & 15 deletions toolchain/semantics/semantics.cpp

This file was deleted.

25 changes: 0 additions & 25 deletions toolchain/semantics/semantics.h

This file was deleted.

28 changes: 28 additions & 0 deletions toolchain/semantics/semantics_ir.cpp
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, Node 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),
Node(Node::Kind::Function, index));
return functions_[index];
}

} // namespace Carbon
78 changes: 78 additions & 0 deletions toolchain/semantics/semantics_ir.h
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:
// Provides a link back to a semantic node in a name scope.
class Node {
public:
Node() : Node(Kind::Invalid, -1) {}

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,
};

Node(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, Node named_entity);

private:
llvm::SmallVector<Node> ordering_;
llvm::StringMap<Node> name_lookup_;
};

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_
58 changes: 58 additions & 0 deletions toolchain/semantics/semantics_ir_factory.cpp
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
40 changes: 40 additions & 0 deletions toolchain/semantics/semantics_ir_factory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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_FACTORY_H_
#define TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_

#include <optional>

#include "llvm/ADT/StringMap.h"
#include "toolchain/parser/parse_tree.h"
#include "toolchain/semantics/semantics_ir.h"

namespace Carbon {

// The main semantic analysis entry.
class SemanticsIRFactory {
public:
// Builds the SemanticsIR without doing any substantial semantic analysis.
static auto Build(const ParseTree& parse_tree) -> SemanticsIR;

private:
explicit SemanticsIRFactory(const ParseTree& parse_tree)
: semantics_(parse_tree) {}

// Processes the roots of the ParseTree into semantics_, transitively
// handling children.
void ProcessRoots();

// Turns a function node from the parse tree into a semantic function node,
// adding it to the containing scope.
void ProcessFunctionNode(SemanticsIR::Block& block,
ParseTree::Node decl_node);

SemanticsIR semantics_;
};

} // namespace Carbon

#endif // TOOLCHAIN_SEMANTICS_SEMANTICS_IR_FACTORY_H_
Loading

0 comments on commit bf7159f

Please sign in to comment.