// 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_INTERPRETER_INTERPRETER_H_ #define EXECUTABLE_SEMANTICS_INTERPRETER_INTERPRETER_H_ #include #include #include #include "common/ostream.h" #include "executable_semantics/ast/declaration.h" #include "executable_semantics/ast/expression.h" #include "executable_semantics/ast/pattern.h" #include "executable_semantics/interpreter/frame.h" #include "executable_semantics/interpreter/heap.h" #include "executable_semantics/interpreter/stack.h" #include "executable_semantics/interpreter/value.h" #include "llvm/ADT/ArrayRef.h" namespace Carbon { using Env = Dictionary; class Interpreter { public: explicit Interpreter(Nonnull arena, bool trace) : arena_(arena), globals_(arena), heap_(arena), trace_(trace) {} // Interpret the whole program. auto InterpProgram(llvm::ArrayRef> fs, Nonnull call_main) -> int; // Interpret an expression at compile-time. auto InterpExp(Env values, Nonnull e) -> Nonnull; // Interpret a pattern at compile-time. auto InterpPattern(Env values, Nonnull p) -> Nonnull; // Attempts to match `v` against the pattern `p`. If matching succeeds, // returns the bindings of pattern variables to their matched values. auto PatternMatch(Nonnull p, Nonnull v, SourceLocation source_loc) -> std::optional; // Support TypeChecker allocating values on the heap. auto AllocateValue(Nonnull v) -> Address { return heap_.AllocateValue(v); } void InitEnv(const Declaration& d, Env* env); void PrintEnv(Env values, llvm::raw_ostream& out); private: // State transition functions // // The `Step*` family of functions implement state transitions in the // interpreter by executing a step of the Action at the top of the todo stack, // and then returning a Transition that specifies how `state.stack` should be // updated. `Transition` is a variant of several "transition types" // representing the different kinds of state transition. // Transition type which indicates that the current Action is now done. struct Done { // The value computed by the Action. Should always be nullopt for Statement // Actions, and never null for any other kind of Action. std::optional> result; }; // Transition type which spawns a new Action on the todo stack above the // current Action, and increments the current Action's position counter. struct Spawn { Nonnull child; }; // Transition type which spawns a new Action that replaces the current action // on the todo stack. struct Delegate { Nonnull delegate; }; // Transition type which keeps the current Action at the top of the stack, // and increments its position counter. struct RunAgain {}; // Transition type which unwinds the `todo` and `scopes` stacks until it // reaches a specified Action lower in the stack. struct UnwindTo { const Nonnull new_top; }; // Transition type which unwinds the entire current stack frame, and returns // a specified value to the caller. struct UnwindFunctionCall { Nonnull return_val; }; // Transition type which removes the current action from the top of the todo // stack, then creates a new stack frame which calls the specified function // with the specified arguments. struct CallFunction { Nonnull function; Nonnull args; SourceLocation source_loc; }; // Transition type which does nothing. // // TODO(geoffromer): This is a temporary placeholder during refactoring. All // uses of this type should be replaced with meaningful transitions. struct ManualTransition {}; using Transition = std::variant; // Visitor which implements the behavior associated with each transition type. class DoTransition; void Step(); // State transitions for expressions. auto StepExp() -> Transition; // State transitions for lvalues. auto StepLvalue() -> Transition; // State transitions for patterns. auto StepPattern() -> Transition; // State transition for statements. auto StepStmt() -> Transition; void InitGlobals(llvm::ArrayRef> fs); auto CurrentEnv() -> Env; auto GetFromEnv(SourceLocation source_loc, const std::string& name) -> Address; void DeallocateScope(Nonnull scope); void DeallocateLocals(Nonnull frame); auto CreateTuple(Nonnull act, Nonnull exp) -> Nonnull; auto CreateStruct(const std::vector& fields, const std::vector>& values) -> Nonnull; auto EvalPrim(Operator op, const std::vector>& args, SourceLocation source_loc) -> Nonnull; void PatternAssignment(Nonnull pat, Nonnull val, SourceLocation source_loc); void PrintState(llvm::raw_ostream& out); Nonnull arena_; // Globally-defined entities, such as functions, structs, or choices. Env globals_; Stack> stack_; Heap heap_; std::optional> program_value_; bool trace_; }; } // namespace Carbon #endif // EXECUTABLE_SEMANTICS_INTERPRETER_INTERPRETER_H_