Start drafting out semantic type checking. (#2406)

This is a first pass at what semantic type checking might look like. Types propagate along nodes, we use an InvalidType object when there's an error, and once there's an InvalidType we stop doing so much type checking.

This adds some RealLiteral handling in order to get type mismatches. I'm cautious about creating some real value for SemanticsIR (since the tokenized buffer version is a bit constrained), so I'm not doing that yet. But I will probably need to in order to maintain SemanticsIR having hermetic copies of its data, without a parse tree dependency.
This commit is contained in:
Jon Ross-Perkins
2022-11-17 13:36:40 -08:00
committed by GitHub
parent c9a1e351ba
commit 4c8fdf5124
23 changed files with 298 additions and 55 deletions
+33 -14
View File
@@ -20,23 +20,36 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
semantics.cross_references_.resize_for_overwrite(
SemanticsBuiltinKind::ValidCount);
// TODO: The type-type should be replaced with a constraint. It will probably
// remain a builtin, just reimplemented as equivalent to `constraint type {}`.
auto builtin_type_type = semantics.AddNode(
constexpr int32_t TypeOfTypeType = 0;
auto type_type = semantics.AddNode(
block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::TypeType(),
SemanticsNodeId(0)));
SemanticsNodeId(TypeOfTypeType)));
semantics.cross_references_[SemanticsBuiltinKind::TypeType().AsInt()] =
SemanticsCrossReference(BuiltinIR, block_id, builtin_type_type);
CARBON_CHECK(builtin_type_type.id == 0)
SemanticsCrossReference(BuiltinIR, block_id, type_type);
CARBON_CHECK(type_type.id == TypeOfTypeType)
<< "TypeType's type must be self-referential.";
auto builtin_int32 = semantics.AddNode(
block_id,
SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::IntegerLiteralType(),
builtin_type_type));
constexpr int32_t TypeOfInvalidType = 1;
auto invalid_type = semantics.AddNode(
block_id, SemanticsNode::MakeBuiltin(SemanticsBuiltinKind::InvalidType(),
SemanticsNodeId(TypeOfInvalidType)));
semantics.cross_references_[SemanticsBuiltinKind::InvalidType().AsInt()] =
SemanticsCrossReference(BuiltinIR, block_id, invalid_type);
CARBON_CHECK(invalid_type.id == TypeOfInvalidType)
<< "InvalidType's type must be self-referential.";
auto integer_literal_type = semantics.AddNode(
block_id, SemanticsNode::MakeBuiltin(
SemanticsBuiltinKind::IntegerLiteralType(), type_type));
semantics
.cross_references_[SemanticsBuiltinKind::IntegerLiteralType().AsInt()] =
SemanticsCrossReference(BuiltinIR, block_id, builtin_int32);
SemanticsCrossReference(BuiltinIR, block_id, integer_literal_type);
auto real_literal_type = semantics.AddNode(
block_id, SemanticsNode::MakeBuiltin(
SemanticsBuiltinKind::RealLiteralType(), type_type));
semantics.cross_references_[SemanticsBuiltinKind::RealLiteralType().AsInt()] =
SemanticsCrossReference(BuiltinIR, block_id, real_literal_type);
CARBON_CHECK(semantics.node_blocks_.size() == 1)
<< "BuildBuiltins should only produce 1 block, actual: "
@@ -47,10 +60,16 @@ auto SemanticsIR::MakeBuiltinIR() -> SemanticsIR {
auto SemanticsIR::MakeFromParseTree(const SemanticsIR& builtin_ir,
const TokenizedBuffer& tokens,
const ParseTree& parse_tree,
DiagnosticConsumer& consumer,
llvm::raw_ostream* vlog_stream)
-> SemanticsIR {
SemanticsIR semantics(builtin_ir);
SemanticsParseTreeHandler(tokens, parse_tree, semantics, vlog_stream).Build();
TokenizedBuffer::TokenLocationTranslator translator(
&tokens, /*last_line_lexed_to_column=*/nullptr);
TokenDiagnosticEmitter emitter(translator, consumer);
SemanticsParseTreeHandler(tokens, emitter, parse_tree, semantics, vlog_stream)
.Build();
return semantics;
}
@@ -62,8 +81,8 @@ auto SemanticsIR::Print(llvm::raw_ostream& out) const -> void {
out << "cross_references = {\n";
for (int32_t i = 0; i < static_cast<int32_t>(cross_references_.size()); ++i) {
out.indent(Indent);
out << SemanticsNodeId::MakeCrossReference(i) << " = \""
<< cross_references_[i] << "\";\n";
out << SemanticsNodeId::MakeCrossReference(i) << " = "
<< cross_references_[i] << ";\n";
}
out << "},\n";