// 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/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. }; // Returns the enumerator corresponding to the most-derived type of this // object. auto Tag() const -> Kind { return tag; } auto SourceLoc() const -> SourceLocation { return loc; } 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()); } protected: // Constructs an Statement representing syntax at the given line number. // `tag` must be the enumerator corresponding to the most-derived type being // constructed. Statement(Kind tag, SourceLocation loc) : tag(tag), loc(loc) {} private: const Kind tag; SourceLocation loc; }; class ExpressionStatement : public Statement { public: ExpressionStatement(SourceLocation loc, Ptr 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; } private: Ptr exp; }; class Assign : public Statement { public: Assign(SourceLocation loc, Ptr lhs, Ptr 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; } private: Ptr lhs; Ptr rhs; }; class VariableDefinition : public Statement { public: VariableDefinition(SourceLocation loc, Ptr pat, Ptr 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; } private: Ptr pat; Ptr init; }; class If : public Statement { public: If(SourceLocation loc, Ptr cond, Ptr then_stmt, std::optional> else_stmt) : Statement(Kind::If, loc), cond(cond), then_stmt(then_stmt), else_stmt(else_stmt) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::If; } auto Cond() const -> Ptr { return cond; } auto ThenStmt() const -> Ptr { return then_stmt; } auto ElseStmt() const -> std::optional> { return else_stmt; } private: Ptr cond; Ptr then_stmt; std::optional> else_stmt; }; class Return : public Statement { public: explicit Return(SourceLocation loc) : Return(loc, global_arena->New(loc), true) {} Return(SourceLocation loc, Ptr exp, bool is_omitted_exp) : Statement(Kind::Return, loc), exp(exp), is_omitted_exp(is_omitted_exp) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Return; } auto Exp() const -> Ptr { return exp; } auto IsOmittedExp() const -> bool { return is_omitted_exp; } private: Ptr exp; bool is_omitted_exp; }; class Sequence : public Statement { public: Sequence(SourceLocation loc, Ptr 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; } private: Ptr stmt; std::optional> next; }; class Block : public Statement { public: 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; } private: std::optional> stmt; }; class While : public Statement { public: While(SourceLocation loc, Ptr cond, Ptr 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; } private: Ptr cond; Ptr body; }; class Break : public Statement { public: explicit Break(SourceLocation loc) : Statement(Kind::Break, loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Break; } }; class Continue : public Statement { public: explicit Continue(SourceLocation loc) : Statement(Kind::Continue, loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Continue; } }; class Match : public Statement { public: Match(SourceLocation loc, Ptr exp, std::list, Ptr>>* clauses) : Statement(Kind::Match, loc), exp(exp), clauses(clauses) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Match; } auto Exp() const -> Ptr { return exp; } auto Clauses() const -> const std::list, Ptr>>* { return clauses; } private: Ptr exp; std::list, Ptr>>* clauses; }; // A continuation statement. // // __continuation { // // } class Continuation : public Statement { public: Continuation(SourceLocation loc, std::string continuation_variable, Ptr body) : Statement(Kind::Continuation, loc), continuation_variable(std::move(continuation_variable)), body(body) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Continuation; } auto ContinuationVariable() const -> const std::string& { return continuation_variable; } auto Body() const -> Ptr { return body; } private: std::string continuation_variable; Ptr body; }; // A run statement. // // __run ; class Run : public Statement { public: Run(SourceLocation loc, Ptr 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; } private: Ptr argument; }; // An await statement. // // __await; class Await : public Statement { public: explicit Await(SourceLocation loc) : Statement(Kind::Await, loc) {} static auto classof(const Statement* stmt) -> bool { return stmt->Tag() == Kind::Await; } }; } // namespace Carbon #endif // EXECUTABLE_SEMANTICS_AST_STATEMENT_H_