From 04ab30f23105205e9049bd09d7a6567c4975a614 Mon Sep 17 00:00:00 2001 From: Jon Meow <46229924+jonmeow@users.noreply.github.com> Date: Mon, 27 Sep 2021 10:57:31 -0700 Subject: [PATCH] Make the AST mutable (#849) The code is pretty intertwined: having the AST be truly mutable means (to me) changing parser.ypp to return non-const values, but then the way things are passed around between objects should be non-const (particularly an issue with lists), which then creates issues with construction of lists in the TypeChecker, which then TypeChecker needs to mostly be non-const. Due to the difficulties in breaking this apart, whereas I'd previously considering refactoring accessor naming in the same PR, I've largely avoided doing so. The intent is then that this PR focuses mainly on const -> non-const AST behavior. call_main moves out of interpreter.cpp so that interpreter.cpp can receive a fully const AST. --- executable_semantics/ast/ast.h | 2 +- executable_semantics/ast/declaration.h | 22 +-- executable_semantics/ast/expression.cpp | 9 +- executable_semantics/ast/expression.h | 57 ++++---- .../ast/function_definition.h | 17 +-- executable_semantics/ast/paren_contents.h | 9 +- executable_semantics/ast/pattern.cpp | 17 ++- executable_semantics/ast/pattern.h | 38 ++--- executable_semantics/ast/statement.h | 96 +++++++------ .../interpreter/exec_program.cpp | 14 +- .../interpreter/interpreter.cpp | 8 +- .../interpreter/interpreter.h | 3 +- .../interpreter/type_checker.cpp | 133 +++++++++--------- .../interpreter/type_checker.h | 49 +++---- executable_semantics/syntax/parser.ypp | 78 +++++----- 15 files changed, 282 insertions(+), 270 deletions(-) diff --git a/executable_semantics/ast/ast.h b/executable_semantics/ast/ast.h index ab599b2eb43f..7d761e046368 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/declaration.h b/executable_semantics/ast/declaration.h index 9290b708ba9f..2c3a0d7451e7 100644 --- a/executable_semantics/ast/declaration.h +++ b/executable_semantics/ast/declaration.h @@ -15,6 +15,7 @@ #include "executable_semantics/ast/pattern.h" #include "executable_semantics/ast/source_location.h" #include "executable_semantics/common/nonnull.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" namespace Carbon { @@ -60,7 +61,7 @@ class Declaration { class FunctionDeclaration : public Declaration { public: - FunctionDeclaration(Nonnull definition) + FunctionDeclaration(Nonnull definition) : Declaration(Kind::FunctionDeclaration, definition->source_loc()), definition(definition) {} @@ -69,9 +70,10 @@ class FunctionDeclaration : public Declaration { } auto Definition() const -> const FunctionDefinition& { return *definition; } + auto Definition() -> FunctionDefinition& { return *definition; } private: - Nonnull definition; + Nonnull definition; }; class ClassDeclaration : public Declaration { @@ -88,6 +90,7 @@ class ClassDeclaration : public Declaration { } auto Definition() const -> const ClassDefinition& { return definition; } + auto Definition() -> ClassDefinition& { return definition; } private: ClassDefinition definition; @@ -97,7 +100,7 @@ class ChoiceDeclaration : public Declaration { public: class Alternative { public: - Alternative(std::string name, Nonnull signature) + Alternative(std::string name, Nonnull signature) : name_(name), signature_(signature) {} auto name() const -> const std::string& { return name_; } @@ -105,7 +108,7 @@ class ChoiceDeclaration : public Declaration { private: std::string name_; - Nonnull signature_; + Nonnull signature_; }; ChoiceDeclaration(SourceLocation loc, std::string name, @@ -131,9 +134,8 @@ class ChoiceDeclaration : public Declaration { // Global variable definition implements the Declaration concept. class VariableDeclaration : public Declaration { public: - VariableDeclaration(SourceLocation loc, - Nonnull binding, - Nonnull initializer) + VariableDeclaration(SourceLocation loc, Nonnull binding, + Nonnull initializer) : Declaration(Kind::VariableDeclaration, loc), binding(binding), initializer(initializer) {} @@ -143,14 +145,16 @@ class VariableDeclaration : public Declaration { } auto Binding() const -> Nonnull { return binding; } + auto Binding() -> Nonnull { return binding; } auto Initializer() const -> Nonnull { return initializer; } + auto Initializer() -> 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. - Nonnull binding; - Nonnull initializer; + Nonnull binding; + Nonnull initializer; }; } // namespace Carbon diff --git a/executable_semantics/ast/expression.cpp b/executable_semantics/ast/expression.cpp index 39490d9d4a48..2d2d57837d18 100644 --- a/executable_semantics/ast/expression.cpp +++ b/executable_semantics/ast/expression.cpp @@ -18,10 +18,8 @@ using llvm::cast; auto ExpressionFromParenContents( Nonnull arena, SourceLocation loc, - const ParenContents& paren_contents) - -> Nonnull { - std::optional> single_term = - paren_contents.SingleTerm(); + const ParenContents& paren_contents) -> Nonnull { + std::optional> single_term = paren_contents.SingleTerm(); if (single_term.has_value()) { return *single_term; } else { @@ -31,8 +29,7 @@ auto ExpressionFromParenContents( auto TupleExpressionFromParenContents( Nonnull arena, SourceLocation loc, - const ParenContents& paren_contents) - -> Nonnull { + 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 76582d2418f5..701c18b94745 100644 --- a/executable_semantics/ast/expression.h +++ b/executable_semantics/ast/expression.h @@ -14,6 +14,7 @@ #include "executable_semantics/ast/paren_contents.h" #include "executable_semantics/ast/source_location.h" #include "executable_semantics/common/arena.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" namespace Carbon { @@ -64,26 +65,24 @@ class Expression { // tuple otherwise. auto ExpressionFromParenContents( Nonnull arena, SourceLocation loc, - const ParenContents& paren_contents) - -> Nonnull; + const ParenContents& paren_contents) -> Nonnull; // Converts paren_contents to an Expression, interpreting the parentheses as // forming a tuple. auto TupleExpressionFromParenContents( Nonnull arena, SourceLocation loc, - const ParenContents& paren_contents) - -> Nonnull; + const ParenContents& paren_contents) -> Nonnull; // A FieldInitializer represents the initialization of a single tuple field. struct FieldInitializer { - FieldInitializer(std::string name, Nonnull 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. - Nonnull expression; + Nonnull expression; }; enum class Operator { @@ -117,7 +116,7 @@ class IdentifierExpression : public Expression { class FieldAccessExpression : public Expression { public: explicit FieldAccessExpression(SourceLocation loc, - Nonnull aggregate, + Nonnull aggregate, std::string field) : Expression(Kind::FieldAccessExpression, loc), aggregate(aggregate), @@ -128,18 +127,18 @@ class FieldAccessExpression : public Expression { } auto Aggregate() const -> Nonnull { return aggregate; } + auto Aggregate() -> Nonnull { return aggregate; } auto Field() const -> const std::string& { return field; } private: - Nonnull aggregate; + Nonnull aggregate; std::string field; }; class IndexExpression : public Expression { public: - explicit IndexExpression(SourceLocation loc, - Nonnull aggregate, - Nonnull offset) + explicit IndexExpression(SourceLocation loc, Nonnull aggregate, + Nonnull offset) : Expression(Kind::IndexExpression, loc), aggregate(aggregate), offset(offset) {} @@ -149,11 +148,13 @@ class IndexExpression : public Expression { } auto Aggregate() const -> Nonnull { return aggregate; } + auto Aggregate() -> Nonnull { return aggregate; } auto Offset() const -> Nonnull { return offset; } + auto Offset() -> Nonnull { return offset; } private: - Nonnull aggregate; - Nonnull offset; + Nonnull aggregate; + Nonnull offset; }; class IntLiteral : public Expression { @@ -233,7 +234,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)) {} @@ -243,20 +244,22 @@ class PrimitiveOperatorExpression : public Expression { } auto Op() const -> Operator { return op; } - auto Arguments() const -> const std::vector>& { + auto Arguments() const -> llvm::ArrayRef> { + return arguments; + } + auto Arguments() -> llvm::MutableArrayRef> { return arguments; } private: Operator op; - std::vector> arguments; + std::vector> arguments; }; class CallExpression : public Expression { public: - explicit CallExpression(SourceLocation loc, - Nonnull function, - Nonnull argument) + explicit CallExpression(SourceLocation loc, Nonnull function, + Nonnull argument) : Expression(Kind::CallExpression, loc), function(function), argument(argument) {} @@ -266,18 +269,20 @@ class CallExpression : public Expression { } auto Function() const -> Nonnull { return function; } + auto Function() -> Nonnull { return function; } auto Argument() const -> Nonnull { return argument; } + auto Argument() -> Nonnull { return argument; } private: - Nonnull function; - Nonnull argument; + Nonnull function; + Nonnull argument; }; class FunctionTypeLiteral : public Expression { public: explicit FunctionTypeLiteral(SourceLocation loc, - Nonnull parameter, - Nonnull return_type, + Nonnull parameter, + Nonnull return_type, bool is_omitted_return_type) : Expression(Kind::FunctionTypeLiteral, loc), parameter(parameter), @@ -289,12 +294,14 @@ class FunctionTypeLiteral : public Expression { } auto Parameter() const -> Nonnull { return parameter; } + auto Parameter() -> Nonnull { return parameter; } auto ReturnType() const -> Nonnull { return return_type; } + auto ReturnType() -> Nonnull { return return_type; } auto IsOmittedReturnType() const -> bool { return is_omitted_return_type; } private: - Nonnull parameter; - Nonnull return_type; + Nonnull parameter; + Nonnull return_type; bool is_omitted_return_type; }; diff --git a/executable_semantics/ast/function_definition.h b/executable_semantics/ast/function_definition.h index 00de202e27ff..cd57588c16ec 100644 --- a/executable_semantics/ast/function_definition.h +++ b/executable_semantics/ast/function_definition.h @@ -26,13 +26,12 @@ class FunctionDefinition { public: FunctionDefinition(SourceLocation source_loc, std::string name, std::vector deduced_params, - Nonnull param_pattern, - Nonnull return_type, - bool is_omitted_return_type, - std::optional> body) + Nonnull param_pattern, + Nonnull return_type, bool is_omitted_return_type, + std::optional> body) : source_loc_(source_loc), name_(std::move(name)), - deduced_parameters_(deduced_params), + deduced_parameters_(std::move(deduced_params)), param_pattern_(param_pattern), return_type_(return_type), is_omitted_return_type_(is_omitted_return_type), @@ -48,6 +47,7 @@ class FunctionDefinition { return deduced_parameters_; } auto param_pattern() const -> const TuplePattern& { return *param_pattern_; } + auto param_pattern() -> TuplePattern& { return *param_pattern_; } auto return_type() const -> const Pattern& { return *return_type_; } auto is_omitted_return_type() const -> bool { return is_omitted_return_type_; @@ -55,15 +55,16 @@ class FunctionDefinition { auto body() const -> std::optional> { return body_; } + auto body() -> std::optional> { return body_; } private: SourceLocation source_loc_; std::string name_; std::vector deduced_parameters_; - Nonnull param_pattern_; - Nonnull 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/paren_contents.h b/executable_semantics/ast/paren_contents.h index df2888cd1bb2..2a5e64eef4a0 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; - Nonnull 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 Nonnull. + // have a constructor that takes a std::string and a Nonnull. // // TODO: Find a way to deduce TupleElement from Term. template @@ -50,8 +50,7 @@ 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 2f6a5b7a547c..455915ffc803 100644 --- a/executable_semantics/ast/pattern.cpp +++ b/executable_semantics/ast/pattern.cpp @@ -55,7 +55,7 @@ void Pattern::Print(llvm::raw_ostream& out) const { } TuplePattern::TuplePattern(Nonnull arena, - Nonnull tuple_literal) + Nonnull tuple_literal) : Pattern(Kind::TuplePattern, tuple_literal->SourceLoc()) { const auto& tuple = cast(*tuple_literal); for (const FieldInitializer& init : tuple.Fields()) { @@ -66,9 +66,8 @@ TuplePattern::TuplePattern(Nonnull arena, auto PatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Nonnull { - std::optional> single_term = - paren_contents.SingleTerm(); + -> Nonnull { + std::optional> single_term = paren_contents.SingleTerm(); if (single_term.has_value()) { return *single_term; } else { @@ -78,7 +77,7 @@ auto PatternFromParenContents(Nonnull arena, SourceLocation loc, auto TuplePatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Nonnull { + -> Nonnull { return arena->New( loc, paren_contents.TupleElements(loc)); } @@ -86,8 +85,8 @@ auto TuplePatternFromParenContents(Nonnull arena, SourceLocation loc, // Used by AlternativePattern for constructor initialization. Produces a helpful // error for incorrect expressions, rather than letting a default cast error // apply. -static const FieldAccessExpression& RequireFieldAccess( - Nonnull alternative) { +static auto RequireFieldAccess(Nonnull alternative) + -> FieldAccessExpression& { if (alternative->Tag() != Expression::Kind::FieldAccessExpression) { FATAL_PROGRAM_ERROR(alternative->SourceLoc()) << "Alternative pattern must have the form of a field access."; @@ -96,8 +95,8 @@ static const FieldAccessExpression& RequireFieldAccess( } AlternativePattern::AlternativePattern(SourceLocation loc, - Nonnull alternative, - Nonnull arguments) + Nonnull alternative, + Nonnull arguments) : Pattern(Kind::AlternativePattern, loc), choice_type(RequireFieldAccess(alternative).Aggregate()), alternative_name(RequireFieldAccess(alternative).Field()), diff --git a/executable_semantics/ast/pattern.h b/executable_semantics/ast/pattern.h index f895ef00244d..1bb702890d96 100644 --- a/executable_semantics/ast/pattern.h +++ b/executable_semantics/ast/pattern.h @@ -12,6 +12,7 @@ #include "common/ostream.h" #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/source_location.h" +#include "llvm/ADT/ArrayRef.h" namespace Carbon { @@ -71,7 +72,7 @@ class AutoPattern : public Pattern { class BindingPattern : public Pattern { public: BindingPattern(SourceLocation loc, std::optional name, - Nonnull type) + Nonnull type) : Pattern(Kind::BindingPattern, loc), name(std::move(name)), type(type) {} static auto classof(const Pattern* pattern) -> bool { @@ -83,10 +84,11 @@ class BindingPattern : public Pattern { // The pattern specifying the type of values that this pattern matches. auto Type() const -> Nonnull { return type; } + auto Type() -> Nonnull { return type; } private: std::optional name; - Nonnull type; + Nonnull type; }; // A pattern that matches a tuple value field-wise. @@ -94,14 +96,14 @@ class TuplePattern : public Pattern { public: // Represents a portion of a tuple pattern corresponding to a single field. struct Field { - Field(std::string name, Nonnull 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. - Nonnull pattern; + Nonnull pattern; }; TuplePattern(SourceLocation loc, std::vector fields) @@ -111,13 +113,14 @@ class TuplePattern : public Pattern { // ExpressionPattern. // // REQUIRES: tuple_literal->Tag() == Expression::Kind::TupleLiteral - TuplePattern(Nonnull arena, Nonnull tuple_literal); + TuplePattern(Nonnull arena, Nonnull tuple_literal); static auto classof(const Pattern* pattern) -> bool { return pattern->Tag() == Kind::TuplePattern; } - auto Fields() const -> const std::vector& { return fields; } + auto Fields() const -> llvm::ArrayRef { return fields; } + auto Fields() -> llvm::MutableArrayRef { return fields; } private: std::vector fields; @@ -128,13 +131,13 @@ class TuplePattern : public Pattern { // tuple otherwise. auto PatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Nonnull; + -> Nonnull; // Converts paren_contents to a TuplePattern, interpreting the parentheses as // forming a tuple. auto TuplePatternFromParenContents(Nonnull arena, SourceLocation loc, const ParenContents& paren_contents) - -> Nonnull; + -> Nonnull; // Converts `contents` to ParenContents by replacing each Expression // with an ExpressionPattern. @@ -148,9 +151,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, Nonnull choice_type, + AlternativePattern(SourceLocation loc, Nonnull choice_type, std::string alternative_name, - Nonnull arguments) + Nonnull arguments) : Pattern(Kind::AlternativePattern, loc), choice_type(choice_type), alternative_name(std::move(alternative_name)), @@ -158,30 +161,32 @@ class AlternativePattern : public Pattern { // Constructs an AlternativePattern that matches the alternative specified // by `alternative`, if its arguments match `arguments`. - AlternativePattern(SourceLocation loc, Nonnull alternative, - Nonnull arguments); + AlternativePattern(SourceLocation loc, Nonnull alternative, + Nonnull arguments); static auto classof(const Pattern* pattern) -> bool { return pattern->Tag() == Kind::AlternativePattern; } auto ChoiceType() const -> Nonnull { return choice_type; } + auto ChoiceType() -> Nonnull { return choice_type; } auto AlternativeName() const -> const std::string& { return alternative_name; } auto Arguments() const -> Nonnull { return arguments; } + auto Arguments() -> Nonnull { return arguments; } private: - Nonnull choice_type; + Nonnull choice_type; std::string alternative_name; - Nonnull 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(Nonnull expression) + ExpressionPattern(Nonnull expression) : Pattern(Kind::ExpressionPattern, expression->SourceLoc()), expression(expression) {} @@ -190,9 +195,10 @@ class ExpressionPattern : public Pattern { } auto Expression() const -> Nonnull { return expression; } + auto Expression() -> Nonnull { return expression; } private: - Nonnull expression; + Nonnull expression; }; } // namespace Carbon diff --git a/executable_semantics/ast/statement.h b/executable_semantics/ast/statement.h index af5980432255..2544d7a3ce2f 100644 --- a/executable_semantics/ast/statement.h +++ b/executable_semantics/ast/statement.h @@ -12,6 +12,7 @@ #include "executable_semantics/ast/pattern.h" #include "executable_semantics/ast/source_location.h" #include "executable_semantics/common/arena.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" namespace Carbon { @@ -58,7 +59,7 @@ class Statement { class ExpressionStatement : public Statement { public: - ExpressionStatement(SourceLocation loc, Nonnull exp) + ExpressionStatement(SourceLocation loc, Nonnull exp) : Statement(Kind::ExpressionStatement, loc), exp(exp) {} static auto classof(const Statement* stmt) -> bool { @@ -66,15 +67,15 @@ class ExpressionStatement : public Statement { } auto Exp() const -> Nonnull { return exp; } + auto Exp() -> Nonnull { return exp; } private: - Nonnull exp; + Nonnull exp; }; class Assign : public Statement { public: - Assign(SourceLocation loc, Nonnull lhs, - Nonnull rhs) + Assign(SourceLocation loc, Nonnull lhs, Nonnull rhs) : Statement(Kind::Assign, loc), lhs(lhs), rhs(rhs) {} static auto classof(const Statement* stmt) -> bool { @@ -82,17 +83,19 @@ class Assign : public Statement { } auto Lhs() const -> Nonnull { return lhs; } + auto Lhs() -> Nonnull { return lhs; } auto Rhs() const -> Nonnull { return rhs; } + auto Rhs() -> Nonnull { return rhs; } private: - Nonnull lhs; - Nonnull rhs; + Nonnull lhs; + Nonnull rhs; }; class VariableDefinition : public Statement { public: - VariableDefinition(SourceLocation loc, Nonnull pat, - Nonnull init) + VariableDefinition(SourceLocation loc, Nonnull pat, + Nonnull init) : Statement(Kind::VariableDefinition, loc), pat(pat), init(init) {} static auto classof(const Statement* stmt) -> bool { @@ -100,18 +103,20 @@ class VariableDefinition : public Statement { } auto Pat() const -> Nonnull { return pat; } + auto Pat() -> Nonnull { return pat; } auto Init() const -> Nonnull { return init; } + auto Init() -> Nonnull { return init; } private: - Nonnull pat; - Nonnull init; + Nonnull pat; + Nonnull init; }; class If : public Statement { public: - If(SourceLocation loc, Nonnull cond, - Nonnull 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), @@ -122,23 +127,25 @@ class If : public Statement { } auto Cond() const -> Nonnull { return cond; } + auto Cond() -> Nonnull { return cond; } auto ThenStmt() const -> Nonnull { return then_stmt; } + auto ThenStmt() -> Nonnull { return then_stmt; } auto ElseStmt() const -> std::optional> { return else_stmt; } + auto ElseStmt() -> std::optional> { return else_stmt; } private: - Nonnull cond; - Nonnull then_stmt; - std::optional> else_stmt; + Nonnull cond; + Nonnull then_stmt; + std::optional> else_stmt; }; class Return : public Statement { public: Return(Nonnull arena, SourceLocation loc) : Return(loc, arena->New(loc), true) {} - Return(SourceLocation loc, Nonnull 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) {} @@ -148,17 +155,18 @@ class Return : public Statement { } auto Exp() const -> Nonnull { return exp; } + auto Exp() -> Nonnull { return exp; } auto IsOmittedExp() const -> bool { return is_omitted_exp; } private: - Nonnull exp; + Nonnull exp; bool is_omitted_exp; }; class Sequence : public Statement { public: - Sequence(SourceLocation loc, Nonnull 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 { @@ -166,16 +174,18 @@ class Sequence : public Statement { } auto Stmt() const -> Nonnull { return stmt; } + auto Stmt() -> Nonnull { return stmt; } auto Next() const -> std::optional> { return next; } + auto Next() -> std::optional> { return next; } private: - Nonnull 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 { @@ -183,15 +193,15 @@ class Block : public Statement { } auto Stmt() const -> std::optional> { return stmt; } + auto Stmt() -> std::optional> { return stmt; } private: - std::optional> stmt; + std::optional> stmt; }; class While : public Statement { public: - While(SourceLocation loc, Nonnull cond, - Nonnull body) + While(SourceLocation loc, Nonnull cond, Nonnull body) : Statement(Kind::While, loc), cond(cond), body(body) {} static auto classof(const Statement* stmt) -> bool { @@ -199,11 +209,13 @@ class While : public Statement { } auto Cond() const -> Nonnull { return cond; } + auto Cond() -> Nonnull { return cond; } auto Body() const -> Nonnull { return body; } + auto Body() -> Nonnull { return body; } private: - Nonnull cond; - Nonnull body; + Nonnull cond; + Nonnull body; }; class Break : public Statement { @@ -226,10 +238,8 @@ class Continue : public Statement { class Match : public Statement { public: - Match( - SourceLocation loc, Nonnull exp, - std::vector, Nonnull>> - clauses) + Match(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 { @@ -237,15 +247,15 @@ class Match : public Statement { } auto Exp() const -> Nonnull { return exp; } - auto Clauses() const -> const std::vector< - std::pair, Nonnull>>& { + auto Exp() -> Nonnull { return exp; } + auto Clauses() const + -> llvm::ArrayRef, Nonnull>> { return clauses; } private: - Nonnull exp; - std::vector, Nonnull>> - clauses; + Nonnull exp; + std::vector, Nonnull>> clauses; }; // A continuation statement. @@ -256,7 +266,7 @@ class Match : public Statement { class Continuation : public Statement { public: Continuation(SourceLocation loc, std::string continuation_variable, - Nonnull body) + Nonnull body) : Statement(Kind::Continuation, loc), continuation_variable(std::move(continuation_variable)), body(body) {} @@ -269,10 +279,11 @@ class Continuation : public Statement { return continuation_variable; } auto Body() const -> Nonnull { return body; } + auto Body() -> Nonnull { return body; } private: std::string continuation_variable; - Nonnull body; + Nonnull body; }; // A run statement. @@ -280,7 +291,7 @@ class Continuation : public Statement { // __run ; class Run : public Statement { public: - Run(SourceLocation loc, Nonnull argument) + Run(SourceLocation loc, Nonnull argument) : Statement(Kind::Run, loc), argument(argument) {} static auto classof(const Statement* stmt) -> bool { @@ -288,9 +299,10 @@ class Run : public Statement { } auto Argument() const -> Nonnull { return argument; } + auto Argument() -> Nonnull { return argument; } private: - Nonnull argument; + Nonnull argument; }; // An await statement. diff --git a/executable_semantics/interpreter/exec_program.cpp b/executable_semantics/interpreter/exec_program.cpp index 1c03d62fc361..86d8fb9bf166 100644 --- a/executable_semantics/interpreter/exec_program.cpp +++ b/executable_semantics/interpreter/exec_program.cpp @@ -15,9 +15,8 @@ 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( - Nonnull arena, - std::vector>* declarations) { +static void AddIntrinsics(Nonnull arena, + std::vector>* declarations) { SourceLocation loc("", 0); std::vector print_fields = {TuplePattern::Field( "0", @@ -47,7 +46,7 @@ void ExecProgram(Nonnull arena, AST ast) { llvm::outs() << "********** type checking **********\n"; } TypeChecker type_checker(arena); - TypeChecker::TypeCheckContext p = type_checker.TopLevel(ast.declarations); + TypeChecker::TypeCheckContext p = type_checker.TopLevel(&ast.declarations); TypeEnv top = p.types; Env ct_top = p.values; std::vector> new_decls; @@ -62,7 +61,12 @@ void ExecProgram(Nonnull arena, AST ast) { } llvm::outs() << "********** starting execution **********\n"; } - int result = Interpreter(arena).InterpProgram(new_decls); + + SourceLocation loc("", 0); + Nonnull call_main = arena->New( + loc, arena->New(loc, "main"), + arena->New(loc)); + int result = Interpreter(arena).InterpProgram(new_decls, call_main); llvm::outs() << "result: " << result << "\n"; } diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 7ffca6716c4d..e12b83394497 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -1133,7 +1133,8 @@ void Interpreter::Step() { } auto Interpreter::InterpProgram( - const std::vector>& fs) -> int { + const std::vector>& fs, + Nonnull call_main) -> int { // Check that the interpreter is in a clean state. CHECK(globals.IsEmpty()); CHECK(stack.IsEmpty()); @@ -1144,11 +1145,6 @@ auto Interpreter::InterpProgram( } InitGlobals(fs); - SourceLocation loc("", 0); - - 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)); diff --git a/executable_semantics/interpreter/interpreter.h b/executable_semantics/interpreter/interpreter.h index 6735b6d17f6d..a47f84238cf6 100644 --- a/executable_semantics/interpreter/interpreter.h +++ b/executable_semantics/interpreter/interpreter.h @@ -28,7 +28,8 @@ class Interpreter { : arena(arena), globals(arena), heap(arena) {} // Interpret the whole program. - auto InterpProgram(const std::vector>& fs) -> int; + auto InterpProgram(const std::vector>& fs, + Nonnull call_main) -> int; // Interpret an expression at compile-time. auto InterpExp(Env values, Nonnull e) diff --git a/executable_semantics/interpreter/type_checker.cpp b/executable_semantics/interpreter/type_checker.cpp index 82df4448bb05..c4601cf945e2 100644 --- a/executable_semantics/interpreter/type_checker.cpp +++ b/executable_semantics/interpreter/type_checker.cpp @@ -52,7 +52,7 @@ static void ExpectPointerType(SourceLocation loc, const std::string& context, } auto TypeChecker::ReifyType(Nonnull t, SourceLocation loc) - -> Nonnull { + -> Nonnull { switch (t->Tag()) { case Value::Kind::IntType: return arena->New(loc); @@ -83,7 +83,7 @@ auto TypeChecker::ReifyType(Nonnull 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, @@ -248,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull type) } } -auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, +auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, Env values) -> TCExpression { if (tracing_output) { llvm::outs() << "checking expression " << *e << "\ntypes: "; @@ -259,7 +259,7 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, } switch (e->Tag()) { case Expression::Kind::IndexExpression: { - const auto& index = cast(*e); + auto& index = cast(*e); auto res = TypeCheckExp(index.Aggregate(), types, values); auto t = res.type; switch (t->Tag()) { @@ -298,7 +298,7 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, return TCExpression(tuple_e, tuple_t, new_types); } case Expression::Kind::FieldAccessExpression: { - const auto& access = cast(*e); + auto& access = cast(*e); auto res = TypeCheckExp(access.Aggregate(), types, values); auto t = res.type; switch (t->Tag()) { @@ -307,18 +307,16 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, // Search for a field for (auto& field : t_class.Fields()) { if (access.Field() == field.first) { - Nonnull 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) { - Nonnull 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); } } @@ -343,9 +341,8 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, const auto& choice = cast(*t); for (const auto& vt : choice.Alternatives()) { if (access.Field() == vt.first) { - Nonnull 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); @@ -377,10 +374,10 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, return TCExpression(e, arena->New(), types); case Expression::Kind::PrimitiveOperatorExpression: { const auto& op = cast(*e); - std::vector> es; + std::vector> es; std::vector> ts; auto new_types = types; - for (Nonnull argument : op.Arguments()) { + for (Nonnull argument : op.Arguments()) { auto res = TypeCheckExp(argument, types, values); new_types = res.types; es.push_back(res.exp); @@ -435,7 +432,7 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, break; } case Expression::Kind::CallExpression: { - const auto& call = cast(*e); + auto& call = cast(*e); auto fun_res = TypeCheckExp(call.Function(), types, values); switch (fun_res.type->Tag()) { case Value::Kind::FunctionType: { @@ -499,7 +496,7 @@ auto TypeChecker::TypeCheckExp(Nonnull e, TypeEnv types, } auto TypeChecker::TypeCheckPattern( - Nonnull p, TypeEnv types, Env values, + Nonnull p, TypeEnv types, Env values, std::optional> expected) -> TCPattern { if (tracing_output) { llvm::outs() << "checking pattern " << *p; @@ -517,7 +514,7 @@ auto TypeChecker::TypeCheckPattern( return {.pattern = p, .type = arena->New(), .types = types}; } case Pattern::Kind::BindingPattern: { - const auto& binding = cast(*p); + auto& binding = cast(*p); TCPattern binding_type_result = TypeCheckPattern(binding.Type(), types, values, std::nullopt); Nonnull type = @@ -543,7 +540,7 @@ auto TypeChecker::TypeCheckPattern( return {.pattern = new_p, .type = type, .types = types}; } case Pattern::Kind::TuplePattern: { - const auto& tuple = cast(*p); + auto& tuple = cast(*p); std::vector new_fields; std::vector field_types; auto new_types = types; @@ -556,7 +553,7 @@ auto TypeChecker::TypeCheckPattern( << "tuples of different length"; } for (size_t i = 0; i < tuple.Fields().size(); ++i) { - const TuplePattern::Field& field = tuple.Fields()[i]; + TuplePattern::Field& field = tuple.Fields()[i]; std::optional> expected_field_type; if (expected) { const TupleElement& expected_element = @@ -580,7 +577,7 @@ auto TypeChecker::TypeCheckPattern( return {.pattern = new_tuple, .type = tuple_t, .types = new_types}; } case Pattern::Kind::AlternativePattern: { - const auto& alternative = cast(*p); + auto& alternative = cast(*p); Nonnull choice_type = interpreter.InterpExp(values, alternative.ChoiceType()); if (choice_type->Tag() != Value::Kind::ChoiceType) { @@ -603,8 +600,8 @@ auto TypeChecker::TypeCheckPattern( values, *parameter_types); // TODO: Think about a cleaner way to cast between Ptr types. // (multiple TODOs) - auto arguments = Nonnull( - cast(arg_results.pattern)); + auto arguments = + Nonnull(cast(arg_results.pattern)); return {.pattern = arena->New( alternative.SourceLoc(), ReifyType(choice_type, alternative.SourceLoc()), @@ -623,26 +620,26 @@ auto TypeChecker::TypeCheckPattern( } auto TypeChecker::TypeCheckCase(Nonnull expected, - Nonnull pat, - Nonnull body, TypeEnv types, - Env values, Nonnull& ret_type, + Nonnull pat, Nonnull body, + TypeEnv types, Env values, + Nonnull& ret_type, bool is_omitted_ret_type) - -> std::pair, Nonnull> { + -> 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(Nonnull s, TypeEnv types, +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& match = cast(*s); auto res = TypeCheckExp(match.Exp(), types, values); auto res_type = res.type; - std::vector, Nonnull>> + std::vector, Nonnull>> new_clauses; for (auto& clause : match.Clauses()) { new_clauses.push_back(TypeCheckCase(res_type, clause.first, @@ -653,7 +650,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, return TCStatement(new_s, types); } case Statement::Kind::While: { - const auto& while_stmt = cast(*s); + auto& while_stmt = cast(*s); auto cnd_res = TypeCheckExp(while_stmt.Cond(), types, values); ExpectType(s->SourceLoc(), "condition of `while`", arena->New(), cnd_res.type); @@ -667,7 +664,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, case Statement::Kind::Continue: return TCStatement(s, types); case Statement::Kind::Block: { - const auto& block = cast(*s); + auto& block = cast(*s); if (block.Stmt()) { auto stmt_res = TypeCheckStmt(*block.Stmt(), types, values, ret_type, is_omitted_ret_type); @@ -678,7 +675,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, } } case Statement::Kind::VariableDefinition: { - const auto& var = cast(*s); + auto& var = cast(*s); auto res = TypeCheckExp(var.Init(), types, values); Nonnull rhs_ty = res.type; auto lhs_res = TypeCheckPattern(var.Pat(), types, values, rhs_ty); @@ -687,11 +684,11 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, return TCStatement(new_s, lhs_res.types); } case Statement::Kind::Sequence: { - const auto& seq = cast(*s); + auto& seq = cast(*s); 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); @@ -703,7 +700,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, checked_types); } case Statement::Kind::Assign: { - const auto& assign = cast(*s); + auto& assign = cast(*s); auto rhs_res = TypeCheckExp(assign.Rhs(), types, values); auto rhs_t = rhs_res.type; auto lhs_res = TypeCheckExp(assign.Lhs(), types, values); @@ -719,13 +716,13 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, return TCStatement(new_s, types); } case Statement::Kind::If: { - const auto& if_stmt = cast(*s); + auto& if_stmt = cast(*s); auto cnd_res = TypeCheckExp(if_stmt.Cond(), types, values); ExpectType(s->SourceLoc(), "condition of `if`", arena->New(), 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); @@ -736,7 +733,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, return TCStatement(new_s, types); } case Statement::Kind::Return: { - const auto& ret = cast(*s); + auto& ret = cast(*s); auto res = TypeCheckExp(ret.Exp(), types, values); if (ret_type->Tag() == Value::Kind::AutoType) { // The following infers the return type from the first 'return' @@ -756,7 +753,7 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, types); } case Statement::Kind::Continuation: { - const auto& cont = cast(*s); + auto& cont = cast(*s); TCStatement body_result = TypeCheckStmt(cont.Body(), types, values, ret_type, is_omitted_ret_type); auto new_continuation = arena->New( @@ -780,8 +777,8 @@ auto TypeChecker::TypeCheckStmt(Nonnull s, TypeEnv types, } auto TypeChecker::CheckOrEnsureReturn( - std::optional> opt_stmt, bool omitted_ret_type, - SourceLocation loc) -> Nonnull { + std::optional> opt_stmt, bool omitted_ret_type, + SourceLocation loc) -> Nonnull { if (!opt_stmt) { if (omitted_ret_type) { return arena->New(arena, loc); @@ -791,11 +788,11 @@ auto TypeChecker::CheckOrEnsureReturn( "type without reaching a return statement"; } } - Nonnull stmt = *opt_stmt; + Nonnull stmt = *opt_stmt; switch (stmt->Tag()) { case Statement::Kind::Match: { - const auto& match = cast(*stmt); - std::vector, Nonnull>> + auto& match = cast(*stmt); + std::vector, Nonnull>> new_clauses; for (const auto& clause : match.Clauses()) { auto s = CheckOrEnsureReturn(clause.second, omitted_ret_type, @@ -810,7 +807,7 @@ auto TypeChecker::CheckOrEnsureReturn( CheckOrEnsureReturn(cast(*stmt).Stmt(), omitted_ret_type, stmt->SourceLoc())); case Statement::Kind::If: { - const auto& if_stmt = cast(*stmt); + auto& if_stmt = cast(*stmt); return arena->New( stmt->SourceLoc(), if_stmt.Cond(), CheckOrEnsureReturn(if_stmt.ThenStmt(), omitted_ret_type, @@ -821,7 +818,7 @@ auto TypeChecker::CheckOrEnsureReturn( case Statement::Kind::Return: return stmt; case Statement::Kind::Sequence: { - const auto& seq = cast(*stmt); + auto& seq = cast(*stmt); if (seq.Next()) { return arena->New( stmt->SourceLoc(), seq.Stmt(), @@ -857,9 +854,8 @@ auto TypeChecker::CheckOrEnsureReturn( // a function. // 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) - -> Nonnull { +auto TypeChecker::TypeCheckFunDef(FunctionDefinition* f, TypeEnv types, + Env values) -> Nonnull { // Bring the deduced parameters into scope for (const auto& deduced : f->deduced_parameters()) { // auto t = interpreter.InterpExp(values, deduced.type); @@ -877,7 +873,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, 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()); @@ -892,7 +888,7 @@ auto TypeChecker::TypeCheckFunDef(const FunctionDefinition* f, TypeEnv types, } auto TypeChecker::TypeOfFunDef(TypeEnv types, Env values, - const FunctionDefinition* fun_def) + FunctionDefinition* fun_def) -> Nonnull { // Bring the deduced parameters into scope for (const auto& deduced : fun_def->deduced_parameters()) { @@ -961,9 +957,8 @@ static auto GetName(const Declaration& d) -> const std::string& { } } -auto TypeChecker::MakeTypeChecked(const Nonnull d, - const TypeEnv& types, const Env& values) - -> Nonnull { +auto TypeChecker::MakeTypeChecked(Nonnull d, const TypeEnv& types, + const Env& values) -> Nonnull { switch (d->Tag()) { case Declaration::Kind::FunctionDeclaration: return arena->New(TypeCheckFunDef( @@ -990,7 +985,7 @@ auto TypeChecker::MakeTypeChecked(const Nonnull d, return d; case Declaration::Kind::VariableDeclaration: { - const auto& var = cast(*d); + auto& var = cast(*d); // Signals a type error if the initializing expression does not have // the declared type of the variable, otherwise returns this // declaration with annotated types. @@ -1012,19 +1007,19 @@ auto TypeChecker::MakeTypeChecked(const Nonnull d, } } -void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { - switch (d.Tag()) { +void TypeChecker::TopLevel(Nonnull d, TypeCheckContext* tops) { + switch (d->Tag()) { case Declaration::Kind::FunctionDeclaration: { - const FunctionDefinition& func_def = - cast(d).Definition(); + FunctionDefinition& func_def = cast(*d).Definition(); auto t = TypeOfFunDef(tops->types, tops->values, &func_def); tops->types.Set(func_def.name(), t); - interpreter.InitEnv(d, &tops->values); + interpreter.InitEnv(*d, &tops->values); break; } case Declaration::Kind::ClassDeclaration: { - const ClassDefinition& class_def = cast(d).Definition(); + const ClassDefinition& class_def = + cast(*d).Definition(); auto st = TypeOfClassDef(&class_def, tops->types, tops->values); Address a = interpreter.AllocateValue(st); tops->values.Set(class_def.name, a); // Is this obsolete? @@ -1041,7 +1036,7 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { } case Declaration::Kind::ChoiceDeclaration: { - const auto& choice = cast(d); + const auto& choice = cast(*d); VarValues alts; for (const auto& alternative : choice.Alternatives()) { auto t = interpreter.InterpExp(tops->values, &alternative.signature()); @@ -1055,10 +1050,10 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { } case Declaration::Kind::VariableDeclaration: { - const auto& var = cast(d); + auto& var = cast(*d); // Associate the variable name with it's declared type in the // compile-time symbol table. - Nonnull type = + Nonnull type = cast(*var.Binding()->Type()).Expression(); Nonnull declared_type = interpreter.InterpExp(tops->values, type); @@ -1068,16 +1063,16 @@ void TypeChecker::TopLevel(const Declaration& d, TypeCheckContext* tops) { } } -auto TypeChecker::TopLevel(const std::vector>& fs) +auto TypeChecker::TopLevel(std::vector>* fs) -> TypeCheckContext { TypeCheckContext tops(arena); bool found_main = false; - for (auto const& d : fs) { + for (auto const& d : *fs) { if (GetName(*d) == "main") { found_main = true; } - TopLevel(*d, &tops); + TopLevel(d, &tops); } if (found_main == false) { diff --git a/executable_semantics/interpreter/type_checker.h b/executable_semantics/interpreter/type_checker.h index bfa70ef99807..8831e2ccfc34 100644 --- a/executable_semantics/interpreter/type_checker.h +++ b/executable_semantics/interpreter/type_checker.h @@ -32,35 +32,31 @@ class TypeChecker { Env values; }; - auto MakeTypeChecked(const Nonnull d, - const TypeEnv& types, const Env& values) - -> Nonnull; + auto MakeTypeChecked(Nonnull d, const TypeEnv& types, + const Env& values) -> Nonnull; - auto TopLevel(const std::vector>& fs) - -> TypeCheckContext; + auto TopLevel(std::vector>* fs) -> TypeCheckContext; private: struct TCExpression { - TCExpression(Nonnull e, Nonnull t, - TypeEnv types) + TCExpression(Nonnull e, Nonnull t, TypeEnv types) : exp(e), type(t), types(types) {} - Nonnull exp; + Nonnull exp; Nonnull type; TypeEnv types; }; struct TCPattern { - Nonnull pattern; + Nonnull pattern; Nonnull type; TypeEnv types; }; struct TCStatement { - TCStatement(Nonnull s, TypeEnv types) - : stmt(s), types(types) {} + TCStatement(Nonnull s, TypeEnv types) : stmt(s), types(types) {} - Nonnull stmt; + Nonnull stmt; TypeEnv types; }; @@ -75,14 +71,14 @@ 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(Nonnull 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(Nonnull p, TypeEnv types, Env values, + auto TypeCheckPattern(Nonnull p, TypeEnv types, Env values, std::optional> expected) -> TCPattern; @@ -93,33 +89,32 @@ 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(Nonnull s, TypeEnv types, Env values, + 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) - -> Nonnull; + auto TypeCheckFunDef(FunctionDefinition* f, TypeEnv types, Env values) + -> Nonnull; - auto TypeCheckCase(Nonnull expected, - Nonnull pat, - Nonnull body, TypeEnv types, Env values, + auto TypeCheckCase(Nonnull expected, Nonnull pat, + Nonnull body, TypeEnv types, Env values, Nonnull& ret_type, bool is_omitted_ret_type) - -> std::pair, Nonnull>; + -> std::pair, Nonnull>; - auto TypeOfFunDef(TypeEnv types, Env values, - const FunctionDefinition* fun_def) -> Nonnull; + auto TypeOfFunDef(TypeEnv types, Env values, FunctionDefinition* fun_def) + -> Nonnull; auto TypeOfClassDef(const ClassDefinition* sd, TypeEnv /*types*/, Env ct_top) -> Nonnull; - void TopLevel(const Declaration& d, TypeCheckContext* tops); + void TopLevel(Nonnull d, TypeCheckContext* tops); - auto CheckOrEnsureReturn(std::optional> opt_stmt, + auto CheckOrEnsureReturn(std::optional> opt_stmt, bool omitted_ret_type, SourceLocation loc) - -> Nonnull; + -> Nonnull; // Reify type to type expression. auto ReifyType(Nonnull t, SourceLocation loc) - -> Nonnull; + -> Nonnull; auto Substitute(TypeEnv dict, Nonnull type) -> Nonnull; diff --git a/executable_semantics/syntax/parser.ypp b/executable_semantics/syntax/parser.ypp index 5f19bb6f64a2..052632b45191 100644 --- a/executable_semantics/syntax/parser.ypp +++ b/executable_semantics/syntax/parser.ypp @@ -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 > 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 , Nonnull>> clause -%type , Nonnull>>> clause_list +%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 { @@ -501,17 +501,13 @@ maybe_empty_tuple_pattern: ; clause: CASE pattern DOUBLE_ARROW statement - { - $$ = - std::pair, Nonnull>($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, Nonnull>(vp, $3); + $$ = std::pair, Nonnull>(vp, $3); } ; clause_list: @@ -701,7 +697,7 @@ declaration_list: | declaration_list declaration { $$ = $1; - $$.push_back(Nonnull($2)); + $$.push_back(Nonnull($2)); } ; %%