From 56dc4ae375639090f601b00335378e29bfb907e2 Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Thu, 16 Sep 2021 19:22:57 -0700 Subject: [PATCH] Rename Ptr to Nonnull (#832) Note that ptr.h also includes an enable_if change, to help avoid https://bugs.llvm.org/show_bug.cgi?id=51881 --- executable_semantics/ast/ast.h | 2 +- executable_semantics/ast/class_definition.h | 2 +- executable_semantics/ast/declaration.cpp | 2 +- executable_semantics/ast/declaration.h | 28 ++-- executable_semantics/ast/expression.cpp | 12 +- executable_semantics/ast/expression.h | 64 ++++---- executable_semantics/ast/expression_test.cpp | 16 +- .../ast/function_definition.h | 14 +- executable_semantics/ast/member.h | 6 +- executable_semantics/ast/paren_contents.h | 9 +- executable_semantics/ast/pattern.cpp | 23 +-- executable_semantics/ast/pattern.h | 44 ++--- executable_semantics/ast/pattern_test.cpp | 16 +- executable_semantics/ast/source_location.h | 2 +- executable_semantics/ast/statement.h | 115 ++++++------- executable_semantics/common/arena.h | 6 +- executable_semantics/common/ptr.h | 13 +- executable_semantics/interpreter/action.cpp | 3 +- executable_semantics/interpreter/action.h | 33 ++-- executable_semantics/interpreter/dictionary.h | 14 +- .../interpreter/exec_program.cpp | 9 +- .../interpreter/exec_program.h | 2 +- executable_semantics/interpreter/frame.h | 6 +- executable_semantics/interpreter/heap.cpp | 7 +- executable_semantics/interpreter/heap.h | 12 +- .../interpreter/interpreter.cpp | 155 +++++++++--------- .../interpreter/interpreter.h | 52 +++--- .../interpreter/type_checker.cpp | 129 ++++++++------- .../interpreter/type_checker.h | 68 ++++---- executable_semantics/interpreter/value.cpp | 57 ++++--- executable_semantics/interpreter/value.h | 90 +++++----- executable_semantics/syntax/parse.cpp | 2 +- executable_semantics/syntax/parse.h | 2 +- .../syntax/parse_and_lex_context.h | 10 +- executable_semantics/syntax/parser.ypp | 94 ++++++----- 35 files changed, 584 insertions(+), 535 deletions(-) diff --git a/executable_semantics/ast/ast.h b/executable_semantics/ast/ast.h index eded57f578bf..4b637c6c3c72 100644 --- a/executable_semantics/ast/ast.h +++ b/executable_semantics/ast/ast.h @@ -22,7 +22,7 @@ struct AST { // Import directives. std::vector imports; // The file's ordered declarations. - std::vector> declarations; + std::vector> declarations; }; } // namespace Carbon diff --git a/executable_semantics/ast/class_definition.h b/executable_semantics/ast/class_definition.h index a4d13db00168..2716e1b8a33e 100644 --- a/executable_semantics/ast/class_definition.h +++ b/executable_semantics/ast/class_definition.h @@ -16,7 +16,7 @@ namespace Carbon { struct ClassDefinition { SourceLocation loc; std::string name; - std::vector> members; + std::vector> members; }; } // namespace Carbon diff --git a/executable_semantics/ast/declaration.cpp b/executable_semantics/ast/declaration.cpp index 7957875a62ac..8477c3dab4d0 100644 --- a/executable_semantics/ast/declaration.cpp +++ b/executable_semantics/ast/declaration.cpp @@ -20,7 +20,7 @@ void Declaration::Print(llvm::raw_ostream& out) const { const ClassDefinition& class_def = cast(*this).Definition(); out << "class " << class_def.name << " {\n"; - for (Ptr m : class_def.members) { + for (Nonnull m : class_def.members) { out << *m; } out << "}\n"; diff --git a/executable_semantics/ast/declaration.h b/executable_semantics/ast/declaration.h index e9eb959a0bde..cfb0a17f7bff 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -60,7 +60,7 @@ class Declaration { class FunctionDeclaration : public Declaration { public: - FunctionDeclaration(Ptr definition) + FunctionDeclaration(Nonnull definition) : Declaration(Kind::FunctionDeclaration, definition->source_location), definition(definition) {} @@ -71,13 +71,13 @@ class FunctionDeclaration : public Declaration { auto Definition() const -> const FunctionDefinition& { return *definition; } private: - Ptr definition; + Nonnull definition; }; class ClassDeclaration : public Declaration { public: ClassDeclaration(SourceLocation loc, std::string name, - std::vector> members) + std::vector> members) : Declaration(Kind::ClassDeclaration, loc), definition({.loc = loc, .name = std::move(name), @@ -97,7 +97,8 @@ class ChoiceDeclaration : public Declaration { public: ChoiceDeclaration( SourceLocation loc, std::string name, - std::vector>> alternatives) + std::vector>> + alternatives) : Declaration(Kind::ChoiceDeclaration, loc), name(std::move(name)), alternatives(std::move(alternatives)) {} @@ -107,21 +108,22 @@ class ChoiceDeclaration : public Declaration { } auto Name() const -> const std::string& { return name; } - auto Alternatives() const - -> const std::vector>>& { + auto Alternatives() const -> const + std::vector>>& { return alternatives; } private: std::string name; - std::vector>> alternatives; + std::vector>> alternatives; }; // Global variable definition implements the Declaration concept. class VariableDeclaration : public Declaration { public: - VariableDeclaration(SourceLocation loc, Ptr binding, - Ptr initializer) + VariableDeclaration(SourceLocation loc, + Nonnull binding, + Nonnull initializer) : Declaration(Kind::VariableDeclaration, loc), binding(binding), initializer(initializer) {} @@ -130,15 +132,15 @@ class VariableDeclaration : public Declaration { return decl->Tag() == Kind::VariableDeclaration; } - auto Binding() const -> Ptr { return binding; } - auto Initializer() const -> Ptr { return initializer; } + auto Binding() const -> Nonnull { return binding; } + auto Initializer() const -> Nonnull { return initializer; } private: // TODO: split this into a non-optional name and a type, initialized by // a constructor that takes a BindingPattern and handles errors like a // missing name. - Ptr binding; - Ptr initializer; + Nonnull binding; + Nonnull initializer; }; } // namespace Carbon diff --git a/executable_semantics/ast/expression.cpp b/executable_semantics/ast/expression.cpp index 5a79ad1dc4aa..39490d9d4a48 100644 --- a/executable_semantics/ast/expression.cpp +++ b/executable_semantics/ast/expression.cpp @@ -17,9 +17,10 @@ namespace Carbon { using llvm::cast; auto ExpressionFromParenContents( - Ptr arena, SourceLocation loc, - const ParenContents& paren_contents) -> Ptr { - std::optional> single_term = + Nonnull arena, SourceLocation loc, + const ParenContents& paren_contents) + -> Nonnull { + std::optional> single_term = paren_contents.SingleTerm(); if (single_term.has_value()) { return *single_term; @@ -29,8 +30,9 @@ auto ExpressionFromParenContents( } auto TupleExpressionFromParenContents( - Ptr arena, SourceLocation loc, - const ParenContents& paren_contents) -> Ptr { + Nonnull arena, SourceLocation loc, + const ParenContents& paren_contents) + -> Nonnull { return arena->New( loc, paren_contents.TupleElements(loc)); } diff --git a/executable_semantics/ast/expression.h b/executable_semantics/ast/expression.h index 1436e61e71df..76582d2418f5 100644 --- a/executable_semantics/ast/expression.h +++ b/executable_semantics/ast/expression.h @@ -63,25 +63,27 @@ class Expression { // grouping if their contents permit that interpretation, or as forming a // tuple otherwise. auto ExpressionFromParenContents( - Ptr arena, SourceLocation loc, - const ParenContents& paren_contents) -> Ptr; + Nonnull arena, SourceLocation loc, + const ParenContents& paren_contents) + -> Nonnull; // Converts paren_contents to an Expression, interpreting the parentheses as // forming a tuple. auto TupleExpressionFromParenContents( - Ptr arena, SourceLocation loc, - const ParenContents& paren_contents) -> Ptr; + Nonnull arena, SourceLocation loc, + const ParenContents& paren_contents) + -> Nonnull; // A FieldInitializer represents the initialization of a single tuple field. struct FieldInitializer { - FieldInitializer(std::string name, Ptr expression) + FieldInitializer(std::string name, Nonnull expression) : name(std::move(name)), expression(expression) {} // The field name. Cannot be empty. std::string name; // The expression that initializes the field. - Ptr expression; + Nonnull expression; }; enum class Operator { @@ -115,7 +117,7 @@ class IdentifierExpression : public Expression { class FieldAccessExpression : public Expression { public: explicit FieldAccessExpression(SourceLocation loc, - Ptr aggregate, + Nonnull aggregate, std::string field) : Expression(Kind::FieldAccessExpression, loc), aggregate(aggregate), @@ -125,18 +127,19 @@ class FieldAccessExpression : public Expression { return exp->Tag() == Kind::FieldAccessExpression; } - auto Aggregate() const -> Ptr { return aggregate; } + auto Aggregate() const -> Nonnull { return aggregate; } auto Field() const -> const std::string& { return field; } private: - Ptr aggregate; + Nonnull aggregate; std::string field; }; class IndexExpression : public Expression { public: - explicit IndexExpression(SourceLocation loc, Ptr aggregate, - Ptr offset) + explicit IndexExpression(SourceLocation loc, + Nonnull aggregate, + Nonnull offset) : Expression(Kind::IndexExpression, loc), aggregate(aggregate), offset(offset) {} @@ -145,12 +148,12 @@ class IndexExpression : public Expression { return exp->Tag() == Kind::IndexExpression; } - auto Aggregate() const -> Ptr { return aggregate; } - auto Offset() const -> Ptr { return offset; } + auto Aggregate() const -> Nonnull { return aggregate; } + auto Offset() const -> Nonnull { return offset; } private: - Ptr aggregate; - Ptr offset; + Nonnull aggregate; + Nonnull offset; }; class IntLiteral : public Expression { @@ -230,7 +233,7 @@ class PrimitiveOperatorExpression : public Expression { public: explicit PrimitiveOperatorExpression( SourceLocation loc, Operator op, - std::vector> arguments) + std::vector> arguments) : Expression(Kind::PrimitiveOperatorExpression, loc), op(op), arguments(std::move(arguments)) {} @@ -240,19 +243,20 @@ class PrimitiveOperatorExpression : public Expression { } auto Op() const -> Operator { return op; } - auto Arguments() const -> const std::vector>& { + auto Arguments() const -> const std::vector>& { return arguments; } private: Operator op; - std::vector> arguments; + std::vector> arguments; }; class CallExpression : public Expression { public: - explicit CallExpression(SourceLocation loc, Ptr function, - Ptr argument) + explicit CallExpression(SourceLocation loc, + Nonnull function, + Nonnull argument) : Expression(Kind::CallExpression, loc), function(function), argument(argument) {} @@ -261,19 +265,19 @@ class CallExpression : public Expression { return exp->Tag() == Kind::CallExpression; } - auto Function() const -> Ptr { return function; } - auto Argument() const -> Ptr { return argument; } + auto Function() const -> Nonnull { return function; } + auto Argument() const -> Nonnull { return argument; } private: - Ptr function; - Ptr argument; + Nonnull function; + Nonnull argument; }; class FunctionTypeLiteral : public Expression { public: explicit FunctionTypeLiteral(SourceLocation loc, - Ptr parameter, - Ptr return_type, + Nonnull parameter, + Nonnull return_type, bool is_omitted_return_type) : Expression(Kind::FunctionTypeLiteral, loc), parameter(parameter), @@ -284,13 +288,13 @@ class FunctionTypeLiteral : public Expression { return exp->Tag() == Kind::FunctionTypeLiteral; } - auto Parameter() const -> Ptr { return parameter; } - auto ReturnType() const -> Ptr { return return_type; } + auto Parameter() const -> Nonnull { return parameter; } + auto ReturnType() const -> Nonnull { return return_type; } auto IsOmittedReturnType() const -> bool { return is_omitted_return_type; } private: - Ptr parameter; - Ptr return_type; + Nonnull parameter; + Nonnull return_type; bool is_omitted_return_type; }; diff --git a/executable_semantics/ast/expression_test.cpp b/executable_semantics/ast/expression_test.cpp index 78eea43d9090..95edbaff7e49 100644 --- a/executable_semantics/ast/expression_test.cpp +++ b/executable_semantics/ast/expression_test.cpp @@ -38,7 +38,7 @@ class ExpressionTest : public ::testing::Test { TEST_F(ExpressionTest, EmptyAsExpression) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; - Ptr expression = + Nonnull expression = ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral); @@ -48,7 +48,7 @@ TEST_F(ExpressionTest, EmptyAsExpression) { TEST_F(ExpressionTest, EmptyAsTuple) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; - Ptr tuple = + Nonnull tuple = TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral); @@ -67,7 +67,7 @@ TEST_F(ExpressionTest, UnaryNoCommaAsExpression) { .term = arena.New(FakeSourceLoc(2), 42)}}, .has_trailing_comma = false}; - Ptr expression = + Nonnull expression = ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(2)); ASSERT_EQ(expression->Tag(), Expression::Kind::IntLiteral); @@ -79,7 +79,7 @@ TEST_F(ExpressionTest, UnaryNoCommaAsTuple) { .term = arena.New(FakeSourceLoc(2), 42)}}, .has_trailing_comma = false}; - Ptr tuple = + Nonnull tuple = TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral); @@ -93,7 +93,7 @@ TEST_F(ExpressionTest, UnaryWithCommaAsExpression) { .term = arena.New(FakeSourceLoc(2), 42)}}, .has_trailing_comma = true}; - Ptr expression = + Nonnull expression = ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral); @@ -107,7 +107,7 @@ TEST_F(ExpressionTest, UnaryWithCommaAsTuple) { .term = arena.New(FakeSourceLoc(2), 42)}}, .has_trailing_comma = true}; - Ptr tuple = + Nonnull tuple = TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral); @@ -123,7 +123,7 @@ TEST_F(ExpressionTest, BinaryAsExpression) { .term = arena.New(FakeSourceLoc(3), 42)}}, .has_trailing_comma = true}; - Ptr expression = + Nonnull expression = ExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(expression->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(expression->Tag(), Expression::Kind::TupleLiteral); @@ -139,7 +139,7 @@ TEST_F(ExpressionTest, BinaryAsTuple) { .term = arena.New(FakeSourceLoc(3), 42)}}, .has_trailing_comma = true}; - Ptr tuple = + Nonnull tuple = TupleExpressionFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); ASSERT_EQ(tuple->Tag(), Expression::Kind::TupleLiteral); diff --git a/executable_semantics/ast/function_definition.h b/executable_semantics/ast/function_definition.h index dbb4de86e7f9..81d4fb22714f 100644 --- a/executable_semantics/ast/function_definition.h +++ b/executable_semantics/ast/function_definition.h @@ -18,16 +18,16 @@ namespace Carbon { // For now, only generic parameters are supported. struct GenericBinding { std::string name; - Ptr type; + Nonnull type; }; struct FunctionDefinition { FunctionDefinition(SourceLocation source_location, std::string name, std::vector deduced_params, - Ptr param_pattern, - Ptr return_type, + Nonnull param_pattern, + Nonnull return_type, bool is_omitted_return_type, - std::optional> body) + std::optional> body) : source_location(source_location), name(std::move(name)), deduced_parameters(deduced_params), @@ -43,10 +43,10 @@ struct FunctionDefinition { SourceLocation source_location; std::string name; std::vector deduced_parameters; - Ptr param_pattern; - Ptr return_type; + Nonnull param_pattern; + Nonnull return_type; bool is_omitted_return_type; - std::optional> body; + std::optional> body; }; } // namespace Carbon diff --git a/executable_semantics/ast/member.h b/executable_semantics/ast/member.h index 354e315e740b..660ebbeb616f 100644 --- a/executable_semantics/ast/member.h +++ b/executable_semantics/ast/member.h @@ -51,20 +51,20 @@ class Member { class FieldMember : public Member { public: - FieldMember(SourceLocation loc, Ptr binding) + FieldMember(SourceLocation loc, Nonnull binding) : Member(Kind::FieldMember, loc), binding(binding) {} static auto classof(const Member* member) -> bool { return member->Tag() == Kind::FieldMember; } - auto Binding() const -> Ptr { return binding; } + auto Binding() const -> Nonnull { return binding; } private: // TODO: split this into a non-optional name and a type, initialized by // a constructor that takes a BindingPattern and handles errors like a // missing name. - Ptr binding; + Nonnull binding; }; } // namespace Carbon diff --git a/executable_semantics/ast/paren_contents.h b/executable_semantics/ast/paren_contents.h index 3a4633cfb000..df2888cd1bb2 100644 --- a/executable_semantics/ast/paren_contents.h +++ b/executable_semantics/ast/paren_contents.h @@ -28,16 +28,16 @@ template struct ParenContents { struct Element { std::optional name; - Ptr term; + Nonnull term; }; // If this object represents a single term, with no name and no trailing // comma, this method returns that term. This typically means the parentheses // can be interpreted as grouping. - auto SingleTerm() const -> std::optional>; + auto SingleTerm() const -> std::optional>; // Converts `elements` to std::vector. TupleElement must - // have a constructor that takes a std::string and a Ptr. + // have a constructor that takes a std::string and a Nonnull. // // TODO: Find a way to deduce TupleElement from Term. template @@ -50,7 +50,8 @@ struct ParenContents { // Implementation details only below here. template -auto ParenContents::SingleTerm() const -> std::optional> { +auto ParenContents::SingleTerm() const + -> std::optional> { if (elements.size() == 1 && !elements.front().name.has_value() && !has_trailing_comma) { return elements.front().term; diff --git a/executable_semantics/ast/pattern.cpp b/executable_semantics/ast/pattern.cpp index 71dbece724cd..2f6a5b7a547c 100644 --- a/executable_semantics/ast/pattern.cpp +++ b/executable_semantics/ast/pattern.cpp @@ -54,8 +54,8 @@ void Pattern::Print(llvm::raw_ostream& out) const { } } -TuplePattern::TuplePattern(Ptr arena, - Ptr tuple_literal) +TuplePattern::TuplePattern(Nonnull arena, + Nonnull tuple_literal) : Pattern(Kind::TuplePattern, tuple_literal->SourceLoc()) { const auto& tuple = cast(*tuple_literal); for (const FieldInitializer& init : tuple.Fields()) { @@ -64,10 +64,11 @@ TuplePattern::TuplePattern(Ptr arena, } } -auto PatternFromParenContents(Ptr arena, SourceLocation loc, +auto PatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Ptr { - std::optional> single_term = paren_contents.SingleTerm(); + -> Nonnull { + std::optional> single_term = + paren_contents.SingleTerm(); if (single_term.has_value()) { return *single_term; } else { @@ -75,9 +76,9 @@ auto PatternFromParenContents(Ptr arena, SourceLocation loc, } } -auto TuplePatternFromParenContents(Ptr arena, SourceLocation loc, +auto TuplePatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Ptr { + -> Nonnull { return arena->New( loc, paren_contents.TupleElements(loc)); } @@ -86,7 +87,7 @@ auto TuplePatternFromParenContents(Ptr arena, SourceLocation loc, // error for incorrect expressions, rather than letting a default cast error // apply. static const FieldAccessExpression& RequireFieldAccess( - Ptr alternative) { + Nonnull alternative) { if (alternative->Tag() != Expression::Kind::FieldAccessExpression) { FATAL_PROGRAM_ERROR(alternative->SourceLoc()) << "Alternative pattern must have the form of a field access."; @@ -95,14 +96,14 @@ static const FieldAccessExpression& RequireFieldAccess( } AlternativePattern::AlternativePattern(SourceLocation loc, - Ptr alternative, - Ptr arguments) + Nonnull alternative, + Nonnull arguments) : Pattern(Kind::AlternativePattern, loc), choice_type(RequireFieldAccess(alternative).Aggregate()), alternative_name(RequireFieldAccess(alternative).Field()), arguments(arguments) {} -auto ParenExpressionToParenPattern(Ptr arena, +auto ParenExpressionToParenPattern(Nonnull arena, const ParenContents& contents) -> ParenContents { ParenContents result = { diff --git a/executable_semantics/ast/pattern.h b/executable_semantics/ast/pattern.h index e7da63b10fea..f895ef00244d 100644 --- a/executable_semantics/ast/pattern.h +++ b/executable_semantics/ast/pattern.h @@ -71,7 +71,7 @@ class AutoPattern : public Pattern { class BindingPattern : public Pattern { public: BindingPattern(SourceLocation loc, std::optional name, - Ptr type) + Nonnull type) : Pattern(Kind::BindingPattern, loc), name(std::move(name)), type(type) {} static auto classof(const Pattern* pattern) -> bool { @@ -82,11 +82,11 @@ class BindingPattern : public Pattern { auto Name() const -> const std::optional& { return name; } // The pattern specifying the type of values that this pattern matches. - auto Type() const -> Ptr { return type; } + auto Type() const -> Nonnull { return type; } private: std::optional name; - Ptr type; + Nonnull type; }; // A pattern that matches a tuple value field-wise. @@ -94,14 +94,14 @@ class TuplePattern : public Pattern { public: // Represents a portion of a tuple pattern corresponding to a single field. struct Field { - Field(std::string name, Ptr pattern) + Field(std::string name, Nonnull pattern) : name(std::move(name)), pattern(pattern) {} // The field name. Cannot be empty std::string name; // The pattern the field must match. - Ptr pattern; + Nonnull pattern; }; TuplePattern(SourceLocation loc, std::vector fields) @@ -111,7 +111,7 @@ class TuplePattern : public Pattern { // ExpressionPattern. // // REQUIRES: tuple_literal->Tag() == Expression::Kind::TupleLiteral - TuplePattern(Ptr arena, Ptr tuple_literal); + TuplePattern(Nonnull arena, Nonnull tuple_literal); static auto classof(const Pattern* pattern) -> bool { return pattern->Tag() == Kind::TuplePattern; @@ -126,19 +126,19 @@ class TuplePattern : public Pattern { // Converts paren_contents to a Pattern, interpreting the parentheses as // grouping if their contents permit that interpretation, or as forming a // tuple otherwise. -auto PatternFromParenContents(Ptr arena, SourceLocation loc, +auto PatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Ptr; + -> Nonnull; // Converts paren_contents to a TuplePattern, interpreting the parentheses as // forming a tuple. -auto TuplePatternFromParenContents(Ptr arena, SourceLocation loc, +auto TuplePatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Ptr; + -> Nonnull; // Converts `contents` to ParenContents by replacing each Expression // with an ExpressionPattern. -auto ParenExpressionToParenPattern(Ptr arena, +auto ParenExpressionToParenPattern(Nonnull arena, const ParenContents& contents) -> ParenContents; @@ -148,9 +148,9 @@ class AlternativePattern : public Pattern { // Constructs an AlternativePattern that matches a value of the type // specified by choice_type if it represents an alternative named // alternative_name, and its arguments match `arguments`. - AlternativePattern(SourceLocation loc, Ptr choice_type, + AlternativePattern(SourceLocation loc, Nonnull choice_type, std::string alternative_name, - Ptr arguments) + Nonnull arguments) : Pattern(Kind::AlternativePattern, loc), choice_type(choice_type), alternative_name(std::move(alternative_name)), @@ -158,30 +158,30 @@ class AlternativePattern : public Pattern { // Constructs an AlternativePattern that matches the alternative specified // by `alternative`, if its arguments match `arguments`. - AlternativePattern(SourceLocation loc, Ptr alternative, - Ptr arguments); + AlternativePattern(SourceLocation loc, Nonnull alternative, + Nonnull arguments); static auto classof(const Pattern* pattern) -> bool { return pattern->Tag() == Kind::AlternativePattern; } - auto ChoiceType() const -> Ptr { return choice_type; } + auto ChoiceType() const -> Nonnull { return choice_type; } auto AlternativeName() const -> const std::string& { return alternative_name; } - auto Arguments() const -> Ptr { return arguments; } + auto Arguments() const -> Nonnull { return arguments; } private: - Ptr choice_type; + Nonnull choice_type; std::string alternative_name; - Ptr arguments; + Nonnull arguments; }; // A pattern that matches a value if it is equal to the value of a given // expression. class ExpressionPattern : public Pattern { public: - ExpressionPattern(Ptr expression) + ExpressionPattern(Nonnull expression) : Pattern(Kind::ExpressionPattern, expression->SourceLoc()), expression(expression) {} @@ -189,10 +189,10 @@ class ExpressionPattern : public Pattern { return pattern->Tag() == Kind::ExpressionPattern; } - auto Expression() const -> Ptr { return expression; } + auto Expression() const -> Nonnull { return expression; } private: - Ptr expression; + Nonnull expression; }; } // namespace Carbon diff --git a/executable_semantics/ast/pattern_test.cpp b/executable_semantics/ast/pattern_test.cpp index f69b4e066a5e..d68ee7dc210d 100644 --- a/executable_semantics/ast/pattern_test.cpp +++ b/executable_semantics/ast/pattern_test.cpp @@ -37,7 +37,7 @@ class PatternTest : public ::testing::Test { TEST_F(PatternTest, EmptyAsPattern) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; - Ptr pattern = + Nonnull pattern = PatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1)); ASSERT_TRUE(isa(*pattern)); @@ -47,7 +47,7 @@ TEST_F(PatternTest, EmptyAsPattern) { TEST_F(PatternTest, EmptyAsTuplePattern) { ParenContents contents = {.elements = {}, .has_trailing_comma = false}; - Ptr tuple = + Nonnull tuple = TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); EXPECT_THAT(tuple->Fields(), IsEmpty()); @@ -65,7 +65,7 @@ TEST_F(PatternTest, UnaryNoCommaAsPattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = false}; - Ptr pattern = + Nonnull pattern = PatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(2)); ASSERT_TRUE(isa(*pattern)); @@ -77,7 +77,7 @@ TEST_F(PatternTest, UnaryNoCommaAsTuplePattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = false}; - Ptr tuple = + Nonnull tuple = TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0"))); @@ -89,7 +89,7 @@ TEST_F(PatternTest, UnaryWithCommaAsPattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = true}; - Ptr pattern = + Nonnull pattern = PatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1)); ASSERT_TRUE(isa(*pattern)); @@ -103,7 +103,7 @@ TEST_F(PatternTest, UnaryWithCommaAsTuplePattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = true}; - Ptr tuple = + Nonnull tuple = TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); EXPECT_THAT(tuple->Fields(), ElementsAre(AutoFieldNamed("0"))); @@ -117,7 +117,7 @@ TEST_F(PatternTest, BinaryAsPattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = true}; - Ptr pattern = + Nonnull pattern = PatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(pattern->SourceLoc(), FakeSourceLoc(1)); ASSERT_TRUE(isa(*pattern)); @@ -133,7 +133,7 @@ TEST_F(PatternTest, BinaryAsTuplePattern) { .term = arena.New(FakeSourceLoc(2))}}, .has_trailing_comma = true}; - Ptr tuple = + Nonnull tuple = TuplePatternFromParenContents(&arena, FakeSourceLoc(1), contents); EXPECT_EQ(tuple->SourceLoc(), FakeSourceLoc(1)); EXPECT_THAT(tuple->Fields(), diff --git a/executable_semantics/ast/source_location.h b/executable_semantics/ast/source_location.h index 55acadf1cbac..49f87c03a1e8 100644 --- a/executable_semantics/ast/source_location.h +++ b/executable_semantics/ast/source_location.h @@ -18,7 +18,7 @@ class SourceLocation { // The filename should be eternal or arena-allocated to eliminate copies. SourceLocation(const char* filename, int line_num) : filename(filename), line_num(line_num) {} - SourceLocation(Ptr filename, int line_num) + SourceLocation(Nonnull filename, int line_num) : filename(filename->c_str()), line_num(line_num) {} SourceLocation(const SourceLocation&) = default; diff --git a/executable_semantics/ast/statement.h b/executable_semantics/ast/statement.h index 5baba4040f45..af5980432255 100644 --- a/executable_semantics/ast/statement.h +++ b/executable_semantics/ast/statement.h @@ -58,60 +58,60 @@ class Statement { class ExpressionStatement : public Statement { public: - ExpressionStatement(SourceLocation loc, Ptr exp) + ExpressionStatement(SourceLocation loc, Nonnull exp) : Statement(Kind::ExpressionStatement, loc), exp(exp) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::ExpressionStatement; } - auto Exp() const -> Ptr { return exp; } + auto Exp() const -> Nonnull { return exp; } private: - Ptr exp; + Nonnull exp; }; class Assign : public Statement { public: - Assign(SourceLocation loc, Ptr lhs, - Ptr rhs) + Assign(SourceLocation loc, Nonnull lhs, + Nonnull rhs) : Statement(Kind::Assign, loc), lhs(lhs), rhs(rhs) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Assign; } - auto Lhs() const -> Ptr { return lhs; } - auto Rhs() const -> Ptr { return rhs; } + auto Lhs() const -> Nonnull { return lhs; } + auto Rhs() const -> Nonnull { return rhs; } private: - Ptr lhs; - Ptr rhs; + Nonnull lhs; + Nonnull rhs; }; class VariableDefinition : public Statement { public: - VariableDefinition(SourceLocation loc, Ptr pat, - Ptr init) + VariableDefinition(SourceLocation loc, Nonnull pat, + Nonnull init) : Statement(Kind::VariableDefinition, loc), pat(pat), init(init) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::VariableDefinition; } - auto Pat() const -> Ptr { return pat; } - auto Init() const -> Ptr { return init; } + auto Pat() const -> Nonnull { return pat; } + auto Init() const -> Nonnull { return init; } private: - Ptr pat; - Ptr init; + Nonnull pat; + Nonnull init; }; class If : public Statement { public: - If(SourceLocation loc, Ptr cond, - Ptr then_stmt, - std::optional> else_stmt) + If(SourceLocation loc, Nonnull cond, + Nonnull then_stmt, + std::optional> else_stmt) : Statement(Kind::If, loc), cond(cond), then_stmt(then_stmt), @@ -121,23 +121,24 @@ class If : public Statement { return stmt->Tag() == Kind::If; } - auto Cond() const -> Ptr { return cond; } - auto ThenStmt() const -> Ptr { return then_stmt; } - auto ElseStmt() const -> std::optional> { + auto Cond() const -> Nonnull { return cond; } + auto ThenStmt() const -> Nonnull { return then_stmt; } + auto ElseStmt() const -> std::optional> { return else_stmt; } private: - Ptr cond; - Ptr then_stmt; - std::optional> else_stmt; + Nonnull cond; + Nonnull then_stmt; + std::optional> else_stmt; }; class Return : public Statement { public: - Return(Ptr arena, SourceLocation loc) + Return(Nonnull arena, SourceLocation loc) : Return(loc, arena->New(loc), true) {} - Return(SourceLocation loc, Ptr exp, bool is_omitted_exp) + Return(SourceLocation loc, Nonnull exp, + bool is_omitted_exp) : Statement(Kind::Return, loc), exp(exp), is_omitted_exp(is_omitted_exp) {} @@ -146,63 +147,63 @@ class Return : public Statement { return stmt->Tag() == Kind::Return; } - auto Exp() const -> Ptr { return exp; } + auto Exp() const -> Nonnull { return exp; } auto IsOmittedExp() const -> bool { return is_omitted_exp; } private: - Ptr exp; + Nonnull exp; bool is_omitted_exp; }; class Sequence : public Statement { public: - Sequence(SourceLocation loc, Ptr stmt, - std::optional> next) + Sequence(SourceLocation loc, Nonnull stmt, + std::optional> next) : Statement(Kind::Sequence, loc), stmt(stmt), next(next) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Sequence; } - auto Stmt() const -> Ptr { return stmt; } - auto Next() const -> std::optional> { return next; } + auto Stmt() const -> Nonnull { return stmt; } + auto Next() const -> std::optional> { return next; } private: - Ptr stmt; - std::optional> next; + Nonnull stmt; + std::optional> next; }; class Block : public Statement { public: - Block(SourceLocation loc, std::optional> stmt) + Block(SourceLocation loc, std::optional> stmt) : Statement(Kind::Block, loc), stmt(stmt) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Block; } - auto Stmt() const -> std::optional> { return stmt; } + auto Stmt() const -> std::optional> { return stmt; } private: - std::optional> stmt; + std::optional> stmt; }; class While : public Statement { public: - While(SourceLocation loc, Ptr cond, - Ptr body) + While(SourceLocation loc, Nonnull cond, + Nonnull body) : Statement(Kind::While, loc), cond(cond), body(body) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::While; } - auto Cond() const -> Ptr { return cond; } - auto Body() const -> Ptr { return body; } + auto Cond() const -> Nonnull { return cond; } + auto Body() const -> Nonnull { return body; } private: - Ptr cond; - Ptr body; + Nonnull cond; + Nonnull body; }; class Break : public Statement { @@ -226,23 +227,25 @@ class Continue : public Statement { class Match : public Statement { public: Match( - SourceLocation loc, Ptr exp, - std::vector, Ptr>> clauses) + SourceLocation loc, Nonnull exp, + std::vector, Nonnull>> + clauses) : Statement(Kind::Match, loc), exp(exp), clauses(std::move(clauses)) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Match; } - auto Exp() const -> Ptr { return exp; } - auto Clauses() const -> const - std::vector, Ptr>>& { + auto Exp() const -> Nonnull { return exp; } + auto Clauses() const -> const std::vector< + std::pair, Nonnull>>& { return clauses; } private: - Ptr exp; - std::vector, Ptr>> clauses; + Nonnull exp; + std::vector, Nonnull>> + clauses; }; // A continuation statement. @@ -253,7 +256,7 @@ class Match : public Statement { class Continuation : public Statement { public: Continuation(SourceLocation loc, std::string continuation_variable, - Ptr body) + Nonnull body) : Statement(Kind::Continuation, loc), continuation_variable(std::move(continuation_variable)), body(body) {} @@ -265,11 +268,11 @@ class Continuation : public Statement { auto ContinuationVariable() const -> const std::string& { return continuation_variable; } - auto Body() const -> Ptr { return body; } + auto Body() const -> Nonnull { return body; } private: std::string continuation_variable; - Ptr body; + Nonnull body; }; // A run statement. @@ -277,17 +280,17 @@ class Continuation : public Statement { // __run ; class Run : public Statement { public: - Run(SourceLocation loc, Ptr argument) + Run(SourceLocation loc, Nonnull argument) : Statement(Kind::Run, loc), argument(argument) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Run; } - auto Argument() const -> Ptr { return argument; } + auto Argument() const -> Nonnull { return argument; } private: - Ptr argument; + Nonnull argument; }; // An await statement. diff --git a/executable_semantics/common/arena.h b/executable_semantics/common/arena.h index 7f52b7d2a906..a6cb2c387f69 100644 --- a/executable_semantics/common/arena.h +++ b/executable_semantics/common/arena.h @@ -16,10 +16,10 @@ class Arena { public: // Allocates an object in the arena, returning a pointer to it. template - auto New(Args&&... args) -> Ptr { + auto New(Args&&... args) -> Nonnull { auto smart_ptr = std::make_unique>(std::forward(args)...); - Ptr ptr = smart_ptr->Instance(); + Nonnull ptr = smart_ptr->Instance(); arena.push_back(std::move(smart_ptr)); return ptr; } @@ -40,7 +40,7 @@ class Arena { explicit ArenaEntryTyped(Args&&... args) : instance(std::forward(args)...) {} - auto Instance() -> Ptr { return Ptr(&instance); } + auto Instance() -> Nonnull { return Nonnull(&instance); } private: T instance; diff --git a/executable_semantics/common/ptr.h b/executable_semantics/common/ptr.h index 32842bf6e872..c971e5635459 100644 --- a/executable_semantics/common/ptr.h +++ b/executable_semantics/common/ptr.h @@ -5,11 +5,18 @@ #ifndef EXECUTABLE_SEMANTICS_COMMON_PTR_H_ #define EXECUTABLE_SEMANTICS_COMMON_PTR_H_ +#include + namespace Carbon { -// A non-nullable pointer. Written as `Ptr` instead of `T*`. -template -using Ptr = T* _Nonnull __attribute__((nonnull)); +// A non-nullable pointer. Written as `Nonnull` instead of `T*`. +// +// Note LLVM primarily enforces the attribute on function calls that can be +// proven to be called with nullptr; in other places, this is essentially a +// comment. +template >* = nullptr> +using Nonnull = T _Nonnull __attribute__((nonnull)); } // namespace Carbon diff --git a/executable_semantics/interpreter/action.cpp b/executable_semantics/interpreter/action.cpp index 3370088e5798..86ba84c00f6c 100644 --- a/executable_semantics/interpreter/action.cpp +++ b/executable_semantics/interpreter/action.cpp @@ -47,7 +47,8 @@ void Action::Print(llvm::raw_ostream& out) const { } } -void Action::PrintList(const Stack>& ls, llvm::raw_ostream& out) { +void Action::PrintList(const Stack>& ls, + llvm::raw_ostream& out) { llvm::ListSeparator sep(" :: "); for (const auto& action : ls) { out << sep << *action; diff --git a/executable_semantics/interpreter/action.h b/executable_semantics/interpreter/action.h index e40ad05c91d5..79078ba388cf 100644 --- a/executable_semantics/interpreter/action.h +++ b/executable_semantics/interpreter/action.h @@ -38,13 +38,13 @@ class Action { auto Pos() const -> int { return pos; } // Results from a subexpression. - auto Results() const -> const std::vector>& { + auto Results() const -> const std::vector>& { return results; } void SetPos(int pos) { this->pos = pos; } - void AddResult(Ptr result) { results.push_back(result); } + void AddResult(Nonnull result) { results.push_back(result); } void Clear() { pos = 0; @@ -55,7 +55,8 @@ class Action { // object. auto Tag() const -> Kind { return tag; } - static void PrintList(const Stack>& ls, llvm::raw_ostream& out); + static void PrintList(const Stack>& ls, + llvm::raw_ostream& out); void Print(llvm::raw_ostream& out) const; LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } @@ -67,69 +68,69 @@ class Action { private: int pos = 0; - std::vector> results; + std::vector> results; const Kind tag; }; class LValAction : public Action { public: - explicit LValAction(Ptr exp) + explicit LValAction(Nonnull exp) : Action(Kind::LValAction), exp(exp) {} static auto classof(const Action* action) -> bool { return action->Tag() == Kind::LValAction; } - auto Exp() const -> Ptr { return exp; } + auto Exp() const -> Nonnull { return exp; } private: - Ptr exp; + Nonnull exp; }; class ExpressionAction : public Action { public: - explicit ExpressionAction(Ptr exp) + explicit ExpressionAction(Nonnull exp) : Action(Kind::ExpressionAction), exp(exp) {} static auto classof(const Action* action) -> bool { return action->Tag() == Kind::ExpressionAction; } - auto Exp() const -> Ptr { return exp; } + auto Exp() const -> Nonnull { return exp; } private: - Ptr exp; + Nonnull exp; }; class PatternAction : public Action { public: - explicit PatternAction(Ptr pat) + explicit PatternAction(Nonnull pat) : Action(Kind::PatternAction), pat(pat) {} static auto classof(const Action* action) -> bool { return action->Tag() == Kind::PatternAction; } - auto Pat() const -> Ptr { return pat; } + auto Pat() const -> Nonnull { return pat; } private: - Ptr pat; + Nonnull pat; }; class StatementAction : public Action { public: - explicit StatementAction(Ptr stmt) + explicit StatementAction(Nonnull stmt) : Action(Kind::StatementAction), stmt(stmt) {} static auto classof(const Action* action) -> bool { return action->Tag() == Kind::StatementAction; } - auto Stmt() const -> Ptr { return stmt; } + auto Stmt() const -> Nonnull { return stmt; } private: - Ptr stmt; + Nonnull stmt; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/dictionary.h b/executable_semantics/interpreter/dictionary.h index 032adf3fbff8..7d7c20165eb7 100644 --- a/executable_semantics/interpreter/dictionary.h +++ b/executable_semantics/interpreter/dictionary.h @@ -20,10 +20,10 @@ class Dictionary { struct Node { using ValueType = std::pair; - Node(ValueType e, std::optional> n) : curr(e), next(n) {} + Node(ValueType e, std::optional> n) : curr(e), next(n) {} const ValueType curr; - const std::optional> next; + const std::optional> next; // Node cells are part of a "persistent data structure" and are thus // immutable. @@ -39,7 +39,7 @@ class Dictionary { using reference = const value_type&; using iterator_category = std::forward_iterator_tag; - Iterator(std::optional> x) : p(x) {} + Iterator(std::optional> x) : p(x) {} Iterator(const Iterator& iter) : p(iter.p) {} Iterator& operator++() { p = (*p)->next; @@ -56,11 +56,11 @@ class Dictionary { const value_type* operator->() { return &(*p)->curr; } private: - std::optional> p; + std::optional> p; }; // Create an empty dictionary. - explicit Dictionary(Ptr arena) : arena(arena) {} + explicit Dictionary(Nonnull arena) : arena(arena) {} // Return the value associated with the given key. // Time complexity: O(n) where n is the number of times @@ -90,8 +90,8 @@ class Dictionary { auto end() const -> Iterator { return Iterator(std::nullopt); } private: - std::optional> head; - Ptr arena; + std::optional> head; + Nonnull arena; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/exec_program.cpp b/executable_semantics/interpreter/exec_program.cpp index 6a496cacc3dd..1c03d62fc361 100644 --- a/executable_semantics/interpreter/exec_program.cpp +++ b/executable_semantics/interpreter/exec_program.cpp @@ -15,8 +15,9 @@ namespace Carbon { // Adds builtins, currently only Print(). Note Print() is experimental, not // standardized, but is made available for printing state in tests. -static void AddIntrinsics(Ptr arena, - std::vector>* declarations) { +static void AddIntrinsics( + Nonnull arena, + std::vector>* declarations) { SourceLocation loc("", 0); std::vector print_fields = {TuplePattern::Field( "0", @@ -36,7 +37,7 @@ static void AddIntrinsics(Ptr arena, declarations->insert(declarations->begin(), print); } -void ExecProgram(Ptr arena, AST ast) { +void ExecProgram(Nonnull arena, AST ast) { AddIntrinsics(arena, &ast.declarations); if (tracing_output) { llvm::outs() << "********** source program **********\n"; @@ -49,7 +50,7 @@ void ExecProgram(Ptr arena, AST ast) { TypeChecker::TypeCheckContext p = type_checker.TopLevel(ast.declarations); TypeEnv top = p.types; Env ct_top = p.values; - std::vector> new_decls; + std::vector> new_decls; for (const auto decl : ast.declarations) { new_decls.push_back(type_checker.MakeTypeChecked(decl, top, ct_top)); } diff --git a/executable_semantics/interpreter/exec_program.h b/executable_semantics/interpreter/exec_program.h index 3e837763f58a..227f438aae8f 100644 --- a/executable_semantics/interpreter/exec_program.h +++ b/executable_semantics/interpreter/exec_program.h @@ -14,7 +14,7 @@ namespace Carbon { // Runs the top-level declaration list. -void ExecProgram(Ptr arena, AST ast); +void ExecProgram(Nonnull arena, AST ast); } // namespace Carbon diff --git a/executable_semantics/interpreter/frame.h b/executable_semantics/interpreter/frame.h index b8d2b123d66c..35291bd47cce 100644 --- a/executable_semantics/interpreter/frame.h +++ b/executable_semantics/interpreter/frame.h @@ -33,7 +33,7 @@ struct Frame { Frame(const Frame&) = delete; Frame& operator=(const Frame&) = delete; - Frame(std::string n, Stack> s, Stack> c) + Frame(std::string n, Stack> s, Stack> c) : name(std::move(std::move(n))), scopes(s), todo(c), continuation() {} void Print(llvm::raw_ostream& out) const; @@ -47,11 +47,11 @@ struct Frame { // blocks within the function. The scope at the top of the stack is // the current scope and its environment is the one used for looking // up the value associated with a variable. - Stack> scopes; + Stack> scopes; // The actions that need to be executed in the future of the // current function call. The top of the stack is the action // that is executed first. - Stack> todo; + Stack> todo; // If this frame is the bottom frame of a continuation, then it stores // the address of the continuation. std::optional
continuation; diff --git a/executable_semantics/interpreter/heap.cpp b/executable_semantics/interpreter/heap.cpp index 8f68d3251b44..d400d386e974 100644 --- a/executable_semantics/interpreter/heap.cpp +++ b/executable_semantics/interpreter/heap.cpp @@ -9,7 +9,7 @@ namespace Carbon { -auto Heap::AllocateValue(Ptr v) -> Address { +auto Heap::AllocateValue(Nonnull v) -> Address { // Putting the following two side effects together in this function // ensures that we don't do anything else in between, which is really bad! // Consider whether to include a copy of the input v in this function @@ -20,12 +20,13 @@ auto Heap::AllocateValue(Ptr v) -> Address { return a; } -auto Heap::Read(const Address& a, SourceLocation loc) -> Ptr { +auto Heap::Read(const Address& a, SourceLocation loc) -> Nonnull { this->CheckAlive(a, loc); return values[a.index]->GetField(arena, a.field_path, loc); } -void Heap::Write(const Address& a, Ptr v, SourceLocation loc) { +void Heap::Write(const Address& a, Nonnull v, + SourceLocation loc) { this->CheckAlive(a, loc); values[a.index] = values[a.index]->SetField(arena, a.field_path, v, loc); } diff --git a/executable_semantics/interpreter/heap.h b/executable_semantics/interpreter/heap.h index 30ba4956ff7d..e5bb27a088e4 100644 --- a/executable_semantics/interpreter/heap.h +++ b/executable_semantics/interpreter/heap.h @@ -18,21 +18,21 @@ namespace Carbon { class Heap { public: // Constructs an empty Heap. - explicit Heap(Ptr arena) : arena(arena){}; + explicit Heap(Nonnull arena) : arena(arena){}; Heap(const Heap&) = delete; Heap& operator=(const Heap&) = delete; // Returns the value at the given address in the heap after // checking that it is alive. - auto Read(const Address& a, SourceLocation loc) -> Ptr; + auto Read(const Address& a, SourceLocation loc) -> Nonnull; // Writes the given value at the address in the heap after // checking that the address is alive. - void Write(const Address& a, Ptr v, SourceLocation loc); + void Write(const Address& a, Nonnull v, SourceLocation loc); // Put the given value on the heap and mark it as alive. - auto AllocateValue(Ptr v) -> Address; + auto AllocateValue(Nonnull v) -> Address; // Marks the object at this address, and all of its sub-objects, as dead. void Deallocate(const Address& address); @@ -49,8 +49,8 @@ class Heap { // Signal an error if the address is no longer alive. void CheckAlive(const Address& address, SourceLocation loc); - Ptr arena; - std::vector> values; + Nonnull arena; + std::vector> values; std::vector alive; }; diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index e5e389d22397..8f636fe5a2a5 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -46,7 +46,7 @@ void Interpreter::PrintEnv(Env values, llvm::raw_ostream& out) { // auto Interpreter::CurrentEnv() -> Env { - Ptr frame = stack.Top(); + Nonnull frame = stack.Top(); return frame->scopes.Top()->values; } @@ -75,8 +75,8 @@ void Interpreter::PrintState(llvm::raw_ostream& out) { } auto Interpreter::EvalPrim(Operator op, - const std::vector>& args, - SourceLocation loc) -> Ptr { + const std::vector>& args, + SourceLocation loc) -> Nonnull { switch (op) { case Operator::Neg: return arena->New(-cast(*args[0]).Val()); @@ -128,11 +128,12 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { const ClassDefinition& class_def = cast(d).Definition(); VarValues fields; VarValues methods; - for (Ptr m : class_def.members) { + for (Nonnull m : class_def.members) { switch (m->Tag()) { case Member::Kind::FieldMember: { - Ptr binding = cast(*m).Binding(); - Ptr type_expression = + Nonnull binding = + cast(*m).Binding(); + Nonnull type_expression = cast(*binding->Type()).Expression(); auto type = InterpExp(Env(arena), type_expression); fields.push_back(make_pair(*binding->Name(), type)); @@ -172,13 +173,14 @@ void Interpreter::InitEnv(const Declaration& d, Env* env) { } } -void Interpreter::InitGlobals(const std::vector>& fs) { +void Interpreter::InitGlobals( + const std::vector>& fs) { for (const auto d : fs) { InitEnv(*d, &globals); } } -void Interpreter::DeallocateScope(Ptr scope) { +void Interpreter::DeallocateScope(Nonnull scope) { for (const auto& l : scope->locals) { std::optional
a = scope->values.Get(l); CHECK(a); @@ -186,15 +188,16 @@ void Interpreter::DeallocateScope(Ptr scope) { } } -void Interpreter::DeallocateLocals(Ptr frame) { +void Interpreter::DeallocateLocals(Nonnull frame) { while (!frame->scopes.IsEmpty()) { DeallocateScope(frame->scopes.Top()); frame->scopes.Pop(); } } -auto Interpreter::CreateTuple(Ptr act, Ptr exp) - -> Ptr { +auto Interpreter::CreateTuple(Nonnull act, + Nonnull exp) + -> Nonnull { // { { (v1,...,vn) :: C, E, F} :: S, H} // -> { { `(v1,...,vn) :: C, E, F} :: S, H} const auto& tup_lit = cast(*exp); @@ -208,7 +211,7 @@ auto Interpreter::CreateTuple(Ptr act, Ptr exp) return arena->New(std::move(elements)); } -auto Interpreter::PatternMatch(Ptr p, Ptr v, +auto Interpreter::PatternMatch(Nonnull p, Nonnull v, SourceLocation loc) -> std::optional { switch (p->Tag()) { case Value::Kind::BindingPlaceholderValue: { @@ -303,7 +306,8 @@ auto Interpreter::PatternMatch(Ptr p, Ptr v, } } -void Interpreter::PatternAssignment(Ptr pat, Ptr val, +void Interpreter::PatternAssignment(Nonnull pat, + Nonnull val, SourceLocation loc) { switch (pat->Tag()) { case Value::Kind::PointerValue: @@ -320,7 +324,7 @@ void Interpreter::PatternAssignment(Ptr pat, Ptr val, << pat_tup << "\n value: " << val_tup; } for (const TupleElement& pattern_element : pat_tup.Elements()) { - std::optional> value_field = + std::optional> value_field = val_tup.FindField(pattern_element.name); if (!value_field) { FATAL_RUNTIME_ERROR(loc) @@ -358,8 +362,8 @@ void Interpreter::PatternAssignment(Ptr pat, Ptr val, } auto Interpreter::StepLvalue() -> Transition { - Ptr act = stack.Top()->todo.Top(); - Ptr exp = cast(*act).Exp(); + Nonnull act = stack.Top()->todo.Top(); + Nonnull exp = cast(*act).Exp(); if (tracing_output) { llvm::outs() << "--- step lvalue " << *exp << " (" << exp->SourceLoc() << ") --->\n"; @@ -370,7 +374,7 @@ auto Interpreter::StepLvalue() -> Transition { // -> { {E(x) :: C, E, F} :: S, H} Address pointer = GetFromEnv(exp->SourceLoc(), cast(*exp).Name()); - Ptr v = arena->New(pointer); + Nonnull v = arena->New(pointer); return Done{v}; } case Expression::Kind::FieldAccessExpression: { @@ -412,7 +416,7 @@ auto Interpreter::StepLvalue() -> Transition { if (act->Pos() == 0) { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} - Ptr e1 = + Nonnull e1 = cast(*exp).Fields()[0].expression; return Spawn{arena->New(e1)}; } else if (act->Pos() != @@ -421,7 +425,7 @@ auto Interpreter::StepLvalue() -> Transition { // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} - Ptr elt = + Nonnull elt = cast(*exp).Fields()[act->Pos()].expression; return Spawn{arena->New(elt)}; } else { @@ -446,8 +450,8 @@ auto Interpreter::StepLvalue() -> Transition { } auto Interpreter::StepExp() -> Transition { - Ptr act = stack.Top()->todo.Top(); - Ptr exp = cast(*act).Exp(); + Nonnull act = stack.Top()->todo.Top(); + Nonnull exp = cast(*act).Exp(); if (tracing_output) { llvm::outs() << "--- step exp " << *exp << " (" << exp->SourceLoc() << ") --->\n"; @@ -472,7 +476,7 @@ auto Interpreter::StepExp() -> Transition { } std::string f = std::to_string(cast(*act->Results()[1]).Val()); - std::optional> field = tuple->FindField(f); + std::optional> field = tuple->FindField(f); if (!field) { FATAL_RUNTIME_ERROR_NO_LINE() << "field " << f << " not in " << *tuple; @@ -485,7 +489,7 @@ auto Interpreter::StepExp() -> Transition { if (cast(*exp).Fields().size() > 0) { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} - Ptr e1 = + Nonnull e1 = cast(*exp).Fields()[0].expression; return Spawn{arena->New(e1)}; } else { @@ -497,7 +501,7 @@ auto Interpreter::StepExp() -> Transition { // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} - Ptr elt = + Nonnull elt = cast(*exp).Fields()[act->Pos()].expression; return Spawn{arena->New(elt)}; } else { @@ -537,7 +541,7 @@ auto Interpreter::StepExp() -> Transition { if (act->Pos() != static_cast(op.Arguments().size())) { // { {v :: op(vs,[],e,es) :: C, E, F} :: S, H} // -> { {e :: op(vs,v,[],es) :: C, E, F} :: S, H} - Ptr arg = op.Arguments()[act->Pos()]; + Nonnull arg = op.Arguments()[act->Pos()]; return Spawn{arena->New(arg)}; } else { // { {v :: op(vs,[]) :: C, E, F} :: S, H} @@ -561,14 +565,14 @@ auto Interpreter::StepExp() -> Transition { // -> { {C',E',F'} :: {C, E, F} :: S, H} switch (act->Results()[0]->Tag()) { case Value::Kind::ClassType: { - Ptr arg = + Nonnull arg = CopyVal(arena, act->Results()[1], exp->SourceLoc()); return Done{arena->New(act->Results()[0], arg)}; } case Value::Kind::AlternativeConstructorValue: { const auto& alt = cast(*act->Results()[0]); - Ptr arg = + Nonnull arg = CopyVal(arena, act->Results()[1], exp->SourceLoc()); return Done{arena->New(alt.AltName(), alt.ChoiceName(), arg)}; @@ -577,7 +581,7 @@ auto Interpreter::StepExp() -> Transition { return CallFunction{ // TODO: Think about a cleaner way to cast between Ptr types. // (multiple TODOs) - .function = Ptr( + .function = Nonnull( cast(act->Results()[0])), .args = act->Results()[1], .loc = exp->SourceLoc()}; @@ -594,7 +598,7 @@ auto Interpreter::StepExp() -> Transition { switch (cast(*exp).Intrinsic()) { case IntrinsicExpression::IntrinsicKind::Print: Address pointer = GetFromEnv(exp->SourceLoc(), "format_str"); - Ptr pointee = heap.Read(pointer, exp->SourceLoc()); + Nonnull pointee = heap.Read(pointer, exp->SourceLoc()); CHECK(pointee->Tag() == Value::Kind::StringValue); // TODO: This could eventually use something like llvm::formatv. llvm::outs() << cast(*pointee).Val(); @@ -646,8 +650,8 @@ auto Interpreter::StepExp() -> Transition { } auto Interpreter::StepPattern() -> Transition { - Ptr act = stack.Top()->todo.Top(); - Ptr pattern = cast(*act).Pat(); + Nonnull act = stack.Top()->todo.Top(); + Nonnull pattern = cast(*act).Pat(); if (tracing_output) { llvm::outs() << "--- step pattern " << *pattern << " (" << pattern->SourceLoc() << ") --->\n"; @@ -672,7 +676,7 @@ auto Interpreter::StepPattern() -> Transition { if (tuple.Fields().empty()) { return Done{TupleValue::Empty()}; } else { - Ptr p1 = tuple.Fields()[0].pattern; + Nonnull p1 = tuple.Fields()[0].pattern; return Spawn{(arena->New(p1))}; } } else if (act->Pos() != static_cast(tuple.Fields().size())) { @@ -680,7 +684,7 @@ auto Interpreter::StepPattern() -> Transition { // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} - Ptr elt = tuple.Fields()[act->Pos()].pattern; + Nonnull elt = tuple.Fields()[act->Pos()].pattern; return Spawn{arena->New(elt)}; } else { std::vector elements; @@ -711,7 +715,7 @@ auto Interpreter::StepPattern() -> Transition { } } -static auto IsWhileAct(Ptr act) -> bool { +static auto IsWhileAct(Nonnull act) -> bool { switch (act->Tag()) { case Action::Kind::StatementAction: switch (cast(*act).Stmt()->Tag()) { @@ -725,7 +729,7 @@ static auto IsWhileAct(Ptr act) -> bool { } } -static auto HasLocalScope(Ptr act) -> bool { +static auto HasLocalScope(Nonnull act) -> bool { switch (act->Tag()) { case Action::Kind::StatementAction: switch (cast(*act).Stmt()->Tag()) { @@ -741,9 +745,9 @@ static auto HasLocalScope(Ptr act) -> bool { } auto Interpreter::StepStmt() -> Transition { - Ptr frame = stack.Top(); - Ptr act = frame->todo.Top(); - Ptr stmt = cast(*act).Stmt(); + Nonnull frame = stack.Top(); + Nonnull act = frame->todo.Top(); + Nonnull stmt = cast(*act).Stmt(); if (tracing_output) { llvm::outs() << "--- step stmt "; stmt->PrintDepth(1, llvm::outs()); @@ -849,7 +853,7 @@ auto Interpreter::StepStmt() -> Transition { return Done{}; } } else { - Ptr scope = frame->scopes.Top(); + Nonnull scope = frame->scopes.Top(); DeallocateScope(scope); frame->scopes.Pop(1); return Done{}; @@ -867,8 +871,8 @@ auto Interpreter::StepStmt() -> Transition { } else { // { { v :: (x = []) :: C, E, F} :: S, H} // -> { { C, E(x := a), F} :: S, H(a := copy(v))} - Ptr v = act->Results()[0]; - Ptr p = act->Results()[1]; + Nonnull v = act->Results()[0]; + Nonnull p = act->Results()[1]; std::optional matches = PatternMatch(p, v, stmt->SourceLoc()); CHECK(matches) @@ -934,7 +938,7 @@ auto Interpreter::StepStmt() -> Transition { } else { // { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H} // -> { {v :: C', E', F'} :: S, H} - Ptr ret_val = + Nonnull ret_val = CopyVal(arena, act->Results()[0], stmt->SourceLoc()); return UnwindFunctionCall{ret_val}; } @@ -957,8 +961,8 @@ auto Interpreter::StepStmt() -> Transition { CHECK(act->Pos() == 0); // Create a continuation object by creating a frame similar the // way one is created in a function call. - auto scopes = Stack>(arena->New(CurrentEnv())); - Stack> todo; + auto scopes = Stack>(arena->New(CurrentEnv())); + Stack> todo; todo.Push(arena->New( arena->New(arena, stmt->SourceLoc()))); todo.Push(arena->New(cast(*stmt).Body())); @@ -966,7 +970,7 @@ auto Interpreter::StepStmt() -> Transition { arena->New("__continuation", scopes, todo); Address continuation_address = heap.AllocateValue(arena->New( - std::vector>({continuation_frame}))); + std::vector>({continuation_frame}))); // Store the continuation's address in the frame. continuation_frame->continuation = continuation_address; // Bind the continuation object to the continuation variable @@ -991,7 +995,7 @@ auto Interpreter::StepStmt() -> Transition { arena->New(stmt->SourceLoc()))); frame->todo.Push(ignore_result); // Push the continuation onto the current stack. - const std::vector>& continuation_vector = + const std::vector>& continuation_vector = cast(*act->Results()[0]).Stack(); for (auto frame_iter = continuation_vector.rbegin(); frame_iter != continuation_vector.rend(); ++frame_iter) { @@ -1003,7 +1007,7 @@ auto Interpreter::StepStmt() -> Transition { CHECK(act->Pos() == 0); // Pause the current continuation frame->todo.Pop(); - std::vector> paused; + std::vector> paused; do { paused.push_back(stack.Pop()); } while (paused.back()->continuation == std::nullopt); @@ -1020,7 +1024,7 @@ class Interpreter::DoTransition { DoTransition(Interpreter* interpreter) : interpreter(interpreter) {} void operator()(const Done& done) { - Ptr frame = interpreter->stack.Top(); + Nonnull frame = interpreter->stack.Top(); if (frame->todo.Top()->Tag() != Action::Kind::StatementAction) { CHECK(done.result); frame->todo.Pop(); @@ -1036,25 +1040,25 @@ class Interpreter::DoTransition { } void operator()(const Spawn& spawn) { - Ptr frame = interpreter->stack.Top(); - Ptr action = frame->todo.Top(); + Nonnull frame = interpreter->stack.Top(); + Nonnull action = frame->todo.Top(); action->SetPos(action->Pos() + 1); frame->todo.Push(spawn.child); } void operator()(const Delegate& delegate) { - Ptr frame = interpreter->stack.Top(); + Nonnull frame = interpreter->stack.Top(); frame->todo.Pop(); frame->todo.Push(delegate.delegate); } void operator()(const RunAgain&) { - Ptr action = interpreter->stack.Top()->todo.Top(); + Nonnull action = interpreter->stack.Top()->todo.Top(); action->SetPos(action->Pos() + 1); } void operator()(const UnwindTo& unwind_to) { - Ptr frame = interpreter->stack.Top(); + Nonnull frame = interpreter->stack.Top(); while (frame->todo.Top() != unwind_to.new_top) { if (HasLocalScope(frame->todo.Top())) { interpreter->DeallocateScope(frame->scopes.Top()); @@ -1088,9 +1092,9 @@ class Interpreter::DoTransition { params.push_back(name); } auto scopes = - Stack>(interpreter->arena->New(values, params)); + Stack>(interpreter->arena->New(values, params)); CHECK(call.function->Body()) << "Calling a function that's missing a body"; - auto todo = Stack>( + auto todo = Stack>( interpreter->arena->New(*call.function->Body())); auto frame = interpreter->arena->New(call.function->Name(), scopes, todo); @@ -1100,18 +1104,18 @@ class Interpreter::DoTransition { void operator()(const ManualTransition&) {} private: - Ptr interpreter; + Nonnull interpreter; }; // State transition. void Interpreter::Step() { - Ptr frame = stack.Top(); + Nonnull frame = stack.Top(); if (frame->todo.IsEmpty()) { FATAL_RUNTIME_ERROR_NO_LINE() << "fell off end of function " << frame->name << " without `return`"; } - Ptr act = frame->todo.Top(); + Nonnull act = frame->todo.Top(); switch (act->Tag()) { case Action::Kind::LValAction: std::visit(DoTransition(this), StepLvalue()); @@ -1128,8 +1132,8 @@ void Interpreter::Step() { } // switch } -auto Interpreter::InterpProgram(const std::vector>& fs) - -> int { +auto Interpreter::InterpProgram( + const std::vector>& fs) -> int { // Check that the interpreter is in a clean state. CHECK(globals.IsEmpty()); CHECK(stack.IsEmpty()); @@ -1142,12 +1146,12 @@ auto Interpreter::InterpProgram(const std::vector>& fs) SourceLocation loc("", 0); - Ptr arg = arena->New(loc); - Ptr call_main = arena->New( + Nonnull arg = arena->New(loc); + Nonnull call_main = arena->New( loc, arena->New(loc, "main"), arg); - auto todo = Stack>(arena->New(call_main)); - auto scopes = Stack>(arena->New(globals)); - stack = Stack>(arena->New("top", scopes, todo)); + auto todo = Stack>(arena->New(call_main)); + auto scopes = Stack>(arena->New(globals)); + stack = Stack>(arena->New("top", scopes, todo)); if (tracing_output) { llvm::outs() << "********** calling main function **********\n"; @@ -1163,14 +1167,14 @@ auto Interpreter::InterpProgram(const std::vector>& fs) return cast(**program_value).Val(); } -auto Interpreter::InterpExp(Env values, Ptr e) - -> Ptr { +auto Interpreter::InterpExp(Env values, Nonnull e) + -> Nonnull { CHECK(program_value == std::nullopt); auto program_value_guard = llvm::make_scope_exit([&] { program_value = std::nullopt; }); - auto todo = Stack>(arena->New(e)); - auto scopes = Stack>(arena->New(values)); - stack = Stack>(arena->New("InterpExp", scopes, todo)); + auto todo = Stack>(arena->New(e)); + auto scopes = Stack>(arena->New(values)); + stack = Stack>(arena->New("InterpExp", scopes, todo)); while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) { Step(); @@ -1179,14 +1183,15 @@ auto Interpreter::InterpExp(Env values, Ptr e) return *program_value; } -auto Interpreter::InterpPattern(Env values, Ptr p) - -> Ptr { +auto Interpreter::InterpPattern(Env values, Nonnull p) + -> Nonnull { CHECK(program_value == std::nullopt); auto program_value_guard = llvm::make_scope_exit([&] { program_value = std::nullopt; }); - auto todo = Stack>(arena->New(p)); - auto scopes = Stack>(arena->New(values)); - stack = Stack>(arena->New("InterpPattern", scopes, todo)); + auto todo = Stack>(arena->New(p)); + auto scopes = Stack>(arena->New(values)); + stack = + Stack>(arena->New("InterpPattern", scopes, todo)); while (stack.Count() > 1 || !stack.Top()->todo.IsEmpty()) { Step(); diff --git a/executable_semantics/interpreter/interpreter.h b/executable_semantics/interpreter/interpreter.h index d824d97a3096..6735b6d17f6d 100644 --- a/executable_semantics/interpreter/interpreter.h +++ b/executable_semantics/interpreter/interpreter.h @@ -24,25 +24,27 @@ using Env = Dictionary; class Interpreter { public: - explicit Interpreter(Ptr arena) + explicit Interpreter(Nonnull arena) : arena(arena), globals(arena), heap(arena) {} // Interpret the whole program. - auto InterpProgram(const std::vector>& fs) -> int; + auto InterpProgram(const std::vector>& fs) -> int; // Interpret an expression at compile-time. - auto InterpExp(Env values, Ptr e) -> Ptr; + auto InterpExp(Env values, Nonnull e) + -> Nonnull; // Interpret a pattern at compile-time. - auto InterpPattern(Env values, Ptr p) -> Ptr; + auto InterpPattern(Env values, Nonnull p) + -> Nonnull; // Attempts to match `v` against the pattern `p`. If matching succeeds, // returns the bindings of pattern variables to their matched values. - auto PatternMatch(Ptr p, Ptr v, SourceLocation loc) - -> std::optional; + auto PatternMatch(Nonnull p, Nonnull v, + SourceLocation loc) -> std::optional; // Support TypeChecker allocating values on the heap. - auto AllocateValue(Ptr v) -> Address { + auto AllocateValue(Nonnull v) -> Address { return heap.AllocateValue(v); } @@ -62,19 +64,19 @@ class Interpreter { struct Done { // The value computed by the Action. Should always be nullopt for Statement // Actions, and never null for any other kind of Action. - std::optional> result; + std::optional> result; }; // Transition type which spawns a new Action on the todo stack above the // current Action, and increments the current Action's position counter. struct Spawn { - Ptr child; + Nonnull child; }; // Transition type which spawns a new Action that replaces the current action // on the todo stack. struct Delegate { - Ptr delegate; + Nonnull delegate; }; // Transition type which keeps the current Action at the top of the stack, @@ -84,21 +86,21 @@ class Interpreter { // Transition type which unwinds the `todo` and `scopes` stacks until it // reaches a specified Action lower in the stack. struct UnwindTo { - const Ptr new_top; + const Nonnull new_top; }; // Transition type which unwinds the entire current stack frame, and returns // a specified value to the caller. struct UnwindFunctionCall { - Ptr return_val; + Nonnull return_val; }; // Transition type which removes the current action from the top of the todo // stack, then creates a new stack frame which calls the specified function // with the specified arguments. struct CallFunction { - Ptr function; - Ptr args; + Nonnull function; + Nonnull args; SourceLocation loc; }; @@ -126,32 +128,32 @@ class Interpreter { // State transition for statements. auto StepStmt() -> Transition; - void InitGlobals(const std::vector>& fs); + void InitGlobals(const std::vector>& fs); auto CurrentEnv() -> Env; auto GetFromEnv(SourceLocation loc, const std::string& name) -> Address; - void DeallocateScope(Ptr scope); - void DeallocateLocals(Ptr frame); + void DeallocateScope(Nonnull scope); + void DeallocateLocals(Nonnull frame); - auto CreateTuple(Ptr act, Ptr exp) - -> Ptr; + auto CreateTuple(Nonnull act, Nonnull exp) + -> Nonnull; - auto EvalPrim(Operator op, const std::vector>& args, - SourceLocation loc) -> Ptr; + auto EvalPrim(Operator op, const std::vector>& args, + SourceLocation loc) -> Nonnull; - void PatternAssignment(Ptr pat, Ptr val, + void PatternAssignment(Nonnull pat, Nonnull val, SourceLocation loc); void PrintState(llvm::raw_ostream& out); - Ptr arena; + Nonnull arena; // Globally-defined entities, such as functions, structs, or choices. Env globals; - Stack> stack; + Stack> stack; Heap heap; - std::optional> program_value; + std::optional> program_value; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/type_checker.cpp b/executable_semantics/interpreter/type_checker.cpp index a4dc3f63f05c..df56f5418e7d 100644 --- a/executable_semantics/interpreter/type_checker.cpp +++ b/executable_semantics/interpreter/type_checker.cpp @@ -33,7 +33,8 @@ void PrintTypeEnv(TypeEnv types, llvm::raw_ostream& out) { } static void ExpectType(SourceLocation loc, const std::string& context, - Ptr expected, Ptr actual) { + Nonnull expected, + Nonnull actual) { if (!TypeEqual(expected, actual)) { FATAL_COMPILATION_ERROR(loc) << "type error in " << context << "\n" << "expected: " << *expected << "\n" @@ -42,7 +43,7 @@ static void ExpectType(SourceLocation loc, const std::string& context, } static void ExpectPointerType(SourceLocation loc, const std::string& context, - Ptr actual) { + Nonnull actual) { if (actual->Tag() != Value::Kind::PointerType) { FATAL_COMPILATION_ERROR(loc) << "type error in " << context << "\n" << "expected a pointer type\n" @@ -50,8 +51,8 @@ static void ExpectPointerType(SourceLocation loc, const std::string& context, } } -auto TypeChecker::ReifyType(Ptr t, SourceLocation loc) - -> Ptr { +auto TypeChecker::ReifyType(Nonnull t, SourceLocation loc) + -> Nonnull { switch (t->Tag()) { case Value::Kind::IntType: return arena->New(loc); @@ -82,7 +83,7 @@ auto TypeChecker::ReifyType(Ptr t, SourceLocation loc) case Value::Kind::PointerType: return arena->New( loc, Operator::Ptr, - std::vector>( + std::vector>( {ReifyType(cast(*t).Type(), loc)})); case Value::Kind::VariableType: return arena->New(loc, @@ -111,12 +112,12 @@ auto TypeChecker::ReifyType(Ptr t, SourceLocation loc) // The `deduced` parameter is an accumulator, that is, it holds the // results so-far. static auto ArgumentDeduction(SourceLocation loc, TypeEnv deduced, - Ptr param, Ptr arg) - -> TypeEnv { + Nonnull param, + Nonnull arg) -> TypeEnv { switch (param->Tag()) { case Value::Kind::VariableType: { const auto& var_type = cast(*param); - std::optional> d = deduced.Get(var_type.Name()); + std::optional> d = deduced.Get(var_type.Name()); if (!d) { deduced.Set(var_type.Name(), arg); } else { @@ -192,11 +193,11 @@ static auto ArgumentDeduction(SourceLocation loc, TypeEnv deduced, } } -auto TypeChecker::Substitute(TypeEnv dict, Ptr type) - -> Ptr { +auto TypeChecker::Substitute(TypeEnv dict, Nonnull type) + -> Nonnull { switch (type->Tag()) { case Value::Kind::VariableType: { - std::optional> t = + std::optional> t = dict.Get(cast(*type).Name()); if (!t) { return type; @@ -247,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Ptr type) } } -auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, +auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, Env values) -> TCExpression { if (tracing_output) { llvm::outs() << "checking expression " << *e << "\ntypes: "; @@ -267,7 +268,7 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, cast(*interpreter.InterpExp(values, index.Offset())) .Val(); std::string f = std::to_string(i); - std::optional> field_t = + std::optional> field_t = cast(*t).FindField(f); if (!field_t) { FATAL_COMPILATION_ERROR(e->SourceLoc()) @@ -306,16 +307,18 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, // Search for a field for (auto& field : t_class.Fields()) { if (access.Field() == field.first) { - Ptr new_e = arena->New( - e->SourceLoc(), res.exp, access.Field()); + Nonnull new_e = + arena->New(e->SourceLoc(), res.exp, + access.Field()); return TCExpression(new_e, field.second, res.types); } } // Search for a method for (auto& method : t_class.Methods()) { if (access.Field() == method.first) { - Ptr new_e = arena->New( - e->SourceLoc(), res.exp, access.Field()); + Nonnull new_e = + arena->New(e->SourceLoc(), res.exp, + access.Field()); return TCExpression(new_e, method.second, res.types); } } @@ -340,8 +343,9 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, const auto& choice = cast(*t); for (const auto& vt : choice.Alternatives()) { if (access.Field() == vt.first) { - Ptr new_e = arena->New( - e->SourceLoc(), res.exp, access.Field()); + Nonnull new_e = + arena->New(e->SourceLoc(), res.exp, + access.Field()); auto fun_ty = arena->New( std::vector(), vt.second, t); return TCExpression(new_e, fun_ty, res.types); @@ -359,7 +363,7 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, } case Expression::Kind::IdentifierExpression: { const auto& ident = cast(*e); - std::optional> type = types.Get(ident.Name()); + std::optional> type = types.Get(ident.Name()); if (type) { return TCExpression(e, *type, types); } else { @@ -373,10 +377,10 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, return TCExpression(e, arena->New(), types); case Expression::Kind::PrimitiveOperatorExpression: { const auto& op = cast(*e); - std::vector> es; - std::vector> ts; + std::vector> es; + std::vector> ts; auto new_types = types; - for (Ptr argument : op.Arguments()) { + for (Nonnull argument : op.Arguments()) { auto res = TypeCheckExp(argument, types, values); new_types = res.types; es.push_back(res.exp); @@ -494,10 +498,9 @@ auto TypeChecker::TypeCheckExp(Ptr e, TypeEnv types, } } -auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, - Env values, - std::optional> expected) - -> TCPattern { +auto TypeChecker::TypeCheckPattern( + Nonnull p, TypeEnv types, Env values, + std::optional> expected) -> TCPattern { if (tracing_output) { llvm::outs() << "checking pattern " << *p; if (expected) { @@ -517,7 +520,7 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, const auto& binding = cast(*p); TCPattern binding_type_result = TypeCheckPattern(binding.Type(), types, values, std::nullopt); - Ptr type = + Nonnull type = interpreter.InterpPattern(values, binding_type_result.pattern); if (expected) { std::optional values = interpreter.PatternMatch( @@ -554,7 +557,7 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, } for (size_t i = 0; i < tuple.Fields().size(); ++i) { const TuplePattern::Field& field = tuple.Fields()[i]; - std::optional> expected_field_type; + std::optional> expected_field_type; if (expected) { const TupleElement& expected_element = cast(**expected).Elements()[i]; @@ -578,7 +581,7 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, } case Pattern::Kind::AlternativePattern: { const auto& alternative = cast(*p); - Ptr choice_type = + Nonnull choice_type = interpreter.InterpExp(values, alternative.ChoiceType()); if (choice_type->Tag() != Value::Kind::ChoiceType) { FATAL_COMPILATION_ERROR(alternative.SourceLoc()) @@ -588,7 +591,7 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, ExpectType(alternative.SourceLoc(), "alternative pattern", *expected, choice_type); } - std::optional> parameter_types = + std::optional> parameter_types = FindInVarValues(alternative.AlternativeName(), cast(*choice_type).Alternatives()); if (parameter_types == std::nullopt) { @@ -600,7 +603,7 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, values, *parameter_types); // TODO: Think about a cleaner way to cast between Ptr types. // (multiple TODOs) - auto arguments = Ptr( + auto arguments = Nonnull( cast(arg_results.pattern)); return {.pattern = arena->New( alternative.SourceLoc(), @@ -619,27 +622,27 @@ auto TypeChecker::TypeCheckPattern(Ptr p, TypeEnv types, } } -auto TypeChecker::TypeCheckCase(Ptr expected, - Ptr pat, - Ptr body, TypeEnv types, - Env values, Ptr& ret_type, +auto TypeChecker::TypeCheckCase(Nonnull expected, + Nonnull pat, + Nonnull body, TypeEnv types, + Env values, Nonnull& ret_type, bool is_omitted_ret_type) - -> std::pair, Ptr> { + -> std::pair, Nonnull> { auto pat_res = TypeCheckPattern(pat, types, values, expected); auto res = TypeCheckStmt(body, pat_res.types, values, ret_type, is_omitted_ret_type); return std::make_pair(pat, res.stmt); } -auto TypeChecker::TypeCheckStmt(Ptr s, TypeEnv types, - Env values, Ptr& ret_type, +auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, + Env values, Nonnull& ret_type, bool is_omitted_ret_type) -> TCStatement { switch (s->Tag()) { case Statement::Kind::Match: { const auto& match = cast(*s); auto res = TypeCheckExp(match.Exp(), types, values); auto res_type = res.type; - std::vector, Ptr>> + std::vector, Nonnull>> new_clauses; for (auto& clause : match.Clauses()) { new_clauses.push_back(TypeCheckCase(res_type, clause.first, @@ -677,7 +680,7 @@ auto TypeChecker::TypeCheckStmt(Ptr s, TypeEnv types, case Statement::Kind::VariableDefinition: { const auto& var = cast(*s); auto res = TypeCheckExp(var.Init(), types, values); - Ptr rhs_ty = res.type; + Nonnull rhs_ty = res.type; auto lhs_res = TypeCheckPattern(var.Pat(), types, values, rhs_ty); auto new_s = arena->New(s->SourceLoc(), var.Pat(), res.exp); @@ -688,7 +691,7 @@ auto TypeChecker::TypeCheckStmt(Ptr s, TypeEnv types, auto stmt_res = TypeCheckStmt(seq.Stmt(), types, values, ret_type, is_omitted_ret_type); auto checked_types = stmt_res.types; - std::optional> next_stmt; + std::optional> next_stmt; if (seq.Next()) { auto next_res = TypeCheckStmt(*seq.Next(), checked_types, values, ret_type, is_omitted_ret_type); @@ -722,7 +725,7 @@ auto TypeChecker::TypeCheckStmt(Ptr s, TypeEnv types, cnd_res.type); auto then_res = TypeCheckStmt(if_stmt.ThenStmt(), types, values, ret_type, is_omitted_ret_type); - std::optional> else_stmt; + std::optional> else_stmt; if (if_stmt.ElseStmt()) { auto else_res = TypeCheckStmt(*if_stmt.ElseStmt(), types, values, ret_type, is_omitted_ret_type); @@ -777,8 +780,8 @@ auto TypeChecker::TypeCheckStmt(Ptr s, TypeEnv types, } auto TypeChecker::CheckOrEnsureReturn( - std::optional> opt_stmt, bool omitted_ret_type, - SourceLocation loc) -> Ptr { + std::optional> opt_stmt, bool omitted_ret_type, + SourceLocation loc) -> Nonnull { if (!opt_stmt) { if (omitted_ret_type) { return arena->New(arena, loc); @@ -788,11 +791,11 @@ auto TypeChecker::CheckOrEnsureReturn( "type without reaching a return statement"; } } - Ptr stmt = *opt_stmt; + Nonnull stmt = *opt_stmt; switch (stmt->Tag()) { case Statement::Kind::Match: { const auto& match = cast(*stmt); - std::vector, Ptr>> + std::vector, Nonnull>> new_clauses; for (const auto& clause : match.Clauses()) { auto s = CheckOrEnsureReturn(clause.second, omitted_ret_type, @@ -855,7 +858,8 @@ auto TypeChecker::CheckOrEnsureReturn( // TODO: Add checking to function definitions to ensure that // all deduced type parameters will be deduced. auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, - Env values) -> Ptr { + Env values) + -> Nonnull { // Bring the deduced parameters into scope for (const auto& deduced : f->deduced_parameters) { // auto t = interpreter.InterpExp(values, deduced.type); @@ -873,7 +877,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, arena->New(), return_type); // TODO: Check that main doesn't have any parameters. } - std::optional> body_stmt; + std::optional> body_stmt; if (f->body) { auto res = TypeCheckStmt(*f->body, param_res.types, values, return_type, f->is_omitted_return_type); @@ -889,7 +893,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values, const FunctionDefinition* fun_def) - -> Ptr { + -> Nonnull { // Bring the deduced parameters into scope for (const auto& deduced : fun_def->deduced_parameters) { // auto t = interpreter.InterpExp(values, deduced.type); @@ -911,13 +915,14 @@ auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values, } auto TypeChecker::TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, - Env ct_top) -> Ptr { + Env ct_top) -> Nonnull { VarValues fields; VarValues methods; - for (Ptr m : sd->members) { + for (Nonnull m : sd->members) { switch (m->Tag()) { case Member::Kind::FieldMember: { - Ptr binding = cast(*m).Binding(); + Nonnull binding = + cast(*m).Binding(); if (!binding->Name().has_value()) { FATAL_COMPILATION_ERROR(binding->SourceLoc()) << "Struct members must have names"; @@ -945,7 +950,7 @@ static auto GetName(const Declaration& d) -> const std::string& { case Declaration::Kind::ChoiceDeclaration: return cast(d).Name(); case Declaration::Kind::VariableDeclaration: { - Ptr binding = + Nonnull binding = cast(d).Binding(); if (!binding->Name().has_value()) { FATAL_COMPILATION_ERROR(binding->SourceLoc()) @@ -956,9 +961,9 @@ static auto GetName(const Declaration& d) -> const std::string& { } } -auto TypeChecker::MakeTypeChecked(const Ptr d, +auto TypeChecker::MakeTypeChecked(const Nonnull d, const TypeEnv& types, const Env& values) - -> Ptr { + -> Nonnull { switch (d->Tag()) { case Declaration::Kind::FunctionDeclaration: return arena->New(TypeCheckFunDef( @@ -967,8 +972,8 @@ auto TypeChecker::MakeTypeChecked(const Ptr d, case Declaration::Kind::ClassDeclaration: { const ClassDefinition& class_def = cast(*d).Definition(); - std::vector> fields; - for (Ptr m : class_def.members) { + std::vector> fields; + for (Nonnull m : class_def.members) { switch (m->Tag()) { case Member::Kind::FieldMember: // TODO: Interpret the type expression and store the result. @@ -998,7 +1003,7 @@ auto TypeChecker::MakeTypeChecked(const Ptr d, FATAL_COMPILATION_ERROR(var.SourceLoc()) << "Type of a top-level variable must be an expression."; } - Ptr declared_type = + Nonnull declared_type = interpreter.InterpExp(values, binding_type->Expression()); ExpectType(var.SourceLoc(), "initializer of variable", declared_type, type_checked_initializer.type); @@ -1053,9 +1058,9 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { const auto& var = cast(d); // Associate the variable name with it's declared type in the // compile-time symbol table. - Ptr type = + Nonnull type = cast(*var.Binding()->Type()).Expression(); - Ptr declared_type = + Nonnull declared_type = interpreter.InterpExp(tops->values, type); tops->types.Set(*var.Binding()->Name(), declared_type); break; @@ -1063,7 +1068,7 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { } } -auto TypeChecker::TopLevel(const std::vector>& fs) +auto TypeChecker::TopLevel(const std::vector>& fs) -> TypeCheckContext { TypeCheckContext tops(arena); bool found_main = false; diff --git a/executable_semantics/interpreter/type_checker.h b/executable_semantics/interpreter/type_checker.h index 13cc86804815..a7a8141b6fcd 100644 --- a/executable_semantics/interpreter/type_checker.h +++ b/executable_semantics/interpreter/type_checker.h @@ -16,14 +16,15 @@ namespace Carbon { -using TypeEnv = Dictionary>; +using TypeEnv = Dictionary>; class TypeChecker { public: - explicit TypeChecker(Ptr arena) : arena(arena), interpreter(arena) {} + explicit TypeChecker(Nonnull arena) + : arena(arena), interpreter(arena) {} struct TypeCheckContext { - TypeCheckContext(Ptr arena) : types(arena), values(arena) {} + TypeCheckContext(Nonnull arena) : types(arena), values(arena) {} // Symbol table mapping names of runtime entities to their type. TypeEnv types; @@ -31,33 +32,35 @@ class TypeChecker { Env values; }; - auto MakeTypeChecked(const Ptr d, const TypeEnv& types, - const Env& values) -> Ptr; + auto MakeTypeChecked(const Nonnull d, + const TypeEnv& types, const Env& values) + -> Nonnull; - auto TopLevel(const std::vector>& fs) + auto TopLevel(const std::vector>& fs) -> TypeCheckContext; private: struct TCExpression { - TCExpression(Ptr e, Ptr t, TypeEnv types) + TCExpression(Nonnull e, Nonnull t, + TypeEnv types) : exp(e), type(t), types(types) {} - Ptr exp; - Ptr type; + Nonnull exp; + Nonnull type; TypeEnv types; }; struct TCPattern { - Ptr pattern; - Ptr type; + Nonnull pattern; + Nonnull type; TypeEnv types; }; struct TCStatement { - TCStatement(Ptr s, TypeEnv types) + TCStatement(Nonnull s, TypeEnv types) : stmt(s), types(types) {} - Ptr stmt; + Nonnull stmt; TypeEnv types; }; @@ -72,15 +75,16 @@ class TypeChecker { // types maps variable names to the type of their run-time value. // values maps variable names to their compile-time values. It is not // directly used in this function but is passed to InterExp. - auto TypeCheckExp(Ptr e, TypeEnv types, Env values) + auto TypeCheckExp(Nonnull e, TypeEnv types, Env values) -> TCExpression; // Equivalent to TypeCheckExp, but operates on Patterns instead of // Expressions. `expected` is the type that this pattern is expected to have, // if the surrounding context gives us that information. Otherwise, it is // nullopt. - auto TypeCheckPattern(Ptr p, TypeEnv types, Env values, - std::optional> expected) -> TCPattern; + auto TypeCheckPattern(Nonnull p, TypeEnv types, Env values, + std::optional> expected) + -> TCPattern; // TypeCheckStmt performs semantic analysis on a statement. It returns a new // version of the statement and a new type environment. @@ -89,36 +93,38 @@ class TypeChecker { // declared return type of the enclosing function definition. If the return // type is "auto", then the return type is inferred from the first return // statement. - auto TypeCheckStmt(Ptr s, TypeEnv types, Env values, - Ptr& ret_type, bool is_omitted_ret_type) + auto TypeCheckStmt(Nonnull s, TypeEnv types, Env values, + Nonnull& ret_type, bool is_omitted_ret_type) -> TCStatement; auto TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, Env values) - -> Ptr; + -> Nonnull; - auto TypeCheckCase(Ptr expected, Ptr pat, - Ptr body, TypeEnv types, Env values, - Ptr& ret_type, bool is_omitted_ret_type) - -> std::pair, Ptr>; + auto TypeCheckCase(Nonnull expected, + Nonnull pat, + Nonnull body, TypeEnv types, Env values, + Nonnull& ret_type, bool is_omitted_ret_type) + -> std::pair, Nonnull>; auto TypeOfFunDef(TypeEnv types, Env values, - const FunctionDefinition* fun_def) -> Ptr; + const FunctionDefinition* fun_def) -> Nonnull; auto TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, Env ct_top) - -> Ptr; + -> Nonnull; void TopLevel(const Declaration& d, TypeCheckContext* tops); - auto CheckOrEnsureReturn(std::optional> opt_stmt, + auto CheckOrEnsureReturn(std::optional> opt_stmt, bool omitted_ret_type, SourceLocation loc) - -> Ptr; + -> Nonnull; // Reify type to type expression. - auto ReifyType(Ptr t, SourceLocation loc) - -> Ptr; + auto ReifyType(Nonnull t, SourceLocation loc) + -> Nonnull; - auto Substitute(TypeEnv dict, Ptr type) -> Ptr; + auto Substitute(TypeEnv dict, Nonnull type) + -> Nonnull; - Ptr arena; + Nonnull arena; Interpreter interpreter; }; diff --git a/executable_semantics/interpreter/value.cpp b/executable_semantics/interpreter/value.cpp index 4ef89da59550..338c4f385cf4 100644 --- a/executable_semantics/interpreter/value.cpp +++ b/executable_semantics/interpreter/value.cpp @@ -18,7 +18,7 @@ namespace Carbon { using llvm::cast; auto FindInVarValues(const std::string& field, const VarValues& inits) - -> std::optional> { + -> std::optional> { for (auto& i : inits) { if (i.first == field) { return i.second; @@ -45,7 +45,7 @@ auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool { } auto TupleValue::FindField(const std::string& name) const - -> std::optional> { + -> std::optional> { for (const TupleElement& element : elements) { if (element.name == name) { return element.value; @@ -56,11 +56,12 @@ auto TupleValue::FindField(const std::string& name) const namespace { -auto GetMember(Ptr arena, Ptr v, const std::string& f, - SourceLocation loc) -> Ptr { +auto GetMember(Nonnull arena, Nonnull v, + const std::string& f, SourceLocation loc) + -> Nonnull { switch (v->Tag()) { case Value::Kind::StructValue: { - std::optional> field = + std::optional> field = cast(*cast(*v).Inits()).FindField(f); if (field == std::nullopt) { FATAL_RUNTIME_ERROR(loc) << "member " << f << " not in " << *v; @@ -68,7 +69,8 @@ auto GetMember(Ptr arena, Ptr v, const std::string& f, return *field; } case Value::Kind::TupleValue: { - std::optional> field = cast(*v).FindField(f); + std::optional> field = + cast(*v).FindField(f); if (!field) { FATAL_RUNTIME_ERROR(loc) << "field " << f << " not in " << *v; } @@ -88,9 +90,9 @@ auto GetMember(Ptr arena, Ptr v, const std::string& f, } // namespace -auto Value::GetField(Ptr arena, const FieldPath& path, - SourceLocation loc) const -> Ptr { - Ptr value(this); +auto Value::GetField(Nonnull arena, const FieldPath& path, + SourceLocation loc) const -> Nonnull { + Nonnull value(this); for (const std::string& field : path.components) { value = GetMember(arena, value, field, loc); } @@ -99,11 +101,11 @@ auto Value::GetField(Ptr arena, const FieldPath& path, namespace { -auto SetFieldImpl(Ptr arena, Ptr value, +auto SetFieldImpl(Nonnull arena, Nonnull value, std::vector::const_iterator path_begin, std::vector::const_iterator path_end, - Ptr field_value, SourceLocation loc) - -> Ptr { + Nonnull field_value, SourceLocation loc) + -> Nonnull { if (path_begin == path_end) { return field_value; } @@ -133,11 +135,12 @@ auto SetFieldImpl(Ptr arena, Ptr value, } // namespace -auto Value::SetField(Ptr arena, const FieldPath& path, - Ptr field_value, SourceLocation loc) const - -> Ptr { - return SetFieldImpl(arena, Ptr(this), path.components.begin(), - path.components.end(), field_value, loc); +auto Value::SetField(Nonnull arena, const FieldPath& path, + Nonnull field_value, + SourceLocation loc) const -> Nonnull { + return SetFieldImpl(arena, Nonnull(this), + path.components.begin(), path.components.end(), + field_value, loc); } void Value::Print(llvm::raw_ostream& out) const { @@ -237,7 +240,7 @@ void Value::Print(llvm::raw_ostream& out) const { case Value::Kind::ContinuationValue: { out << "{"; llvm::ListSeparator sep(" :: "); - for (Ptr frame : cast(*this).Stack()) { + for (Nonnull frame : cast(*this).Stack()) { out << sep << *frame; } out << "}"; @@ -254,8 +257,8 @@ void Value::Print(llvm::raw_ostream& out) const { } } -auto CopyVal(Ptr arena, Ptr val, SourceLocation loc) - -> Ptr { +auto CopyVal(Nonnull arena, Nonnull val, + SourceLocation loc) -> Nonnull { switch (val->Tag()) { case Value::Kind::TupleValue: { std::vector elements; @@ -267,12 +270,12 @@ auto CopyVal(Ptr arena, Ptr val, SourceLocation loc) } case Value::Kind::AlternativeValue: { const auto& alt = cast(*val); - Ptr arg = CopyVal(arena, alt.Argument(), loc); + Nonnull arg = CopyVal(arena, alt.Argument(), loc); return arena->New(alt.AltName(), alt.ChoiceName(), arg); } case Value::Kind::StructValue: { const auto& s = cast(*val); - Ptr inits = CopyVal(arena, s.Inits(), loc); + Nonnull inits = CopyVal(arena, s.Inits(), loc); return arena->New(s.Type(), inits); } case Value::Kind::IntValue: @@ -322,7 +325,7 @@ auto CopyVal(Ptr arena, Ptr val, SourceLocation loc) } } -auto TypeEqual(Ptr t1, Ptr t2) -> bool { +auto TypeEqual(Nonnull t1, Nonnull t2) -> bool { if (t1->Tag() != t2->Tag()) { return false; } @@ -394,8 +397,8 @@ static auto FieldsValueEqual(const std::vector& ts1, // Returns true if the two values are equal and returns false otherwise. // // This function implements the `==` operator of Carbon. -auto ValueEqual(Ptr v1, Ptr v2, SourceLocation loc) - -> bool { +auto ValueEqual(Nonnull v1, Nonnull v2, + SourceLocation loc) -> bool { if (v1->Tag() != v2->Tag()) { return false; } @@ -407,9 +410,9 @@ auto ValueEqual(Ptr v1, Ptr v2, SourceLocation loc) case Value::Kind::PointerValue: return cast(*v1).Val() == cast(*v2).Val(); case Value::Kind::FunctionValue: { - std::optional> body1 = + std::optional> body1 = cast(*v1).Body(); - std::optional> body2 = + std::optional> body2 = cast(*v2).Body(); return body1.has_value() == body2.has_value() && (!body1.has_value() || *body1 == *body2); diff --git a/executable_semantics/interpreter/value.h b/executable_semantics/interpreter/value.h index a092ef7aa3b9..4ac8c4dfc53d 100644 --- a/executable_semantics/interpreter/value.h +++ b/executable_semantics/interpreter/value.h @@ -68,14 +68,14 @@ class Value { // Returns the sub-Value specified by `path`, which must be a valid field // path for *this. - auto GetField(Ptr arena, const FieldPath& path, - SourceLocation loc) const -> Ptr; + auto GetField(Nonnull arena, const FieldPath& path, + SourceLocation loc) const -> Nonnull; // Returns a copy of *this, but with the sub-Value specified by `path` // set to `field_value`. `path` must be a valid field path for *this. - auto SetField(Ptr arena, const FieldPath& path, - Ptr field_value, SourceLocation loc) const - -> Ptr; + auto SetField(Nonnull arena, const FieldPath& path, + Nonnull field_value, SourceLocation loc) const + -> Nonnull; protected: // Constructs a Value. `tag` must be the enumerator corresponding to the @@ -86,10 +86,10 @@ class Value { const Kind tag; }; -using VarValues = std::vector>>; +using VarValues = std::vector>>; auto FindInVarValues(const std::string& field, const VarValues& inits) - -> std::optional>; + -> std::optional>; auto FieldsEqual(const VarValues& ts1, const VarValues& ts2) -> bool; // A TupleElement represents the value of a single tuple field. @@ -98,7 +98,7 @@ struct TupleElement { std::string name; // The field's value. - Ptr value; + Nonnull value; }; struct Frame; // Used by continuation. @@ -121,8 +121,8 @@ class IntValue : public Value { // A function value. class FunctionValue : public Value { public: - FunctionValue(std::string name, Ptr param, - std::optional> body) + FunctionValue(std::string name, Nonnull param, + std::optional> body) : Value(Kind::FunctionValue), name(std::move(name)), param(param), @@ -133,13 +133,13 @@ class FunctionValue : public Value { } auto Name() const -> const std::string& { return name; } - auto Param() const -> Ptr { return param; } - auto Body() const -> std::optional> { return body; } + auto Param() const -> Nonnull { return param; } + auto Body() const -> std::optional> { return body; } private: std::string name; - Ptr param; - std::optional> body; + Nonnull param; + std::optional> body; }; // A pointer value. @@ -176,19 +176,19 @@ class BoolValue : public Value { // A function value. class StructValue : public Value { public: - StructValue(Ptr type, Ptr inits) + StructValue(Nonnull type, Nonnull inits) : Value(Kind::StructValue), type(type), inits(inits) {} static auto classof(const Value* value) -> bool { return value->Tag() == Kind::StructValue; } - auto Type() const -> Ptr { return type; } - auto Inits() const -> Ptr { return inits; } + auto Type() const -> Nonnull { return type; } + auto Inits() const -> Nonnull { return inits; } private: - Ptr type; - Ptr inits; + Nonnull type; + Nonnull inits; }; // An alternative constructor value. @@ -215,7 +215,7 @@ class AlternativeConstructorValue : public Value { class AlternativeValue : public Value { public: AlternativeValue(std::string alt_name, std::string choice_name, - Ptr argument) + Nonnull argument) : Value(Kind::AlternativeValue), alt_name(std::move(alt_name)), choice_name(std::move(choice_name)), @@ -227,21 +227,21 @@ class AlternativeValue : public Value { auto AltName() const -> const std::string& { return alt_name; } auto ChoiceName() const -> const std::string& { return choice_name; } - auto Argument() const -> Ptr { return argument; } + auto Argument() const -> Nonnull { return argument; } private: std::string alt_name; std::string choice_name; - Ptr argument; + Nonnull argument; }; // A function value. class TupleValue : public Value { public: // An empty tuple, also known as the unit type. - static Ptr Empty() { + static Nonnull Empty() { static const TupleValue empty = TupleValue(std::vector()); - return Ptr(&empty); + return Nonnull(&empty); } explicit TupleValue(std::vector elements) @@ -256,7 +256,7 @@ class TupleValue : public Value { // Returns the value of the field named `name` in this tuple, or // nullopt if there is no such field. auto FindField(const std::string& name) const - -> std::optional>; + -> std::optional>; private: std::vector elements; @@ -267,7 +267,7 @@ class BindingPlaceholderValue : public Value { public: // nullopt represents the `_` placeholder. BindingPlaceholderValue(std::optional name, - Ptr type) + Nonnull type) : Value(Kind::BindingPlaceholderValue), name(std::move(name)), type(type) {} @@ -277,11 +277,11 @@ class BindingPlaceholderValue : public Value { } auto Name() const -> const std::optional& { return name; } - auto Type() const -> Ptr { return type; } + auto Type() const -> Nonnull { return type; } private: std::optional name; - Ptr type; + Nonnull type; }; // The int type. @@ -317,8 +317,8 @@ class TypeType : public Value { // A function type. class FunctionType : public Value { public: - FunctionType(std::vector deduced, Ptr param, - Ptr ret) + FunctionType(std::vector deduced, Nonnull param, + Nonnull ret) : Value(Kind::FunctionType), deduced(std::move(deduced)), param(param), @@ -329,29 +329,29 @@ class FunctionType : public Value { } auto Deduced() const -> const std::vector& { return deduced; } - auto Param() const -> Ptr { return param; } - auto Ret() const -> Ptr { return ret; } + auto Param() const -> Nonnull { return param; } + auto Ret() const -> Nonnull { return ret; } private: std::vector deduced; - Ptr param; - Ptr ret; + Nonnull param; + Nonnull ret; }; // A pointer type. class PointerType : public Value { public: - explicit PointerType(Ptr type) + explicit PointerType(Nonnull type) : Value(Kind::PointerType), type(type) {} static auto classof(const Value* value) -> bool { return value->Tag() == Kind::PointerType; } - auto Type() const -> Ptr { return type; } + auto Type() const -> Nonnull { return type; } private: - Ptr type; + Nonnull type; }; // The `auto` type. @@ -436,17 +436,17 @@ class VariableType : public Value { // A first-class continuation representation of a fragment of the stack. class ContinuationValue : public Value { public: - explicit ContinuationValue(std::vector> stack) + explicit ContinuationValue(std::vector> stack) : Value(Kind::ContinuationValue), stack(std::move(stack)) {} static auto classof(const Value* value) -> bool { return value->Tag() == Kind::ContinuationValue; } - auto Stack() const -> const std::vector>& { return stack; } + auto Stack() const -> const std::vector>& { return stack; } private: - std::vector> stack; + std::vector> stack; }; // The String type. @@ -475,12 +475,12 @@ class StringValue : public Value { std::string val; }; -auto CopyVal(Ptr arena, Ptr val, SourceLocation loc) - -> Ptr; +auto CopyVal(Nonnull arena, Nonnull val, + SourceLocation loc) -> Nonnull; -auto TypeEqual(Ptr t1, Ptr t2) -> bool; -auto ValueEqual(Ptr v1, Ptr v2, SourceLocation loc) - -> bool; +auto TypeEqual(Nonnull t1, Nonnull t2) -> bool; +auto ValueEqual(Nonnull v1, Nonnull v2, + SourceLocation loc) -> bool; } // namespace Carbon diff --git a/executable_semantics/syntax/parse.cpp b/executable_semantics/syntax/parse.cpp index 39f34f8fe71d..bc53ab819e4d 100644 --- a/executable_semantics/syntax/parse.cpp +++ b/executable_semantics/syntax/parse.cpp @@ -13,7 +13,7 @@ namespace Carbon { -auto Parse(Ptr arena, const std::string& input_file_name) +auto Parse(Nonnull arena, const std::string& input_file_name) -> std::variant { FILE* input_file = fopen(input_file_name.c_str(), "r"); if (input_file == nullptr) { diff --git a/executable_semantics/syntax/parse.h b/executable_semantics/syntax/parse.h index cadef2b460f2..2e4ebc27226d 100644 --- a/executable_semantics/syntax/parse.h +++ b/executable_semantics/syntax/parse.h @@ -18,7 +18,7 @@ using SyntaxErrorCode = int; // Returns the AST representing the contents of the named file, or an error code // if parsing fails. Allocations go into the provided arena. -auto Parse(Ptr arena, const std::string& input_file_name) +auto Parse(Nonnull arena, const std::string& input_file_name) -> std::variant; } // namespace Carbon diff --git a/executable_semantics/syntax/parse_and_lex_context.h b/executable_semantics/syntax/parse_and_lex_context.h index 4e67e7127215..5a7295b21356 100644 --- a/executable_semantics/syntax/parse_and_lex_context.h +++ b/executable_semantics/syntax/parse_and_lex_context.h @@ -17,7 +17,7 @@ namespace Carbon { class ParseAndLexContext { public: // Creates an instance analyzing the given input file. - ParseAndLexContext(Ptr input_file_name) + ParseAndLexContext(Nonnull input_file_name) : input_file_name(input_file_name) {} // Writes a syntax error diagnostic containing message to standard error. @@ -34,15 +34,15 @@ class ParseAndLexContext { private: // A path to the file processed, relative to the current working directory // when *this is called. - Ptr input_file_name; + Nonnull input_file_name; }; } // namespace Carbon // Gives flex the yylex prototype we want. -#define YY_DECL \ - Carbon::Parser::symbol_type yylex(Carbon::Ptr arena, \ - yyscan_t yyscanner, \ +#define YY_DECL \ + Carbon::Parser::symbol_type yylex(Carbon::Nonnull arena, \ + yyscan_t yyscanner, \ Carbon::ParseAndLexContext& context) // Declares yylex for the parser's sake. diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 1b4f5c409b4a..bce5c9de1b51 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -38,7 +38,7 @@ // thus available to its methods. // "inout" parameters passed to both the parser and the lexer. -%param {Ptr arena} +%param {Nonnull arena} %param {yyscan_t yyscanner} %param {ParseAndLexContext& context} @@ -98,43 +98,43 @@ %type > import_directives %type optional_library_path %type api_or_impl -%type >> declaration -%type >> function_declaration -%type >> function_definition -%type >> declaration_list -%type >> statement -%type >> if_statement -%type >> optional_else -%type , bool>>> return_expression -%type >> block -%type >> statement_list -%type >> expression +%type >> declaration +%type >> function_declaration +%type >> function_definition +%type >> declaration_list +%type >> statement +%type >> if_statement +%type >> optional_else +%type , bool>>> return_expression +%type >> block +%type >> statement_list +%type >> expression %type > generic_binding %type > deduced_params %type > deduced_param_list -%type >> pattern -%type >> non_expression_pattern -%type , bool>>> return_type -%type >> paren_expression -%type >> tuple +%type >> pattern +%type >> non_expression_pattern +%type , bool>>> return_type +%type >> paren_expression +%type >> tuple %type > binding_lhs -%type >> variable_declaration -%type >> member -%type >> member_list +%type >> variable_declaration +%type >> member +%type >> member_list %type ::Element>> paren_expression_element %type > paren_expression_base %type > paren_expression_contents -%type >> paren_pattern -%type >> tuple_pattern -%type >> maybe_empty_tuple_pattern +%type >> paren_pattern +%type >> tuple_pattern +%type >> maybe_empty_tuple_pattern %type > paren_pattern_base %type ::Element>> paren_pattern_element %type > paren_pattern_contents -%type >>> alternative -%type >>> alternative_list -%type >>> alternative_list_contents -%type , Ptr>>> clause -%type , Ptr>>> clause_list +%type >>> alternative +%type >>> alternative_list +%type >>> alternative_list_contents +%type , Nonnull>>> clause +%type , Nonnull>>> clause_list %token // Most tokens have their spelling defined in lexer.lpp. @@ -303,61 +303,61 @@ expression: { $$ = arena->New( context.SourceLoc(), Operator::Eq, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | expression PLUS expression { $$ = arena->New( context.SourceLoc(), Operator::Add, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | expression MINUS expression { $$ = arena->New( context.SourceLoc(), Operator::Sub, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | expression BINARY_STAR expression { $$ = arena->New( context.SourceLoc(), Operator::Mul, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | expression AND expression { $$ = arena->New( context.SourceLoc(), Operator::And, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | expression OR expression { $$ = arena->New( context.SourceLoc(), Operator::Or, - std::vector>({$1, $3})); + std::vector>({$1, $3})); } | NOT expression { $$ = arena->New( context.SourceLoc(), Operator::Not, - std::vector>({$2})); + std::vector>({$2})); } | MINUS expression %prec UNARY_MINUS { $$ = arena->New( context.SourceLoc(), Operator::Neg, - std::vector>({$2})); + std::vector>({$2})); } | PREFIX_STAR expression { $$ = arena->New( context.SourceLoc(), Operator::Deref, - std::vector>({$2})); + std::vector>({$2})); } | UNARY_STAR expression %prec PREFIX_STAR { $$ = arena->New( context.SourceLoc(), Operator::Deref, - std::vector>({$2})); + std::vector>({$2})); } | expression tuple { $$ = arena->New(context.SourceLoc(), $1, $2); } @@ -365,13 +365,13 @@ expression: { $$ = arena->New( context.SourceLoc(), Operator::Ptr, - std::vector>({$1})); + std::vector>({$1})); } | expression UNARY_STAR { $$ = arena->New( context.SourceLoc(), Operator::Ptr, - std::vector>({$1})); + std::vector>({$1})); } | FNTY tuple return_type { @@ -502,13 +502,17 @@ maybe_empty_tuple_pattern: ; clause: CASE pattern DOUBLE_ARROW statement - { $$ = std::pair, Ptr>($2, $4); } + { + $$ = + std::pair, Nonnull>($2, $4); + } | DEFAULT DOUBLE_ARROW statement { auto vp = arena -> New( context.SourceLoc(), std::nullopt, arena->New(context.SourceLoc())); - $$ = std::pair, Ptr>(vp, $3); + $$ = + std::pair, Nonnull>(vp, $3); } ; clause_list: @@ -656,10 +660,10 @@ member_list: ; alternative: identifier tuple - { $$ = std::pair>($1, $2); } + { $$ = std::pair>($1, $2); } | identifier { - $$ = std::pair>( + $$ = std::pair>( $1, arena->New(context.SourceLoc())); } ; @@ -698,7 +702,7 @@ declaration_list: | declaration_list declaration { $$ = $1; - $$.push_back(Ptr($2)); + $$.push_back(Nonnull($2)); } ; %%