// Part of the Carbon Language project, under the Apache License v2.0 with LLVM // Exceptions. See /LICENSE for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception #ifndef EXECUTABLE_SEMANTICS_AST_STATEMENT_H_ #define EXECUTABLE_SEMANTICS_AST_STATEMENT_H_ #include #include "common/ostream.h" #include "executable_semantics/ast/expression.h" #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 { class Statement { public: enum class Kind { ExpressionStatement, Assign, VariableDefinition, If, Return, Sequence, Block, While, Break, Continue, Match, Continuation, // Create a first-class continuation. Run, // Run a continuation to the next await or until it finishes. Await, // Pause execution of the continuation. }; void Print(llvm::raw_ostream& out) const { PrintDepth(-1, out); } void PrintDepth(int depth, llvm::raw_ostream& out) const; LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } // Returns the enumerator corresponding to the most-derived type of this // object. auto kind() const -> Kind { return kind_; } auto source_loc() const -> SourceLocation { return source_loc_; } protected: // Constructs an Statement representing syntax at the given line number. // `kind` must be the enumerator corresponding to the most-derived type being // constructed. Statement(Kind kind, SourceLocation source_loc) : kind_(kind), source_loc_(source_loc) {} private: const Kind kind_; SourceLocation source_loc_; }; class ExpressionStatement : public Statement { public: ExpressionStatement(SourceLocation source_loc, Nonnull expression) : Statement(Kind::ExpressionStatement, source_loc), expression_(expression) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::ExpressionStatement; } auto expression() const -> const Expression& { return *expression_; } auto expression() -> Expression& { return *expression_; } private: Nonnull expression_; }; class Assign : public Statement { public: Assign(SourceLocation source_loc, Nonnull lhs, Nonnull rhs) : Statement(Kind::Assign, source_loc), lhs_(lhs), rhs_(rhs) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Assign; } auto lhs() const -> const Expression& { return *lhs_; } auto lhs() -> Expression& { return *lhs_; } auto rhs() const -> const Expression& { return *rhs_; } auto rhs() -> Expression& { return *rhs_; } private: Nonnull lhs_; Nonnull rhs_; }; class VariableDefinition : public Statement { public: VariableDefinition(SourceLocation source_loc, Nonnull pattern, Nonnull init) : Statement(Kind::VariableDefinition, source_loc), pattern_(pattern), init_(init) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::VariableDefinition; } auto pattern() const -> const Pattern& { return *pattern_; } auto pattern() -> Pattern& { return *pattern_; } auto init() const -> const Expression& { return *init_; } auto init() -> Expression& { return *init_; } private: Nonnull pattern_; Nonnull init_; }; class If : public Statement { public: If(SourceLocation source_loc, Nonnull condition, Nonnull then_statement, std::optional> else_statement) : Statement(Kind::If, source_loc), condition_(condition), then_statement_(then_statement), else_statement_(else_statement) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::If; } auto condition() const -> const Expression& { return *condition_; } auto condition() -> Expression& { return *condition_; } auto then_statement() const -> const Statement& { return *then_statement_; } auto then_statement() -> Statement& { return *then_statement_; } auto else_statement() const -> std::optional> { return else_statement_; } auto else_statement() -> std::optional> { return else_statement_; } private: Nonnull condition_; Nonnull then_statement_; std::optional> else_statement_; }; class Return : public Statement { public: Return(Nonnull arena, SourceLocation source_loc) : Return(source_loc, arena->New(source_loc), true) {} Return(SourceLocation source_loc, Nonnull expression, bool is_omitted_expression) : Statement(Kind::Return, source_loc), expression_(expression), is_omitted_expression_(is_omitted_expression) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Return; } auto expression() const -> const Expression& { return *expression_; } auto expression() -> Expression& { return *expression_; } auto is_omitted_expression() const -> bool { return is_omitted_expression_; } private: Nonnull expression_; bool is_omitted_expression_; }; class Sequence : public Statement { public: Sequence(SourceLocation source_loc, Nonnull statement, std::optional> next) : Statement(Kind::Sequence, source_loc), statement_(statement), next_(next) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Sequence; } auto statement() const -> const Statement& { return *statement_; } auto statement() -> Statement& { return *statement_; } auto next() const -> std::optional> { return next_; } auto next() -> std::optional> { return next_; } private: Nonnull statement_; std::optional> next_; }; class Block : public Statement { public: Block(SourceLocation source_loc, std::optional> statement) : Statement(Kind::Block, source_loc), statement_(statement) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Block; } auto statement() const -> std::optional> { return statement_; } auto statement() -> std::optional> { return statement_; } private: std::optional> statement_; }; class While : public Statement { public: While(SourceLocation source_loc, Nonnull condition, Nonnull body) : Statement(Kind::While, source_loc), condition_(condition), body_(body) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::While; } auto condition() const -> const Expression& { return *condition_; } auto condition() -> Expression& { return *condition_; } auto body() const -> const Statement& { return *body_; } auto body() -> Statement& { return *body_; } private: Nonnull condition_; Nonnull body_; }; class Break : public Statement { public: explicit Break(SourceLocation source_loc) : Statement(Kind::Break, source_loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Break; } }; class Continue : public Statement { public: explicit Continue(SourceLocation source_loc) : Statement(Kind::Continue, source_loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Continue; } }; class Match : public Statement { public: class Clause { public: Clause(Nonnull pattern, Nonnull statement) : pattern_(pattern), statement_(statement) {} auto pattern() const -> const Pattern& { return *pattern_; } auto pattern() -> Pattern& { return *pattern_; } auto statement() const -> const Statement& { return *statement_; } auto statement() -> Statement& { return *statement_; } private: Nonnull pattern_; Nonnull statement_; }; Match(SourceLocation source_loc, Nonnull expression, std::vector clauses) : Statement(Kind::Match, source_loc), expression_(expression), clauses_(std::move(clauses)) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Match; } auto expression() const -> const Expression& { return *expression_; } auto expression() -> Expression& { return *expression_; } auto clauses() const -> llvm::ArrayRef { return clauses_; } auto clauses() -> llvm::MutableArrayRef { return clauses_; } private: Nonnull expression_; std::vector clauses_; }; // A continuation statement. // // __continuation { // // } class Continuation : public Statement { public: Continuation(SourceLocation source_loc, std::string continuation_variable, Nonnull body) : Statement(Kind::Continuation, source_loc), continuation_variable_(std::move(continuation_variable)), body_(body) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Continuation; } auto continuation_variable() const -> const std::string& { return continuation_variable_; } auto body() const -> const Statement& { return *body_; } auto body() -> Statement& { return *body_; } private: std::string continuation_variable_; Nonnull body_; }; // A run statement. // // __run ; class Run : public Statement { public: Run(SourceLocation source_loc, Nonnull argument) : Statement(Kind::Run, source_loc), argument_(argument) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Run; } auto argument() const -> const Expression& { return *argument_; } auto argument() -> Expression& { return *argument_; } private: Nonnull argument_; }; // An await statement. // // __await; class Await : public Statement { public: explicit Await(SourceLocation source_loc) : Statement(Kind::Await, source_loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->kind() == Kind::Await; } }; } // namespace Carbon #endif // EXECUTABLE_SEMANTICS_AST_STATEMENT_H_