diff --git a/executable_semantics/interpreter/action.cpp b/executable_semantics/interpreter/action.cpp index dad17615d43a..52985b97d63c 100644 --- a/executable_semantics/interpreter/action.cpp +++ b/executable_semantics/interpreter/action.cpp @@ -15,75 +15,28 @@ #include "executable_semantics/common/arena.h" #include "executable_semantics/interpreter/stack.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Casting.h" namespace Carbon { -auto Action::MakeLValAction(const Expression* e) -> Action* { - auto* act = global_arena->New(); - act->value = LValAction({.exp = e}); - return act; -} - -auto Action::MakeExpressionAction(const Expression* e) -> Action* { - auto* act = global_arena->New(); - act->value = ExpressionAction({.exp = e}); - return act; -} - -auto Action::MakePatternAction(const Pattern* p) -> Action* { - auto* act = global_arena->New(); - act->value = PatternAction({.pattern = p}); - return act; -} - -auto Action::MakeStatementAction(const Statement* s) -> Action* { - auto* act = global_arena->New(); - act->value = StatementAction({.stmt = s}); - return act; -} - -auto Action::MakeValAction(const Value* v) -> Action* { - auto* act = global_arena->New(); - act->value = ValAction({.val = v}); - return act; -} - -auto Action::GetLValAction() const -> const LValAction& { - return std::get(value); -} - -auto Action::GetExpressionAction() const -> const ExpressionAction& { - return std::get(value); -} - -auto Action::GetPatternAction() const -> const PatternAction& { - return std::get(value); -} - -auto Action::GetStatementAction() const -> const StatementAction& { - return std::get(value); -} - -auto Action::GetValAction() const -> const ValAction& { - return std::get(value); -} +using llvm::cast; void Action::Print(llvm::raw_ostream& out) const { - switch (tag()) { - case ActionKind::LValAction: - out << *GetLValAction().exp; + switch (Tag()) { + case Action::Kind::LValAction: + out << *cast(*this).Exp(); break; - case ActionKind::ExpressionAction: - out << *GetExpressionAction().exp; + case Action::Kind::ExpressionAction: + out << *cast(*this).Exp(); break; - case ActionKind::PatternAction: - out << *GetPatternAction().pattern; + case Action::Kind::PatternAction: + out << *cast(*this).Pat(); break; - case ActionKind::StatementAction: - GetStatementAction().stmt->PrintDepth(1, out); + case Action::Kind::StatementAction: + cast(*this).Stmt()->PrintDepth(1, out); break; - case ActionKind::ValAction: - out << *GetValAction().val; + case Action::Kind::ValAction: + out << *cast(*this).Val(); break; } out << "<" << pos << ">"; diff --git a/executable_semantics/interpreter/action.h b/executable_semantics/interpreter/action.h index ac4f0f4b7f96..3cfb7fe6a072 100644 --- a/executable_semantics/interpreter/action.h +++ b/executable_semantics/interpreter/action.h @@ -17,60 +17,18 @@ namespace Carbon { -enum class ActionKind { - LValAction, - ExpressionAction, - PatternAction, - StatementAction, - ValAction, -}; +class Action { + public: + enum class Kind { + LValAction, + ExpressionAction, + PatternAction, + StatementAction, + ValAction, + }; -struct LValAction { - static constexpr ActionKind Kind = ActionKind::LValAction; - const Expression* exp; -}; - -struct ExpressionAction { - static constexpr ActionKind Kind = ActionKind::ExpressionAction; - const Expression* exp; -}; - -struct PatternAction { - static constexpr ActionKind Kind = ActionKind::PatternAction; - const Pattern* pattern; -}; - -struct StatementAction { - static constexpr ActionKind Kind = ActionKind::StatementAction; - const Statement* stmt; -}; - -struct ValAction { - static constexpr ActionKind Kind = ActionKind::ValAction; - const Value* val; -}; - -struct Action { - static auto MakeLValAction(const Expression* e) -> Action*; - static auto MakeExpressionAction(const Expression* e) -> Action*; - static auto MakePatternAction(const Pattern* p) -> Action*; - static auto MakeStatementAction(const Statement* s) -> Action*; - static auto MakeValAction(const Value* v) -> Action*; - - static void PrintList(const Stack& ls, llvm::raw_ostream& out); - - auto GetLValAction() const -> const LValAction&; - auto GetExpressionAction() const -> const ExpressionAction&; - auto GetPatternAction() const -> const PatternAction&; - auto GetStatementAction() const -> const StatementAction&; - auto GetValAction() const -> const ValAction&; - - void Print(llvm::raw_ostream& out) const; - LLVM_DUMP_METHOD void Dump() const { Print(llvm::errs()); } - - inline auto tag() const -> ActionKind { - return std::visit([](const auto& t) { return t.Kind; }, value); - } + Action(const Value&) = delete; + Action& operator=(const Value&) = delete; // The position or state of the action. Starts at 0 and goes up to the number // of subexpressions. @@ -78,15 +36,113 @@ struct Action { // pos indicates how many of the entries in the following `results` vector // will be filled in the next time this action is active. // For each i < pos, results[i] contains a pointer to a Value. - int pos = 0; + auto Pos() const -> int { return pos; } // Results from a subexpression. - std::vector results; + auto Results() const -> const std::vector& { return results; } + + void IncrementPos() { ++pos; } + + void AddResult(const Value* result) { results.push_back(result); } + + void Clear() { + pos = 0; + results.clear(); + } + + // Returns the enumerator corresponding to the most-derived type of this + // object. + auto Tag() const -> Kind { return tag; } + + 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()); } + + protected: + // Constructs an Action. `tag` must be the enumerator corresponding to the + // most-derived type being constructed. + explicit Action(Kind tag) : tag(tag) {} private: - std::variant - value; + int pos = 0; + std::vector results; + + const Kind tag; +}; + +class LValAction : public Action { + public: + explicit LValAction(const Expression* exp) + : Action(Kind::LValAction), exp(exp) {} + + static auto classof(const Action* action) -> bool { + return action->Tag() == Kind::LValAction; + } + + auto Exp() const -> const Expression* { return exp; } + + private: + const Expression* exp; +}; + +class ExpressionAction : public Action { + public: + explicit ExpressionAction(const Expression* exp) + : Action(Kind::ExpressionAction), exp(exp) {} + + static auto classof(const Action* action) -> bool { + return action->Tag() == Kind::ExpressionAction; + } + + auto Exp() const -> const Expression* { return exp; } + + private: + const Expression* exp; +}; + +class PatternAction : public Action { + public: + explicit PatternAction(const Pattern* pat) + : Action(Kind::PatternAction), pat(pat) {} + + static auto classof(const Action* action) -> bool { + return action->Tag() == Kind::PatternAction; + } + + auto Pat() const -> const Pattern* { return pat; } + + private: + const Pattern* pat; +}; + +class StatementAction : public Action { + public: + explicit StatementAction(const Statement* stmt) + : Action(Kind::StatementAction), stmt(stmt) {} + + static auto classof(const Action* action) -> bool { + return action->Tag() == Kind::StatementAction; + } + + auto Stmt() const -> const Statement* { return stmt; } + + private: + const Statement* stmt; +}; + +class ValAction : public Action { + public: + explicit ValAction(const Value* val) : Action(Kind::ValAction), val(val) {} + + static auto classof(const Action* action) -> bool { + return action->Tag() == Kind::ValAction; + } + + auto Val() const -> const Value* { return val; } + + private: + const Value* val; }; } // namespace Carbon diff --git a/executable_semantics/interpreter/interpreter.cpp b/executable_semantics/interpreter/interpreter.cpp index 399f4815dc1c..0c7aa7809f02 100644 --- a/executable_semantics/interpreter/interpreter.cpp +++ b/executable_semantics/interpreter/interpreter.cpp @@ -199,7 +199,7 @@ void CallFunction(int line_num, std::vector operas, auto* scope = global_arena->New(*matches, params); auto* frame = global_arena->New( fn.Name(), Stack(scope), - Stack(Action::MakeStatementAction(fn.Body()))); + Stack(global_arena->New(fn.Body()))); state->stack.Push(frame); break; } @@ -207,7 +207,7 @@ void CallFunction(int line_num, std::vector operas, const Value* arg = CopyVal(operas[1], line_num); const Value* sv = global_arena->New(operas[0], arg); Frame* frame = state->stack.Top(); - frame->todo.Push(Action::MakeValAction(sv)); + frame->todo.Push(global_arena->New(sv)); break; } case Value::Kind::AlternativeConstructorValue: { @@ -216,7 +216,7 @@ void CallFunction(int line_num, std::vector operas, const Value* av = global_arena->New( alt.AltName(), alt.ChoiceName(), arg); Frame* frame = state->stack.Top(); - frame->todo.Push(Action::MakeValAction(av)); + frame->todo.Push(global_arena->New(av)); break; } default: @@ -243,15 +243,17 @@ void DeallocateLocals(int line_num, Frame* frame) { void CreateTuple(Frame* frame, Action* act, const Expression* exp) { // { { (v1,...,vn) :: C, E, F} :: S, H} // -> { { `(v1,...,vn) :: C, E, F} :: S, H} + const auto& tup_lit = exp->GetTupleLiteral(); + CHECK(act->Results().size() == tup_lit.fields.size()); std::vector elements; - auto f = exp->GetTupleLiteral().fields.begin(); - - for (auto i = act->results.begin(); i != act->results.end(); ++i, ++f) { - elements.push_back({.name = f->name, .value = *i}); + for (size_t i = 0; i < act->Results().size(); ++i) { + elements.push_back( + {.name = tup_lit.fields[i].name, .value = act->Results()[i]}); } + const Value* tv = global_arena->New(std::move(elements)); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(tv)); + frame->todo.Push(global_arena->New(tv)); } // Returns an updated environment that includes the bindings of @@ -401,7 +403,7 @@ void PatternAssignment(const Value* pat, const Value* val, int line_num) { void StepLvalue() { Frame* frame = state->stack.Top(); Action* act = frame->todo.Top(); - const Expression* exp = act->GetLValAction().exp; + const Expression* exp = cast(*act).Exp(); if (tracing_output) { llvm::outs() << "--- step lvalue " << *exp << " --->\n"; } @@ -417,68 +419,69 @@ void StepLvalue() { } const Value* v = global_arena->New(*pointer); frame->todo.Pop(); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } case ExpressionKind::FieldAccessExpression: { - if (act->pos == 0) { + if (act->Pos() == 0) { // { {e.f :: C, E, F} :: S, H} // -> { e :: [].f :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeLValAction(exp->GetFieldAccessExpression().aggregate)); - act->pos++; + frame->todo.Push(global_arena->New( + exp->GetFieldAccessExpression().aggregate)); + act->IncrementPos(); } else { // { v :: [].f :: C, E, F} :: S, H} // -> { { &v.f :: C, E, F} :: S, H } - Address aggregate = cast(*act->results[0]).Val(); + Address aggregate = cast(*act->Results()[0]).Val(); Address field = aggregate.SubobjectAddress(exp->GetFieldAccessExpression().field); frame->todo.Pop(1); - frame->todo.Push( - Action::MakeValAction(global_arena->New(field))); + frame->todo.Push(global_arena->New( + global_arena->New(field))); } break; } case ExpressionKind::IndexExpression: { - if (act->pos == 0) { + if (act->Pos() == 0) { // { {e[i] :: C, E, F} :: S, H} // -> { e :: [][i] :: C, E, F} :: S, H} frame->todo.Push( - Action::MakeLValAction(exp->GetIndexExpression().aggregate)); - act->pos++; - } else if (act->pos == 1) { - frame->todo.Push( - Action::MakeExpressionAction(exp->GetIndexExpression().offset)); - act->pos++; - } else if (act->pos == 2) { + global_arena->New(exp->GetIndexExpression().aggregate)); + act->IncrementPos(); + } else if (act->Pos() == 1) { + frame->todo.Push(global_arena->New( + exp->GetIndexExpression().offset)); + act->IncrementPos(); + } else if (act->Pos() == 2) { // { v :: [][i] :: C, E, F} :: S, H} // -> { { &v[i] :: C, E, F} :: S, H } - Address aggregate = cast(*act->results[0]).Val(); - std::string f = std::to_string(cast(*act->results[1]).Val()); + Address aggregate = cast(*act->Results()[0]).Val(); + std::string f = + std::to_string(cast(*act->Results()[1]).Val()); Address field = aggregate.SubobjectAddress(f); frame->todo.Pop(1); - frame->todo.Push( - Action::MakeValAction(global_arena->New(field))); + frame->todo.Push(global_arena->New( + global_arena->New(field))); } break; } case ExpressionKind::TupleLiteral: { - if (act->pos == 0) { + if (act->Pos() == 0) { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} const Expression* e1 = exp->GetTupleLiteral().fields[0].expression; - frame->todo.Push(Action::MakeLValAction(e1)); - act->pos++; - } else if (act->pos != + frame->todo.Push(global_arena->New(e1)); + act->IncrementPos(); + } else if (act->Pos() != static_cast(exp->GetTupleLiteral().fields.size())) { // { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S, // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} const Expression* elt = - exp->GetTupleLiteral().fields[act->pos].expression; - frame->todo.Push(Action::MakeLValAction(elt)); - act->pos++; + exp->GetTupleLiteral().fields[act->Pos()].expression; + frame->todo.Push(global_arena->New(elt)); + act->IncrementPos(); } else { CreateTuple(frame, act, exp); } @@ -504,37 +507,37 @@ void StepLvalue() { void StepExp() { Frame* frame = state->stack.Top(); Action* act = frame->todo.Top(); - const Expression* exp = act->GetExpressionAction().exp; + const Expression* exp = cast(*act).Exp(); if (tracing_output) { llvm::outs() << "--- step exp " << *exp << " --->\n"; } switch (exp->tag()) { case ExpressionKind::IndexExpression: { - if (act->pos == 0) { + if (act->Pos() == 0) { // { { e[i] :: C, E, F} :: S, H} // -> { { e :: [][i] :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeExpressionAction(exp->GetIndexExpression().aggregate)); - act->pos++; - } else if (act->pos == 1) { - frame->todo.Push( - Action::MakeExpressionAction(exp->GetIndexExpression().offset)); - act->pos++; - } else if (act->pos == 2) { - auto tuple = act->results[0]; + frame->todo.Push(global_arena->New( + exp->GetIndexExpression().aggregate)); + act->IncrementPos(); + } else if (act->Pos() == 1) { + frame->todo.Push(global_arena->New( + exp->GetIndexExpression().offset)); + act->IncrementPos(); + } else if (act->Pos() == 2) { + auto tuple = act->Results()[0]; switch (tuple->Tag()) { case Value::Kind::TupleValue: { // { { v :: [][i] :: C, E, F} :: S, H} // -> { { v_i :: C, E, F} : S, H} std::string f = - std::to_string(cast(*act->results[1]).Val()); + std::to_string(cast(*act->Results()[1]).Val()); const Value* field = cast(*tuple).FindField(f); if (field == nullptr) { FATAL_RUNTIME_ERROR_NO_LINE() << "field " << f << " not in " << *tuple; } frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(field)); + frame->todo.Push(global_arena->New(field)); break; } default: @@ -545,50 +548,50 @@ void StepExp() { break; } case ExpressionKind::TupleLiteral: { - if (act->pos == 0) { + if (act->Pos() == 0) { if (exp->GetTupleLiteral().fields.size() > 0) { // { {(f1=e1,...) :: C, E, F} :: S, H} // -> { {e1 :: (f1=[],...) :: C, E, F} :: S, H} const Expression* e1 = exp->GetTupleLiteral().fields[0].expression; - frame->todo.Push(Action::MakeExpressionAction(e1)); - act->pos++; + frame->todo.Push(global_arena->New(e1)); + act->IncrementPos(); } else { CreateTuple(frame, act, exp); } - } else if (act->pos != + } else if (act->Pos() != static_cast(exp->GetTupleLiteral().fields.size())) { // { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S, // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} const Expression* elt = - exp->GetTupleLiteral().fields[act->pos].expression; - frame->todo.Push(Action::MakeExpressionAction(elt)); - act->pos++; + exp->GetTupleLiteral().fields[act->Pos()].expression; + frame->todo.Push(global_arena->New(elt)); + act->IncrementPos(); } else { CreateTuple(frame, act, exp); } break; } case ExpressionKind::FieldAccessExpression: { - if (act->pos == 0) { + if (act->Pos() == 0) { // { { e.f :: C, E, F} :: S, H} // -> { { e :: [].f :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction( + frame->todo.Push(global_arena->New( exp->GetFieldAccessExpression().aggregate)); - act->pos++; + act->IncrementPos(); } else { // { { v :: [].f :: C, E, F} :: S, H} // -> { { v_f :: C, E, F} : S, H} - const Value* element = act->results[0]->GetField( + const Value* element = act->Results()[0]->GetField( FieldPath(exp->GetFieldAccessExpression().field), exp->line_num); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(element)); + frame->todo.Push(global_arena->New(element)); } break; } case ExpressionKind::IdentifierExpression: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { {x :: C, E, F} :: S, H} -> { {H(E(x)) :: C, E, F} :: S, H} std::optional
pointer = CurrentEnv(state).Get(exp->GetIdentifierExpression().name); @@ -598,111 +601,112 @@ void StepExp() { } const Value* pointee = state->heap.Read(*pointer, exp->line_num); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(pointee)); + frame->todo.Push(global_arena->New(pointee)); break; } case ExpressionKind::IntLiteral: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction( + frame->todo.Push(global_arena->New( global_arena->New(exp->GetIntLiteral()))); break; case ExpressionKind::BoolLiteral: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { {n :: C, E, F} :: S, H} -> { {n' :: C, E, F} :: S, H} frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction( + frame->todo.Push(global_arena->New( global_arena->New(exp->GetBoolLiteral()))); break; case ExpressionKind::PrimitiveOperatorExpression: - if (act->pos != + if (act->Pos() != static_cast( exp->GetPrimitiveOperatorExpression().arguments.size())) { // { {v :: op(vs,[],e,es) :: C, E, F} :: S, H} // -> { {e :: op(vs,v,[],es) :: C, E, F} :: S, H} const Expression* arg = - exp->GetPrimitiveOperatorExpression().arguments[act->pos]; - frame->todo.Push(Action::MakeExpressionAction(arg)); - act->pos++; + exp->GetPrimitiveOperatorExpression().arguments[act->Pos()]; + frame->todo.Push(global_arena->New(arg)); + act->IncrementPos(); } else { // { {v :: op(vs,[]) :: C, E, F} :: S, H} // -> { {eval_prim(op, (vs,v)) :: C, E, F} :: S, H} const Value* v = EvalPrim(exp->GetPrimitiveOperatorExpression().op, - act->results, exp->line_num); + act->Results(), exp->line_num); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); } break; case ExpressionKind::CallExpression: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {e1(e2) :: C, E, F} :: S, H} // -> { {e1 :: [](e2) :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeExpressionAction(exp->GetCallExpression().function)); - act->pos++; - } else if (act->pos == 1) { + frame->todo.Push(global_arena->New( + exp->GetCallExpression().function)); + act->IncrementPos(); + } else if (act->Pos() == 1) { // { { v :: [](e) :: C, E, F} :: S, H} // -> { { e :: v([]) :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeExpressionAction(exp->GetCallExpression().argument)); - act->pos++; - } else if (act->pos == 2) { + frame->todo.Push(global_arena->New( + exp->GetCallExpression().argument)); + act->IncrementPos(); + } else if (act->Pos() == 2) { // { { v2 :: v1([]) :: C, E, F} :: S, H} // -> { {C',E',F'} :: {C, E, F} :: S, H} frame->todo.Pop(1); - CallFunction(exp->line_num, act->results, state); + CallFunction(exp->line_num, act->Results(), state); } else { - FATAL() << "in handle_value with Call pos " << act->pos; + FATAL() << "in handle_value with Call pos " << act->Pos(); } break; case ExpressionKind::IntTypeLiteral: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); const Value* v = global_arena->New(); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } case ExpressionKind::BoolTypeLiteral: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); const Value* v = global_arena->New(); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } case ExpressionKind::TypeTypeLiteral: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); const Value* v = global_arena->New(); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } case ExpressionKind::FunctionTypeLiteral: { - if (act->pos == 0) { - frame->todo.Push(Action::MakeExpressionAction( + if (act->Pos() == 0) { + frame->todo.Push(global_arena->New( exp->GetFunctionTypeLiteral().parameter)); - act->pos++; - } else if (act->pos == 1) { + act->IncrementPos(); + } else if (act->Pos() == 1) { // { { pt :: fn [] -> e :: C, E, F} :: S, H} // -> { { e :: fn pt -> []) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction( + frame->todo.Push(global_arena->New( exp->GetFunctionTypeLiteral().return_type)); - act->pos++; - } else if (act->pos == 2) { + act->IncrementPos(); + } else if (act->Pos() == 2) { // { { rt :: fn pt -> [] :: C, E, F} :: S, H} // -> { fn pt -> rt :: {C, E, F} :: S, H} const Value* v = global_arena->New( - std::vector(), act->results[0], act->results[1]); + std::vector(), act->Results()[0], + act->Results()[1]); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); } break; } case ExpressionKind::ContinuationTypeLiteral: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); const Value* v = global_arena->New(); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } } // switch (exp->tag) @@ -711,95 +715,96 @@ void StepExp() { void StepPattern() { Frame* frame = state->stack.Top(); Action* act = frame->todo.Top(); - const Pattern* pattern = act->GetPatternAction().pattern; + const Pattern* pattern = cast(*act).Pat(); if (tracing_output) { llvm::outs() << "--- step pattern " << *pattern << " --->\n"; } switch (pattern->Tag()) { case Pattern::Kind::AutoPattern: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); const Value* v = global_arena->New(); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); break; } case Pattern::Kind::BindingPattern: { const auto& binding = cast(*pattern); - if (act->pos == 0) { - frame->todo.Push(Action::MakePatternAction(binding.Type())); - act->pos++; + if (act->Pos() == 0) { + frame->todo.Push(global_arena->New(binding.Type())); + act->IncrementPos(); } else { auto v = global_arena->New(binding.Name(), - act->results[0]); + act->Results()[0]); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(v)); + frame->todo.Push(global_arena->New(v)); } break; } case Pattern::Kind::TuplePattern: { const auto& tuple = cast(*pattern); - if (act->pos == 0) { + if (act->Pos() == 0) { if (tuple.Fields().empty()) { frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(&TupleValue::Empty())); + frame->todo.Push(global_arena->New(&TupleValue::Empty())); } else { const Pattern* p1 = tuple.Fields()[0].pattern; - frame->todo.Push(Action::MakePatternAction(p1)); - act->pos++; + frame->todo.Push(global_arena->New(p1)); + act->IncrementPos(); } - } else if (act->pos != static_cast(tuple.Fields().size())) { + } else if (act->Pos() != static_cast(tuple.Fields().size())) { // { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S, // H} // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, // H} - const Pattern* elt = tuple.Fields()[act->pos].pattern; - frame->todo.Push(Action::MakePatternAction(elt)); - act->pos++; + const Pattern* elt = tuple.Fields()[act->Pos()].pattern; + frame->todo.Push(global_arena->New(elt)); + act->IncrementPos(); } else { std::vector elements; for (size_t i = 0; i < tuple.Fields().size(); ++i) { elements.push_back( - {.name = tuple.Fields()[i].name, .value = act->results[i]}); + {.name = tuple.Fields()[i].name, .value = act->Results()[i]}); } const Value* tuple_value = global_arena->New(std::move(elements)); frame->todo.Pop(1); - frame->todo.Push(Action::MakeValAction(tuple_value)); + frame->todo.Push(global_arena->New(tuple_value)); } break; } case Pattern::Kind::AlternativePattern: { const auto& alternative = cast(*pattern); - if (act->pos == 0) { + if (act->Pos() == 0) { frame->todo.Push( - Action::MakeExpressionAction(alternative.ChoiceType())); - act->pos++; - } else if (act->pos == 1) { - frame->todo.Push(Action::MakePatternAction(alternative.Arguments())); - act->pos++; + global_arena->New(alternative.ChoiceType())); + act->IncrementPos(); + } else if (act->Pos() == 1) { + frame->todo.Push( + global_arena->New(alternative.Arguments())); + act->IncrementPos(); } else { - CHECK(act->pos == 2); - const auto& choice_type = cast(*act->results[0]); + CHECK(act->Pos() == 2); + const auto& choice_type = cast(*act->Results()[0]); frame->todo.Pop(1); frame->todo.Push( - Action::MakeValAction(global_arena->New( + global_arena->New(global_arena->New( alternative.AlternativeName(), choice_type.Name(), - act->results[1]))); + act->Results()[1]))); } break; } case Pattern::Kind::ExpressionPattern: frame->todo.Pop(1); - frame->todo.Push(Action::MakeExpressionAction( + frame->todo.Push(global_arena->New( cast(pattern)->Expression())); break; } } auto IsWhileAct(Action* act) -> bool { - switch (act->tag()) { - case ActionKind::StatementAction: - switch (act->GetStatementAction().stmt->tag()) { + switch (act->Tag()) { + case Action::Kind::StatementAction: + switch (cast(*act).Stmt()->tag()) { case StatementKind::While: return true; default: @@ -811,9 +816,9 @@ auto IsWhileAct(Action* act) -> bool { } auto IsBlockAct(Action* act) -> bool { - switch (act->tag()) { - case ActionKind::StatementAction: - switch (act->GetStatementAction().stmt->tag()) { + switch (act->Tag()) { + case Action::Kind::StatementAction: + switch (cast(*act).Stmt()->tag()) { case StatementKind::Block: return true; default: @@ -829,7 +834,7 @@ auto IsBlockAct(Action* act) -> bool { void StepStmt() { Frame* frame = state->stack.Top(); Action* act = frame->todo.Top(); - const Statement* stmt = act->GetStatementAction().stmt; + const Statement* stmt = cast(*act).Stmt(); CHECK(stmt != nullptr) << "null statement!"; if (tracing_output) { llvm::outs() << "--- step stmt "; @@ -838,22 +843,23 @@ void StepStmt() { } switch (stmt->tag()) { case StatementKind::Match: - if (act->pos == 0) { + if (act->Pos() == 0) { // { { (match (e) ...) :: C, E, F} :: S, H} // -> { { e :: (match ([]) ...) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction(stmt->GetMatch().exp)); - act->pos++; + frame->todo.Push( + global_arena->New(stmt->GetMatch().exp)); + act->IncrementPos(); } else { - // Regarding act->pos: + // Regarding act->Pos(): // * odd: start interpreting the pattern of a clause // * even: finished interpreting the pattern, now try to match // - // Regarding act->results: + // Regarding act->Results(): // * 0: the value that we're matching // * 1: the pattern for clause 0 // * 2: the pattern for clause 1 // * ... - auto clause_num = (act->pos - 1) / 2; + auto clause_num = (act->Pos() - 1) / 2; if (clause_num >= static_cast(stmt->GetMatch().clauses->size())) { frame->todo.Pop(1); break; @@ -861,15 +867,15 @@ void StepStmt() { auto c = stmt->GetMatch().clauses->begin(); std::advance(c, clause_num); - if (act->pos % 2 == 1) { + if (act->Pos() % 2 == 1) { // start interpreting the pattern of the clause // { {v :: (match ([]) ...) :: C, E, F} :: S, H} // -> { {pi :: (match ([]) ...) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakePatternAction(c->first)); - act->pos++; + frame->todo.Push(global_arena->New(c->first)); + act->IncrementPos(); } else { // try to match - auto v = act->results[0]; - auto pat = act->results[clause_num + 1]; + auto v = act->Results()[0]; + auto pat = act->Results()[clause_num + 1]; auto values = CurrentEnv(state); std::list vars; std::optional matches = @@ -879,15 +885,15 @@ void StepStmt() { frame->scopes.Push(new_scope); const Statement* body_block = Statement::MakeBlock(stmt->line_num, c->second); - Action* body_act = Action::MakeStatementAction(body_block); - body_act->pos = 1; + Action* body_act = global_arena->New(body_block); + body_act->IncrementPos(); frame->todo.Pop(1); frame->todo.Push(body_act); - frame->todo.Push(Action::MakeStatementAction(c->second)); + frame->todo.Push(global_arena->New(c->second)); } else { // this case did not match, moving on - act->pos++; - clause_num = (act->pos - 1) / 2; + act->IncrementPos(); + clause_num = (act->Pos() - 1) / 2; if (clause_num == static_cast(stmt->GetMatch().clauses->size())) { frame->todo.Pop(1); @@ -897,27 +903,27 @@ void StepStmt() { } break; case StatementKind::While: - if (act->pos == 0) { + if (act->Pos() == 0) { // { { (while (e) s) :: C, E, F} :: S, H} // -> { { e :: (while ([]) s) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction(stmt->GetWhile().cond)); - act->pos++; - } else if (cast(*act->results[0]).Val()) { + frame->todo.Push( + global_arena->New(stmt->GetWhile().cond)); + act->IncrementPos(); + } else if (cast(*act->Results()[0]).Val()) { // { {true :: (while ([]) s) :: C, E, F} :: S, H} // -> { { s :: (while (e) s) :: C, E, F } :: S, H} - frame->todo.Top()->pos = 0; - frame->todo.Top()->results.clear(); - frame->todo.Push(Action::MakeStatementAction(stmt->GetWhile().body)); + frame->todo.Top()->Clear(); + frame->todo.Push( + global_arena->New(stmt->GetWhile().body)); } else { // { {false :: (while ([]) s) :: C, E, F} :: S, H} // -> { { C, E, F } :: S, H} - frame->todo.Top()->pos = 0; - frame->todo.Top()->results.clear(); + frame->todo.Top()->Clear(); frame->todo.Pop(1); } break; case StatementKind::Break: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { { break; :: ... :: (while (e) s) :: C, E, F} :: S, H} // -> { { C, E', F} :: S, H} frame->todo.Pop(1); @@ -931,7 +937,7 @@ void StepStmt() { frame->todo.Pop(1); break; case StatementKind::Continue: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { { continue; :: ... :: (while (e) s) :: C, E, F} :: S, H} // -> { { (while (e) s) :: C, E', F} :: S, H} frame->todo.Pop(1); @@ -944,14 +950,15 @@ void StepStmt() { } break; case StatementKind::Block: { - if (act->pos == 0) { + if (act->Pos() == 0) { if (stmt->GetBlock().stmt) { auto* scope = global_arena->New(CurrentEnv(state), std::list()); frame->scopes.Push(scope); - frame->todo.Push(Action::MakeStatementAction(stmt->GetBlock().stmt)); - act->pos++; - act->pos++; + frame->todo.Push( + global_arena->New(stmt->GetBlock().stmt)); + act->IncrementPos(); + act->IncrementPos(); } else { frame->todo.Pop(); } @@ -964,21 +971,21 @@ void StepStmt() { break; } case StatementKind::VariableDefinition: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {(var x = e) :: C, E, F} :: S, H} // -> { {e :: (var x = []) :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeExpressionAction(stmt->GetVariableDefinition().init)); - act->pos++; - } else if (act->pos == 1) { - frame->todo.Push( - Action::MakePatternAction(stmt->GetVariableDefinition().pat)); - act->pos++; - } else if (act->pos == 2) { + frame->todo.Push(global_arena->New( + stmt->GetVariableDefinition().init)); + act->IncrementPos(); + } else if (act->Pos() == 1) { + frame->todo.Push(global_arena->New( + stmt->GetVariableDefinition().pat)); + act->IncrementPos(); + } else if (act->Pos() == 2) { // { { v :: (x = []) :: C, E, F} :: S, H} // -> { { C, E(x := a), F} :: S, H(a := copy(v))} - const Value* v = act->results[0]; - const Value* p = act->results[1]; + const Value* v = act->Results()[0]; + const Value* p = act->Results()[1]; std::optional matches = PatternMatch(p, v, frame->scopes.Top()->values, @@ -991,86 +998,93 @@ void StepStmt() { } break; case StatementKind::ExpressionStatement: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {e :: C, E, F} :: S, H} // -> { {e :: C, E, F} :: S, H} - frame->todo.Push( - Action::MakeExpressionAction(stmt->GetExpressionStatement().exp)); - act->pos++; + frame->todo.Push(global_arena->New( + stmt->GetExpressionStatement().exp)); + act->IncrementPos(); } else { frame->todo.Pop(1); } break; case StatementKind::Assign: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {(lv = e) :: C, E, F} :: S, H} // -> { {lv :: ([] = e) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeLValAction(stmt->GetAssign().lhs)); - act->pos++; - } else if (act->pos == 1) { + frame->todo.Push(global_arena->New(stmt->GetAssign().lhs)); + act->IncrementPos(); + } else if (act->Pos() == 1) { // { { a :: ([] = e) :: C, E, F} :: S, H} // -> { { e :: (a = []) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction(stmt->GetAssign().rhs)); - act->pos++; - } else if (act->pos == 2) { + frame->todo.Push( + global_arena->New(stmt->GetAssign().rhs)); + act->IncrementPos(); + } else if (act->Pos() == 2) { // { { v :: (a = []) :: C, E, F} :: S, H} // -> { { C, E, F} :: S, H(a := v)} - auto pat = act->results[0]; - auto val = act->results[1]; + auto pat = act->Results()[0]; + auto val = act->Results()[1]; PatternAssignment(pat, val, stmt->line_num); frame->todo.Pop(1); } break; case StatementKind::If: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {(if (e) then_stmt else else_stmt) :: C, E, F} :: S, H} // -> { { e :: (if ([]) then_stmt else else_stmt) :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction(stmt->GetIf().cond)); - act->pos++; - } else if (cast(*act->results[0]).Val()) { + frame->todo.Push( + global_arena->New(stmt->GetIf().cond)); + act->IncrementPos(); + } else if (cast(*act->Results()[0]).Val()) { // { {true :: if ([]) then_stmt else else_stmt :: C, E, F} :: // S, H} // -> { { then_stmt :: C, E, F } :: S, H} frame->todo.Pop(1); - frame->todo.Push(Action::MakeStatementAction(stmt->GetIf().then_stmt)); + frame->todo.Push( + global_arena->New(stmt->GetIf().then_stmt)); } else if (stmt->GetIf().else_stmt) { // { {false :: if ([]) then_stmt else else_stmt :: C, E, F} :: // S, H} // -> { { else_stmt :: C, E, F } :: S, H} frame->todo.Pop(1); - frame->todo.Push(Action::MakeStatementAction(stmt->GetIf().else_stmt)); + frame->todo.Push( + global_arena->New(stmt->GetIf().else_stmt)); } else { frame->todo.Pop(1); } break; case StatementKind::Return: - if (act->pos == 0) { + if (act->Pos() == 0) { // { {return e :: C, E, F} :: S, H} // -> { {e :: return [] :: C, E, F} :: S, H} - frame->todo.Push(Action::MakeExpressionAction(stmt->GetReturn().exp)); - act->pos++; + frame->todo.Push( + global_arena->New(stmt->GetReturn().exp)); + act->IncrementPos(); } else { // { {v :: return [] :: C, E, F} :: {C', E', F'} :: S, H} // -> { {v :: C', E', F'} :: S, H} - const Value* ret_val = CopyVal(act->results[0], stmt->line_num); + const Value* ret_val = CopyVal(act->Results()[0], stmt->line_num); DeallocateLocals(stmt->line_num, frame); state->stack.Pop(1); frame = state->stack.Top(); - frame->todo.Push(Action::MakeValAction(ret_val)); + frame->todo.Push(global_arena->New(ret_val)); } break; case StatementKind::Sequence: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // { { (s1,s2) :: C, E, F} :: S, H} // -> { { s1 :: s2 :: C, E, F} :: S, H} frame->todo.Pop(1); if (stmt->GetSequence().next) { - frame->todo.Push(Action::MakeStatementAction(stmt->GetSequence().next)); + frame->todo.Push( + global_arena->New(stmt->GetSequence().next)); } - frame->todo.Push(Action::MakeStatementAction(stmt->GetSequence().stmt)); + frame->todo.Push( + global_arena->New(stmt->GetSequence().stmt)); break; case StatementKind::Continuation: { - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // Create a continuation object by creating a frame similar the // way one is created in a function call. Scope* scope = @@ -1078,10 +1092,11 @@ void StepStmt() { Stack scopes; scopes.Push(scope); Stack todo; - todo.Push(Action::MakeStatementAction( + todo.Push(global_arena->New( Statement::MakeReturn(stmt->line_num, nullptr, /*is_omitted_exp=*/true))); - todo.Push(Action::MakeStatementAction(stmt->GetContinuation().body)); + todo.Push( + global_arena->New(stmt->GetContinuation().body)); Frame* continuation_frame = global_arena->New("__continuation", scopes, todo); Address continuation_address = @@ -1097,23 +1112,23 @@ void StepStmt() { break; } case StatementKind::Run: - if (act->pos == 0) { + if (act->Pos() == 0) { // Evaluate the argument of the run statement. - frame->todo.Push(Action::MakeExpressionAction(stmt->GetRun().argument)); - act->pos++; + frame->todo.Push( + global_arena->New(stmt->GetRun().argument)); + act->IncrementPos(); } else { frame->todo.Pop(1); // Push an expression statement action to ignore the result // value from the continuation. - Action* ignore_result = - Action::MakeStatementAction(Statement::MakeExpressionStatement( + Action* ignore_result = global_arena->New( + Statement::MakeExpressionStatement( stmt->line_num, Expression::MakeTupleLiteral(stmt->line_num, {}))); - ignore_result->pos = 0; frame->todo.Push(ignore_result); // Push the continuation onto the current stack. const std::vector& continuation_vector = - cast(*act->results[0]).Stack(); + cast(*act->Results()[0]).Stack(); for (auto frame_iter = continuation_vector.rbegin(); frame_iter != continuation_vector.rend(); ++frame_iter) { state->stack.Push(*frame_iter); @@ -1121,7 +1136,7 @@ void StepStmt() { } break; case StatementKind::Await: - CHECK(act->pos == 0); + CHECK(act->Pos() == 0); // Pause the current continuation frame->todo.Pop(); std::vector paused; @@ -1145,23 +1160,23 @@ void Step() { } Action* act = frame->todo.Top(); - switch (act->tag()) { - case ActionKind::ValAction: { - Action* val_act = frame->todo.Pop(); + switch (act->Tag()) { + case Action::Kind::ValAction: { + const ValAction& val_act = cast(*frame->todo.Pop()); Action* act = frame->todo.Top(); - act->results.push_back(val_act->GetValAction().val); + act->AddResult(val_act.Val()); break; } - case ActionKind::LValAction: + case Action::Kind::LValAction: StepLvalue(); break; - case ActionKind::ExpressionAction: + case Action::Kind::ExpressionAction: StepExp(); break; - case ActionKind::PatternAction: + case Action::Kind::PatternAction: StepPattern(); break; - case ActionKind::StatementAction: + case Action::Kind::StatementAction: StepStmt(); break; } // switch @@ -1178,7 +1193,7 @@ auto InterpProgram(const std::list& fs) -> int { const Expression* arg = Expression::MakeTupleLiteral(0, {}); const Expression* call_main = Expression::MakeCallExpression( 0, Expression::MakeIdentifierExpression(0, "main"), arg); - auto todo = Stack(Action::MakeExpressionAction(call_main)); + auto todo = Stack(global_arena->New(call_main)); auto* scope = global_arena->New(globals, std::list()); auto* frame = global_arena->New("top", Stack(scope), todo); state->stack = Stack(frame); @@ -1189,44 +1204,42 @@ auto InterpProgram(const std::list& fs) -> int { } while (state->stack.Count() > 1 || state->stack.Top()->todo.Count() > 1 || - state->stack.Top()->todo.Top()->tag() != ActionKind::ValAction) { + state->stack.Top()->todo.Top()->Tag() != Action::Kind::ValAction) { Step(); if (tracing_output) { PrintState(llvm::outs()); } } - const Value* v = state->stack.Top()->todo.Top()->GetValAction().val; + const Value* v = cast(*state->stack.Top()->todo.Top()).Val(); return cast(*v).Val(); } // Interpret an expression at compile-time. auto InterpExp(Env values, const Expression* e) -> const Value* { - auto todo = Stack(Action::MakeExpressionAction(e)); + auto todo = Stack(global_arena->New(e)); auto* scope = global_arena->New(values, std::list()); auto* frame = global_arena->New("InterpExp", Stack(scope), todo); state->stack = Stack(frame); while (state->stack.Count() > 1 || state->stack.Top()->todo.Count() > 1 || - state->stack.Top()->todo.Top()->tag() != ActionKind::ValAction) { + state->stack.Top()->todo.Top()->Tag() != Action::Kind::ValAction) { Step(); } - const Value* v = state->stack.Top()->todo.Top()->GetValAction().val; - return v; + return cast(*state->stack.Top()->todo.Top()).Val(); } // Interpret a pattern at compile-time. auto InterpPattern(Env values, const Pattern* p) -> const Value* { - auto todo = Stack(Action::MakePatternAction(p)); + auto todo = Stack(global_arena->New(p)); auto* scope = global_arena->New(values, std::list()); auto* frame = global_arena->New("InterpPattern", Stack(scope), todo); state->stack = Stack(frame); while (state->stack.Count() > 1 || state->stack.Top()->todo.Count() > 1 || - state->stack.Top()->todo.Top()->tag() != ActionKind::ValAction) { + state->stack.Top()->todo.Top()->Tag() != Action::Kind::ValAction) { Step(); } - const Value* v = state->stack.Top()->todo.Top()->GetValAction().val; - return v; + return cast(*state->stack.Top()->todo.Top()).Val(); } } // namespace Carbon