mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 20:21:21 +01:00
Ensure all NamedEntities have static types (#968)
This commit is contained in:
@@ -91,9 +91,22 @@ struct GenericBinding : public virtual AstNode, public NamedEntity {
|
||||
auto type() const -> const Expression& { return *type_; }
|
||||
auto type() -> Expression& { return *type_; }
|
||||
|
||||
// The static type of the binding. Cannot be called before typechecking.
|
||||
auto static_type() const -> const Value& { return **static_type_; }
|
||||
|
||||
// Sets the static type of the binding. Can only be called once, during
|
||||
// typechecking.
|
||||
void set_static_type(Nonnull<const Value*> type) { static_type_ = type; }
|
||||
|
||||
// Returns whether the static type has been set. Should only be called
|
||||
// during typechecking: before typechecking it's guaranteed to be false,
|
||||
// and after typechecking it's guaranteed to be true.
|
||||
auto has_static_type() const -> bool { return static_type_.has_value(); }
|
||||
|
||||
private:
|
||||
std::string name_;
|
||||
Nonnull<Expression*> type_;
|
||||
std::optional<Nonnull<const Value*>> static_type_;
|
||||
};
|
||||
|
||||
// The syntactic representation of a function declaration's return type.
|
||||
|
||||
@@ -326,9 +326,25 @@ class Continuation : public Statement, public NamedEntity {
|
||||
auto body() const -> const Block& { return *body_; }
|
||||
auto body() -> Block& { return *body_; }
|
||||
|
||||
// The static type of the continuation. Cannot be called before typechecking.
|
||||
//
|
||||
// This will always be ContinuationType, but we must set it dynamically in
|
||||
// the typechecker because this code can't depend on ContinuationType.
|
||||
auto static_type() const -> const Value& { return **static_type_; }
|
||||
|
||||
// Sets the static type of the continuation. Can only be called once,
|
||||
// during typechecking.
|
||||
void set_static_type(Nonnull<const Value*> type) { static_type_ = type; }
|
||||
|
||||
// Returns whether the static type has been set. Should only be called
|
||||
// during typechecking: before typechecking it's guaranteed to be false,
|
||||
// and after typechecking it's guaranteed to be true.
|
||||
auto has_static_type() const -> bool { return static_type_.has_value(); }
|
||||
|
||||
private:
|
||||
std::string continuation_variable_;
|
||||
Nonnull<Block*> body_;
|
||||
std::optional<Nonnull<const Value*>> static_type_;
|
||||
};
|
||||
|
||||
// A run statement.
|
||||
|
||||
@@ -25,45 +25,15 @@ using llvm::isa;
|
||||
|
||||
namespace Carbon {
|
||||
|
||||
// Sets the static type of `expression`. Can be called multiple times on
|
||||
// Sets the static type of `*object`. Can be called multiple times on
|
||||
// the same node, so long as the types are the same on each call.
|
||||
static void SetStaticType(Nonnull<Expression*> expression,
|
||||
Nonnull<const Value*> type) {
|
||||
if (expression->has_static_type()) {
|
||||
CHECK(TypeEqual(&expression->static_type(), type));
|
||||
// T must have static_type, has_static_type, and set_static_type methods.
|
||||
template <typename T>
|
||||
static void SetStaticType(Nonnull<T*> object, Nonnull<const Value*> type) {
|
||||
if (object->has_static_type()) {
|
||||
CHECK(TypeEqual(&object->static_type(), type));
|
||||
} else {
|
||||
expression->set_static_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the static type of `pattern`. Can be called multiple times on
|
||||
// the same node, so long as the types are the same on each call.
|
||||
static void SetStaticType(Nonnull<Pattern*> pattern,
|
||||
Nonnull<const Value*> type) {
|
||||
if (pattern->has_static_type()) {
|
||||
CHECK(TypeEqual(&pattern->static_type(), type));
|
||||
} else {
|
||||
pattern->set_static_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the static type of `definition`. Can be called multiple times on
|
||||
// the same node, so long as the types are the same on each call.
|
||||
static void SetStaticType(Nonnull<Declaration*> definition,
|
||||
Nonnull<const Value*> type) {
|
||||
if (definition->has_static_type()) {
|
||||
CHECK(TypeEqual(&definition->static_type(), type));
|
||||
} else {
|
||||
definition->set_static_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
static void SetStaticType(Nonnull<ReturnTerm*> return_term,
|
||||
Nonnull<const Value*> type) {
|
||||
if (return_term->has_static_type()) {
|
||||
CHECK(TypeEqual(&return_term->static_type(), type));
|
||||
} else {
|
||||
return_term->set_static_type(type);
|
||||
object->set_static_type(type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -959,7 +929,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull<Statement*> s, TypeEnv types,
|
||||
case StatementKind::Continuation: {
|
||||
auto& cont = cast<Continuation>(*s);
|
||||
TypeCheckStmt(&cont.body(), types, values);
|
||||
types.Set(cont.continuation_variable(), arena_->New<ContinuationType>());
|
||||
SetStaticType(&cont, arena_->New<ContinuationType>());
|
||||
types.Set(cont.continuation_variable(), &cont.static_type());
|
||||
return TCResult(types);
|
||||
}
|
||||
case StatementKind::Run: {
|
||||
@@ -1058,7 +1029,8 @@ auto TypeChecker::TypeCheckFunctionDeclaration(Nonnull<FunctionDeclaration*> f,
|
||||
for (Nonnull<GenericBinding*> deduced : f->deduced_parameters()) {
|
||||
TypeCheckExp(&deduced->type(), types, values);
|
||||
// auto t = interpreter_.InterpExp(values, deduced.type);
|
||||
types.Set(deduced->name(), arena_->New<VariableType>(deduced->name()));
|
||||
SetStaticType(deduced, arena_->New<VariableType>(deduced->name()));
|
||||
types.Set(deduced->name(), &deduced->static_type());
|
||||
AllocationId a = interpreter_.AllocateValue(*types.Get(deduced->name()));
|
||||
values.Set(deduced->name(), a);
|
||||
}
|
||||
@@ -1109,7 +1081,7 @@ auto TypeChecker::TypeCheckFunctionDeclaration(Nonnull<FunctionDeclaration*> f,
|
||||
return TCResult(types);
|
||||
}
|
||||
|
||||
auto TypeChecker::TypeOfClassDecl(const ClassDeclaration& class_decl,
|
||||
auto TypeChecker::TypeOfClassDecl(ClassDeclaration& class_decl,
|
||||
TypeEnv /*types*/, Env ct_top)
|
||||
-> Nonnull<const Value*> {
|
||||
std::vector<NamedValue> fields;
|
||||
@@ -1133,8 +1105,10 @@ auto TypeChecker::TypeOfClassDecl(const ClassDeclaration& class_decl,
|
||||
}
|
||||
}
|
||||
}
|
||||
return arena_->New<NominalClassType>(class_decl.name(), std::move(fields),
|
||||
std::move(methods));
|
||||
SetStaticType(&class_decl,
|
||||
arena_->New<NominalClassType>(
|
||||
class_decl.name(), std::move(fields), std::move(methods)));
|
||||
return &class_decl.static_type();
|
||||
}
|
||||
|
||||
static auto GetName(const Declaration& d) -> const std::string& {
|
||||
@@ -1219,7 +1193,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
}
|
||||
|
||||
case DeclarationKind::ClassDeclaration: {
|
||||
const auto& class_decl = cast<ClassDeclaration>(*d);
|
||||
auto& class_decl = cast<ClassDeclaration>(*d);
|
||||
auto st = TypeOfClassDecl(class_decl, tops->types, tops->values);
|
||||
AllocationId a = interpreter_.AllocateValue(st);
|
||||
tops->values.Set(class_decl.name(), a); // Is this obsolete?
|
||||
@@ -1228,7 +1202,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
}
|
||||
|
||||
case DeclarationKind::ChoiceDeclaration: {
|
||||
const auto& choice = cast<ChoiceDeclaration>(*d);
|
||||
auto& choice = cast<ChoiceDeclaration>(*d);
|
||||
std::vector<NamedValue> alts;
|
||||
for (Nonnull<const AlternativeSignature*> alternative :
|
||||
choice.alternatives()) {
|
||||
@@ -1237,6 +1211,7 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
alts.push_back({.name = alternative->name(), .value = t});
|
||||
}
|
||||
auto ct = arena_->New<ChoiceType>(choice.name(), std::move(alts));
|
||||
SetStaticType(&choice, ct);
|
||||
AllocationId a = interpreter_.AllocateValue(ct);
|
||||
tops->values.Set(choice.name(), a); // Is this obsolete?
|
||||
tops->types.Set(choice.name(), ct);
|
||||
@@ -1249,9 +1224,13 @@ void TypeChecker::TopLevel(Nonnull<Declaration*> d, TypeCheckContext* tops) {
|
||||
// compile-time symbol table.
|
||||
Expression& type =
|
||||
cast<ExpressionPattern>(var.binding().type()).expression();
|
||||
tops->types = TypeCheckPattern(&var.binding(), tops->types, tops->values,
|
||||
std::nullopt)
|
||||
.types;
|
||||
Nonnull<const Value*> declared_type =
|
||||
interpreter_.InterpExp(tops->values, &type);
|
||||
tops->types.Set(*var.binding().name(), declared_type);
|
||||
SetStaticType(&var, declared_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ class TypeChecker {
|
||||
Nonnull<Statement*> body, TypeEnv types, Env values)
|
||||
-> Match::Clause;
|
||||
|
||||
auto TypeOfClassDecl(const ClassDeclaration& class_decl, TypeEnv /*types*/,
|
||||
auto TypeOfClassDecl(ClassDeclaration& class_decl, TypeEnv /*types*/,
|
||||
Env ct_top) -> Nonnull<const Value*>;
|
||||
|
||||
auto TopLevel(std::vector<Nonnull<Declaration*>>* fs) -> TypeCheckContext;
|
||||
|
||||
Reference in New Issue
Block a user