Store named constant values in the AST (#1011)

This enables us to stop using `Env` in the typechecker. As a byproduct, this commit also restructures the interpreter to handle run-time global initialization as part of ordinary execution, using the Action stack.
This commit is contained in:
Geoff Romer
2022-01-13 11:07:28 -08:00
committed by GitHub
parent d88f95ad31
commit 461e178273
15 changed files with 309 additions and 242 deletions
+44
View File
@@ -108,11 +108,22 @@ class GenericBinding : public AstNode {
auto has_static_type() const -> bool { return static_type_.has_value(); }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return constant_value_;
}
// Sets the value returned by constant_value(). Can only be called once,
// during typechecking.
void set_constant_value(Nonnull<const Value*> value) {
CHECK(!constant_value_.has_value());
constant_value_ = value;
}
private:
std::string name_;
Nonnull<Expression*> type_;
std::optional<Nonnull<const Value*>> static_type_;
std::optional<Nonnull<const Value*>> constant_value_;
};
// The syntactic representation of a function declaration's return type.
@@ -232,6 +243,16 @@ class FunctionDeclaration : public Declaration {
auto body() -> std::optional<Nonnull<Block*>> { return body_; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return constant_value_;
}
// Sets the value returned by constant_value(). Can only be called once,
// during typechecking.
void set_constant_value(Nonnull<const Value*> value) {
CHECK(!constant_value_.has_value());
constant_value_ = value;
}
private:
std::string name_;
@@ -239,6 +260,7 @@ class FunctionDeclaration : public Declaration {
Nonnull<TuplePattern*> param_pattern_;
ReturnTerm return_term_;
std::optional<Nonnull<Block*>> body_;
std::optional<Nonnull<const Value*>> constant_value_;
};
class ClassDeclaration : public Declaration {
@@ -259,10 +281,21 @@ class ClassDeclaration : public Declaration {
auto members() const -> llvm::ArrayRef<Nonnull<Member*>> { return members_; }
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return constant_value_;
}
// Sets the value returned by constant_value(). Can only be called once,
// during typechecking.
void set_constant_value(Nonnull<const Value*> value) {
CHECK(!constant_value_.has_value());
constant_value_ = value;
}
private:
std::string name_;
std::vector<Nonnull<Member*>> members_;
std::optional<Nonnull<const Value*>> constant_value_;
};
class AlternativeSignature : public AstNode {
@@ -312,10 +345,21 @@ class ChoiceDeclaration : public Declaration {
}
auto value_category() const -> ValueCategory { return ValueCategory::Let; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return constant_value_;
}
// Sets the value returned by constant_value(). Can only be called once,
// during typechecking.
void set_constant_value(Nonnull<const Value*> value) {
CHECK(!constant_value_.has_value());
constant_value_ = value;
}
private:
std::string name_;
std::vector<Nonnull<AlternativeSignature*>> alternatives_;
std::optional<Nonnull<const Value*>> constant_value_;
};
// Global variable definition implements the Declaration concept.
+5
View File
@@ -61,6 +61,7 @@ class Pattern : public AstNode {
auto has_static_type() const -> bool { return static_type_.has_value(); }
// The value of this pattern. Cannot be called before typechecking.
// TODO rename to avoid confusion with BindingPattern::constant_value
auto value() const -> const Value& { return **value_; }
// Sets the value of this pattern. Can only be called once, during
@@ -122,6 +123,10 @@ class BindingPattern : public Pattern {
auto value_category() const -> ValueCategory { return ValueCategory::Var; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return std::nullopt;
}
private:
std::string name_;
Nonnull<Pattern*> type_;
+3
View File
@@ -344,6 +344,9 @@ class Continuation : public Statement {
auto has_static_type() const -> bool { return static_type_.has_value(); }
auto value_category() const -> ValueCategory { return ValueCategory::Var; }
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return std::nullopt;
}
private:
std::string name_;
+16 -1
View File
@@ -37,6 +37,10 @@ static constexpr std::string_view AnonymousName = "_";
// Returns the name of an IdentifierExpression that names *this. If *this
// is anonymous, returns AnonymousName.
auto name() const -> std::string_view;
// If *this names a compile-time constant whose value is known, returns that
// value. Otherwise returns std::nullopt.
auto constant_value() const -> std::optional<Nonnull<const Value*>>;
*/
// NodeType must be derived from AstNode.
//
@@ -70,7 +74,11 @@ class NamedEntityView {
}),
value_category_([](const AstNode& base) -> ValueCategory {
return llvm::cast<NodeType>(base).value_category();
}) {
}),
constant_value_(
[](const AstNode& base) -> std::optional<Nonnull<const Value*>> {
return llvm::cast<NodeType>(base).constant_value();
}) {
CHECK(node->name() != AnonymousName)
<< "Entity with no name used as NamedEntity: " << *node;
}
@@ -94,6 +102,11 @@ class NamedEntityView {
return value_category_(*base_);
}
// Returns node->constant_value()
auto constant_value() const -> std::optional<Nonnull<const Value*>> {
return constant_value_(*base_);
}
friend auto operator==(const NamedEntityView& lhs, const NamedEntityView& rhs)
-> bool {
return lhs.base_ == rhs.base_;
@@ -114,6 +127,8 @@ class NamedEntityView {
std::function<std::string_view(const AstNode&)> name_;
std::function<const Value&(const AstNode&)> static_type_;
std::function<ValueCategory(const AstNode&)> value_category_;
std::function<std::optional<Nonnull<const Value*>>(const AstNode&)>
constant_value_;
};
// Maps the names visible in a given scope to the entities they name.